int rtl_dict_set(rtl_dict_t *d, const char *key, const char *val) { ssize_t i; unsigned hash; if (d == NULL || key == NULL) return -1; /* Compute hash for this key */ hash = rtl_dict_hash(key); /* Find if value is already in rtl_dict_t */ if (d->n > 0) { for (i = 0; i < d->size; i++) { if (d->key[i] == NULL) continue; if (hash == d->hash[i]) { /* Same hash value */ if (!strcmp(key, d->key[i])) { /*Same key */ /* Found a value: modify and return */ if (d->val[i] != NULL) free(d->val[i]); d->val[i] = (val ? strdup(val) : NULL); /* Value has been modified: return */ return 0; } } } } /* Add a new value */ /* See if rtl_dict_t needs to grow */ if (d->n == d->size) { /* Reached maximum size: reallocate rtl_dict_t */ if (dict_grow(d) != 0) return -1; } /* Insert key in the first empty slot. Start at d->n and wrap at * d->size. Because d->n < d->size this will necessarily * terminate. */ for (i = d->n; d->key[i];) { if (++i == d->size) i = 0; } /* Copy key */ d->key[i] = strdup(key); d->val[i] = (val ? strdup(val) : NULL); d->hash[i] = hash; d->n++; return 0; }
/* * Enter a key-value pair in a dictionary. * See idict.h for the possible return values. */ int dict_put(ref * pdref /* t_dictionary */ , const ref * pkey, const ref * pvalue, dict_stack_t *pds) { dict *pdict = pdref->value.pdict; gs_ref_memory_t *mem = dict_memory(pdict); gs_memory_t *pmem = dict_mem(pdict); int rcode = 0; int code; ref *pvslot, kname; /* Check the value. */ store_check_dest(pdref, pvalue); top:if ((code = dict_find(pdref, pkey, &pvslot)) <= 0) { /* not found *//* Check for overflow */ uint index; switch (code) { case 0: break; case gs_error_dictfull: if (!pmem->gs_lib_ctx->dict_auto_expand) return_error(gs_error_dictfull); code = dict_grow(pdref, pds); if (code < 0) return code; goto top; /* keep things simple */ default: /* gs_error_typecheck */ return code; } index = pvslot - pdict->values.value.refs; /* If the key is a string, convert it to a name. */ if (r_has_type(pkey, t_string)) { int code; if (!r_has_attr(pkey, a_read)) return_error(gs_error_invalidaccess); code = name_from_string(pmem, pkey, &kname); if (code < 0) return code; pkey = &kname; } if (dict_is_packed(pdict)) { ref_packed *kp; if (!r_has_type(pkey, t_name) || name_index(pmem, pkey) > packed_name_max_index ) { /* Change to unpacked representation. */ int code = dict_unpack(pdref, pds); if (code < 0) return code; goto top; } kp = pdict->keys.value.writable_packed + index; if (ref_must_save_in(mem, &pdict->keys)) { /* See initial comment for why it is safe */ /* not to save the change if the keys */ /* array itself is new. */ ref_do_save_in(mem, &pdict->keys, kp, "dict_put(key)"); } *kp = pt_tag(pt_literal_name) + name_index(pmem, pkey); } else { ref *kp = pdict->keys.value.refs + index; if_debug2m('d', (const gs_memory_t *)mem, "[d]0x%lx: fill key at 0x%lx\n", (ulong) pdict, (ulong) kp); store_check_dest(pdref, pkey); ref_assign_old_in(mem, &pdict->keys, kp, pkey, "dict_put(key)"); /* set key of pair */ } ref_save_in(mem, pdref, &pdict->count, "dict_put(count)"); pdict->count.value.intval++; /* If the key is a name, update its 1-element cache. */ if (r_has_type(pkey, t_name)) { name *pname = pkey->value.pname; if (pname->pvalue == pv_no_defn && CAN_SET_PVALUE_CACHE(pds, pdref, mem) ) { /* Set the cache. */ if_debug0m('d', (const gs_memory_t *)mem, "[d]set cache\n"); pname->pvalue = pvslot; } else { /* The cache can't be used. */ if_debug0m('d', (const gs_memory_t *)mem, "[d]no cache\n"); pname->pvalue = pv_other; } } rcode = 1; } if_debug8m('d', (const gs_memory_t *)mem, "[d]0x%lx: put key 0x%lx 0x%lx\n value at 0x%lx: old 0x%lx 0x%lx, new 0x%lx 0x%lx\n", (ulong) pdref->value.pdict, ((const ulong *)pkey)[0], ((const ulong *)pkey)[1], (ulong) pvslot, ((const ulong *)pvslot)[0], ((const ulong *)pvslot)[1], ((const ulong *)pvalue)[0], ((const ulong *)pvalue)[1]); ref_assign_old_in(mem, &pdref->value.pdict->values, pvslot, pvalue, "dict_put(value)"); return rcode; }