/* Given a key, remove the corresponding key:value pair from a set. * Abort if the key is not in the set. */ void ncptl_set_remove (NCPTL_SET *set, void *key) { if (set->chains) { NCPTL_QUEUE *chain = set->chains[set_hash_key(set, key)]; NCPTL_SET_ELT *chaindata = (NCPTL_SET_ELT *) ncptl_queue_contents (chain, 0); ncptl_int numelts = ncptl_queue_length(chain); ncptl_int i; for (i=0; i<numelts; i++) if (!memcmp(key, chaindata[i].key, set->keybytes)) { /* Move the element to the head of the queue then pop the queue. */ if (i > 0) { NCPTL_SET_ELT firstelt = chaindata[0]; chaindata[0] = chaindata[i]; chaindata[i] = firstelt; } ncptl_free (chaindata[0].key); ncptl_free (chaindata[0].value); (void) ncptl_queue_pop (chain); set->numelts--; return; } } ncptl_fatal ("internal error -- ncptl_set_remove() tried to remove a nonexistent key"); }
/* Given a key, return a pointer to the corresponding value or NULL if * the key is not found. */ void *ncptl_set_find (NCPTL_SET *set, void *key) { NCPTL_QUEUE *chain; /* Pointer to the bucket chain containing KEY */ NCPTL_SET_ELT *chaindata; /* Array of buckets */ ncptl_int i; /* If the set is empty there's no point searching it. */ if (!set->chains) return NULL; /* Linear-search the bucket chain. */ chain = set->chains[set_hash_key(set, key)]; chaindata = (NCPTL_SET_ELT *) ncptl_queue_contents (chain, 0); for (i=0; i<ncptl_queue_length(chain); i++) if (!memcmp(key, chaindata[i].key, set->keybytes)) { if (i > 0) { /* For performance, bubble up the element we just found. */ NCPTL_SET_ELT prevelt = chaindata[i-1]; chaindata[i-1] = chaindata[i]; chaindata[i] = prevelt; return chaindata[i-1].value; } else return chaindata[i].value; } return NULL; }
void set_normal_type_instance_attribute(VALUE obj, VALUE attr, VALUE v) { VALUE ut; HASH_OBJECT_ENTRY *e; size_t n; ut = NORMAL_TYPE_INSTANCE_TYPE(obj); e = get_hash_key(NGS_TYPE_FIELDS(ut), attr); if(e) { n = GET_INT(e->val); } else { n = OBJ_LEN(NGS_TYPE_FIELDS(ut)); set_hash_key(NGS_TYPE_FIELDS(ut), attr, MAKE_INT(n)); } // TODO: more optimized while(OBJ_LEN(NORMAL_TYPE_INSTANCE_FIELDS(obj)) < n) { array_push(NORMAL_TYPE_INSTANCE_FIELDS(obj), (VALUE){.num = V_UNDEF}); }
/* Insert a copy of a key:value pair into a set. Abort if the key is * already in the set. */ void ncptl_set_insert (NCPTL_SET *set, void *key, void *value) { NCPTL_QUEUE *chain; /* Bucket chain in which to insert the key:value pair */ NCPTL_SET_ELT newelt; /* key:value pair to insert */ if (ncptl_set_find (set, key)) ncptl_fatal ("internal error -- ncptl_set_insert() inserted the same key twice"); if (!set->chains) { /* This is the first invocation since set creation/emptying -- * allocate all of the bucket chains. */ ncptl_int i; set->chains = (NCPTL_QUEUE **) ncptl_malloc (set->numchains*sizeof(NCPTL_QUEUE *), 0); for (i=0; i<set->numchains; i++) set->chains[i] = ncptl_queue_init (sizeof(NCPTL_SET_ELT)); } chain = set->chains[set_hash_key(set, key)]; newelt.key = ncptl_malloc (set->keybytes, 0); memcpy (newelt.key, key, set->keybytes); newelt.value = ncptl_malloc (set->valuebytes, 0); memcpy (newelt.value, value, set->valuebytes); ncptl_queue_push (chain, &newelt); set->numelts++; }