Return-Path: Delivered-To: apmail-apr-cvs-archive@apr.apache.org Received: (qmail 10382 invoked by uid 500); 9 Nov 2001 23:11:04 -0000 Mailing-List: contact cvs-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Reply-To: dev@apr.apache.org Delivered-To: mailing list cvs@apr.apache.org Received: (qmail 10371 invoked from network); 9 Nov 2001 23:11:04 -0000 Date: 9 Nov 2001 22:59:00 -0000 Message-ID: <20011109225900.622.qmail@icarus.apache.org> From: ianh@apache.org To: apr-cvs@apache.org Subject: cvs commit: apr/tables apr_hash.c X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N ianh 01/11/09 14:59:00 Modified: . CHANGES include apr_hash.h tables apr_hash.c Log: Add 2 new hash functions. apr_hash_copy & apr_hash_merge. the merge function allows for a callback if both hash's have the same value this changes the overlay function so that it calls the 'merge' Submitted by: Brian Pane Reviewed by: Ian Holsman Revision Changes Path 1.177 +4 -0 apr/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/apr/CHANGES,v retrieving revision 1.176 retrieving revision 1.177 diff -u -r1.176 -r1.177 --- CHANGES 2001/10/29 14:54:19 1.176 +++ CHANGES 2001/11/09 22:59:00 1.177 @@ -1,5 +1,9 @@ Changes with APR b1 + *) New functions apr_hash_[merge|copy], change to overlay fn + so that it calls merge, which does a inline iteration instead + of calling the iterator function. [Brian Pan array) * (orig->max + 1) + + sizeof(apr_hash_entry_t) * orig->count); + ht->pool = pool; + ht->count = orig->count; + ht->max = orig->max; + ht->array = (apr_hash_entry_t **)((char *)ht + sizeof(apr_hash_t)); + + new_vals = (apr_hash_entry_t *)((char *)(ht) + sizeof(apr_hash_t) + + sizeof(*ht->array) * (orig->max + 1)); + j = 0; + for (i = 0; i <= ht->max; i++) { + apr_hash_entry_t **new_entry = &(ht->array[i]); + apr_hash_entry_t *orig_entry = orig->array[i]; + while (orig_entry) { + *new_entry = &new_vals[j++]; + (*new_entry)->hash = orig_entry->hash; + (*new_entry)->key = orig_entry->key; + (*new_entry)->klen = orig_entry->klen; + (*new_entry)->val = orig_entry->val; + new_entry = &((*new_entry)->next); + orig_entry = orig_entry->next; + } + *new_entry = NULL; + } + return ht; +} + APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht, const void *key, apr_ssize_t klen) @@ -335,10 +370,25 @@ const apr_hash_t *overlay, const apr_hash_t *base) { + return apr_hash_merge(p, overlay, base, NULL, NULL); +} + +APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p, + const apr_hash_t *overlay, + const apr_hash_t *base, + void * (*merger)(apr_pool_t *p, + const void *key, + apr_ssize_t klen, + const void *h1_val, + const void *h2_val, + const void *data), + const void *data) +{ apr_hash_t *res; - apr_hash_index_t *hi; apr_hash_entry_t *new_vals; - int i,j; + apr_hash_entry_t *iter; + apr_hash_entry_t *ent; + int i,j,k; #ifdef POOL_DEBUG /* we don't copy keys and values, so it's necessary that @@ -361,27 +411,55 @@ res->pool = p; res->count = base->count; res->max = (overlay->max > base->max) ? overlay->max : base->max; + if (base->count + overlay->count > res->max) { + res->max = res->max * 2 + 1; + } res->array = alloc_array(res, res->max); - new_vals = apr_palloc(p, sizeof(apr_hash_entry_t) * res->count); + if (base->count + overlay->count) { + new_vals = apr_palloc(p, sizeof(apr_hash_entry_t) * + (base->count + overlay->count)); + } j = 0; - for (hi = apr_hash_first(NULL, (apr_hash_t*)base); hi; hi = apr_hash_next(hi)) { - i = hi->this->hash & res->max; - - new_vals[j].klen = hi->this->klen; - new_vals[j].key = hi->this->key; - new_vals[j].val = hi->this->val; - new_vals[j].hash = hi->this->hash; - new_vals[j].next = res->array[i]; - res->array[i] = &new_vals[j]; - j++; + for (k = 0; k <= base->max; k++) { + for (iter = base->array[k]; iter; iter = iter->next) { + i = iter->hash & res->max; + new_vals[j].klen = iter->klen; + new_vals[j].key = iter->key; + new_vals[j].val = iter->val; + new_vals[j].hash = iter->hash; + new_vals[j].next = res->array[i]; + res->array[i] = &new_vals[j]; + j++; + } } - /* can't simply copy the stuff over, need to set each one so as to - * increment the counts/array properly - */ - for (hi = apr_hash_first(NULL, (apr_hash_t*)overlay); hi; - hi = apr_hash_next(hi)) { - apr_hash_set(res, hi->this->key, hi->this->klen, hi->this->val); + for (k = 0; k < overlay->max; k++) { + for (iter = overlay->array[k]; iter; iter = iter->next) { + i = iter->hash & res->max; + for (ent = res->array[i]; ent; ent = ent->next) { + if ((ent->klen == iter->klen) && + (memcmp(ent->key, iter->key, iter->klen) == 0)) { + if (merger) { + ent->val = (*merger)(p, iter->key, iter->klen, + iter->val, ent->val, data); + } + else { + ent->val = iter->val; + } + break; + } + } + if (!ent) { + new_vals[j].klen = iter->klen; + new_vals[j].key = iter->key; + new_vals[j].val = iter->val; + new_vals[j].hash = iter->hash; + new_vals[j].next = res->array[i]; + res->array[i] = &new_vals[j]; + res->count++; + j++; + } + } } return res; }