You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by je...@apache.org on 2001/07/19 05:45:33 UTC
cvs commit: apr/test testhash.c Makefile.in
jerenkrantz 01/07/18 20:45:33
Modified: include apr_hash.h
tables apr_hash.c
test Makefile.in
Added: test testhash.c
Log:
Add apr_hash_overlay function in the spirit of apr_table_overlay.
Also add testhash.c program to test the proper operation of the hash
functions.
I (Justin) did the following things to Ian's patch as posted:
- Reformatted to fit APR coding style.
- Fixed comment in apr_hash.h (swapped base and overlay)
- Also reformat the test/Makefile.in while I'm at it
Submitted by: Ian Holsman <ia...@cnet.com>
Reviewed by: Justin Erenkrantz, Brian Pane <bp...@pacbell.net>
Revision Changes Path
1.26 +13 -0 apr/include/apr_hash.h
Index: apr_hash.h
===================================================================
RCS file: /home/cvs/apr/include/apr_hash.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- apr_hash.h 2001/05/16 05:30:51 1.25
+++ apr_hash.h 2001/07/19 03:45:33 1.26
@@ -181,6 +181,19 @@
*/
APR_DECLARE(int) apr_hash_count(apr_hash_t *ht);
+/**
+ * Merge two hash tables into one new hash table. The values of the overlay
+ * hash override the values of the base if both have the same key.
+ * @param p The pool to use for the new hash table
+ * @param overlay The table to add to the initial table
+ * @param base The table that represents the initial values of the new table
+ * @return A new hash table containing all of the data from the two passed in
+ * @deffunc apr_hash_t *apr_hash_overlay(apr_pool_t *p, const apr_table_t *over
+lay, const apr_table_t *base);
+ */
+APR_DECLARE(apr_hash_t *) apr_hash_overlay(apr_pool_t *p,
+ const apr_hash_t *overlay,
+ const apr_hash_t *base);
#ifdef __cplusplus
}
1.20 +55 -0 apr/tables/apr_hash.c
Index: apr_hash.c
===================================================================
RCS file: /home/cvs/apr/tables/apr_hash.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- apr_hash.c 2001/05/16 05:30:52 1.19
+++ apr_hash.c 2001/07/19 03:45:33 1.20
@@ -325,3 +325,58 @@
{
return ht->count;
}
+
+APR_DECLARE(apr_hash_t*) apr_hash_overlay(apr_pool_t *p,
+ const apr_hash_t *overlay,
+ const apr_hash_t *base)
+{
+ apr_hash_t *res;
+ apr_hash_index_t *hi;
+ apr_hash_entry_t *new_vals;
+ int i,j;
+
+#ifdef POOL_DEBUG
+ /* we don't copy keys and values, so it's necessary that
+ * overlay->a.pool and base->a.pool have a life span at least
+ * as long as p
+ */
+ if (!apr_pool_is_ancestor(overlay->a.pool, p)) {
+ fprintf(stderr,
+ "apr_hash_overlay: overlay's pool is not an ancestor of p\n");
+ abort();
+ }
+ if (!apr_pool_is_ancestor(base->a.pool, p)) {
+ fprintf(stderr,
+ "apr_hash_overlay: base's pool is not an ancestor of p\n");
+ abort();
+ }
+#endif
+
+ res = apr_palloc(p, sizeof(apr_hash_t));
+ res->pool = p;
+ res->count = base->count;
+ res->max = (overlay->max > base->max) ? overlay->max : base->max;
+ res->array = alloc_array(res, res->max);
+ new_vals = apr_palloc(p, sizeof(apr_hash_entry_t) * res->count);
+ j = 0;
+ for (hi = apr_hash_first((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++;
+ }
+
+ /* 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((apr_hash_t*)overlay); hi;
+ hi = apr_hash_next(hi)) {
+ apr_hash_set(res, hi->this->key, hi->this->klen, hi->this->val);
+ }
+ return res;
+}
1.60 +10 -6 apr/test/Makefile.in
Index: Makefile.in
===================================================================
RCS file: /home/cvs/apr/test/Makefile.in,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -r1.59 -r1.60
--- Makefile.in 2001/07/07 13:03:46 1.59
+++ Makefile.in 2001/07/19 03:45:33 1.60
@@ -19,13 +19,14 @@
testpipe@EXEEXT@ \
testoc@EXEEXT@ \
testuuid@EXEEXT@ \
- testsockopt@EXEEXT@ \
- testipsub@EXEEXT@ \
- testmd5@EXEEXT@ \
- testpoll@EXEEXT@ \
- testmem@EXEEXT@ \
+ testsockopt@EXEEXT@ \
+ testipsub@EXEEXT@ \
+ testmd5@EXEEXT@ \
+ testpoll@EXEEXT@ \
+ testmem@EXEEXT@ \
+ testhash@EXEEXT@ \
occhild@EXEEXT@ \
- teststr@EXEEXT@
+ teststr@EXEEXT@
TARGETS = $(PROGRAMS)
@@ -122,6 +123,9 @@
testmem@EXEEXT@: testmem.lo $(LOCAL_LIBS)
$(LINK) testmem.lo $(LOCAL_LIBS) $(ALL_LIBS)
+
+testhash@EXEEXT@: testhash.lo $(LOCAL_LIBS)
+ $(LINK) testhash.lo $(LOCAL_LIBS) $(ALL_LIBS)
teststr@EXEEXT@: teststr.lo $(LOCAL_LIBS)
$(LINK) teststr.lo $(LOCAL_LIBS) $(ALL_LIBS)
1.1 apr/test/testhash.c
Index: testhash.c
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "apr.h"
#include "apr_strings.h"
#include "apr_general.h"
#include "apr_pools.h"
#include "apr_hash.h"
#if APR_HAVE_STDIO_H
#include <stdio.h>
#endif
#if APR_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if APR_HAVE_STRING_H
#include <string.h>
#endif
static void dump_hash(apr_hash_t *h)
{
apr_hash_index_t *hi;
char *val, *key;
int len;
int i = 0;
for (hi = apr_hash_first(h); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi,(void*) &key, &len,(void*) &val);
fprintf(stdout, "Key %s (%d) Value %s\n",key,len,val);
i++;
}
if (i != apr_hash_count(h))
fprintf(stderr, "ERROR: #entries (%d) does not match count (%d)\n",
i, apr_hash_count(h));
else
fprintf(stdout, "#entries %d \n", i);
}
static void sum_hash(apr_hash_t *h, int *pcount, int *keySum, int *valSum)
{
apr_hash_index_t *hi;
void *val, *key;
int count = 0;
*keySum = 0;
*valSum = 0;
*pcount = 0;
for (hi = apr_hash_first(h); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi, (void*)&key, NULL, &val);
*valSum += *(int *)val;
*keySum += *(int *)key;
count++;
}
*pcount=count;
}
int main(int argc, const char *const argv[])
{
apr_pool_t *cntxt;
apr_hash_t *h, *h2, *h3, *h4;
int i, j, *val, *key;
char *result;
int sumKeys, sumVal, trySumKey, trySumVal;
apr_initialize();
atexit(apr_terminate);
apr_pool_create(&cntxt, NULL);
/* table defaults */
h = apr_hash_make(cntxt);
if (h == NULL) {
fprintf(stderr, "ERROR: can not allocate HASH!\n");
exit(-1);
}
apr_hash_set(h, "OVERWRITE", APR_HASH_KEY_STRING, "should not see this");
apr_hash_set(h, "FOO3", APR_HASH_KEY_STRING, "bar3");
apr_hash_set(h, "FOO3", APR_HASH_KEY_STRING, "bar3");
apr_hash_set(h, "FOO1", APR_HASH_KEY_STRING, "bar1");
apr_hash_set(h, "FOO2", APR_HASH_KEY_STRING, "bar2");
apr_hash_set(h, "FOO4", APR_HASH_KEY_STRING, "bar4");
apr_hash_set(h, "SAME1", APR_HASH_KEY_STRING, "same");
apr_hash_set(h, "SAME2", APR_HASH_KEY_STRING, "same");
apr_hash_set(h, "OVERWRITE", APR_HASH_KEY_STRING, "Overwrite key");
result = apr_hash_get(h, "FOO2", APR_HASH_KEY_STRING);
if (strcmp(result, "bar2"))
fprintf(stderr, "ERROR:apr_hash_get FOO2 = %s (should be bar2)\n",
result);
result = apr_hash_get(h, "SAME2", APR_HASH_KEY_STRING);
if (strcmp(result, "same"))
fprintf(stderr, "ERROR:apr_hash_get SAME2 = %s (should be same)\n",
result);
result = apr_hash_get(h, "OVERWRITE", APR_HASH_KEY_STRING);
if (strcmp(result, "Overwrite key"))
fprintf(stderr,
"ERROR:apr_hash_get OVERWRITE = %s (should be 'Overwrite key')\n",
result);
result = apr_hash_get(h, "NOTTHERE", APR_HASH_KEY_STRING);
if (result)
fprintf(stderr, "ERROR:apr_hash_get NOTTHERE = %s (should be NULL)\n",
result);
result=apr_hash_get(h, "FOO3", APR_HASH_KEY_STRING);
if (strcmp(result, "bar3"))
fprintf(stderr, "ERROR:apr_hash_get FOO3 = %s (should be bar3)\n",
result);
dump_hash(h);
h2 =apr_hash_make(cntxt);
if (h2 == NULL) {
fprintf(stderr, "ERROR: can not allocate HASH!\n");
exit(-1);
}
sumKeys = 0;
sumVal = 0;
trySumKey = 0;
trySumVal = 0;
for (i = 0; i < 100; i++) {
j = i * 10 + 1;
sumKeys += j;
sumVal += i;
key = apr_palloc(cntxt, sizeof(int));
*key = j;
val = apr_palloc(cntxt, sizeof(int));
*val = i;
apr_hash_set(h2, key, sizeof(int), val);
}
sum_hash(h2, &i, &trySumKey, &trySumVal);
if (i==100) {
fprintf(stdout, "All keys accounted for\n");
} else {
fprintf(stderr, "ERROR: Only got %d (out of 100)\n",i);
}
if (trySumVal != sumVal) {
fprintf(stderr, "ERROR:Values don't add up Got %d expected %d\n",
trySumVal, sumVal);
}
if (trySumKey != sumKeys) {
fprintf(stderr, "ERROR:Keys don't add up Got %d expected %d\n",
trySumKey, sumKeys);
}
j=891;
apr_hash_set(h2, &j, sizeof(int), NULL);
if (apr_hash_get(h2, &j, sizeof(int))) {
fprintf(stderr, "ERROR: Delete not working\n");
} else {
fprintf(stdout, "Delete working\n");
}
sum_hash(h2, &i, &trySumKey, &trySumVal);
sumKeys -= 891;
sumVal -= 89;
if (i==99) {
fprintf(stdout, "All keys accounted for.. Delete OK\n");
} else {
fprintf(stderr, "Only got %d (out of 99) Delete Not OK\n", i);
}
if (trySumVal != sumVal) {
fprintf(stderr, "ERROR:Values don't add up Got %d expected %d\n",
trySumVal, sumVal);
}
if (trySumKey != sumKeys) {
fprintf(stderr, "ERROR:Keys don't add up Got %d expected %d\n",
trySumKey, sumKeys);
}
/* test overlay */
h3 = apr_hash_make(cntxt);
/* test with blank hash tables */
h4 = apr_hash_overlay(cntxt, h3, h);
if (apr_hash_count(h4) != apr_hash_count(h)) {
fprintf(stderr,
"ERROR: overlay not working with blank overlay as overlay\n");
dump_hash(h4);
}
h4 = apr_hash_overlay(cntxt, h, h3);
if (apr_hash_count(h4) != apr_hash_count(h)) {
fprintf(stderr,
"ERROR: overlay not working with blank overlay as base\n");
dump_hash(h4);
}
h4 = apr_hash_overlay(cntxt, h, h2);
if (apr_hash_count(h4) != (apr_hash_count(h) + apr_hash_count(h2)))
fprintf(stderr,
"ERROR: overlay not working when overlaying 2 unique hashs\n");
h4 = apr_hash_overlay(cntxt, h, h);
if (apr_hash_count(h4) != apr_hash_count(h)) {
fprintf(stderr,
"ERROR: overlay not working when overlaying same hash\n");
dump_hash(h4);
}
result = apr_hash_get(h4, "FOO2", APR_HASH_KEY_STRING);
if (strcmp(result, "bar2"))
fprintf(stderr, "ERROR:apr_hash_get FOO2 = %s (should be bar2)\n",
result);
result = apr_hash_get(h4, "SAME2", APR_HASH_KEY_STRING);
if (strcmp(result, "same"))
fprintf(stderr, "ERROR:apr_hash_get SAME2 = %s (should be same)\n",
result);
result = apr_hash_get(h4, "OVERWRITE", APR_HASH_KEY_STRING);
if (strcmp(result, "Overwrite key"))
fprintf(stderr,
"ERROR:apr_hash_get OVERWRITE = %s (should be 'Overwrite key')\n",
result);
result = apr_hash_get(h4, "NOTTHERE", APR_HASH_KEY_STRING);
if (result)
fprintf(stderr, "ERROR:apr_hash_get NOTTHERE = %s (should be NULL)\n",
result);
result = apr_hash_get(h4, "FOO3", APR_HASH_KEY_STRING);
if (strcmp(result, "bar3"))
fprintf(stderr, "ERROR:apr_hash_get FOO3 = %s (should be bar3)\n",
result);
apr_hash_set(h4, "FOO3", sizeof(int), NULL);
result = apr_hash_get(h4, "FOO3", APR_HASH_KEY_STRING);
if (result)
fprintf(stderr,
"ERROR:apr_hash_get FOO3 = %s (should be NULL, we just deleted it!)\n",
result);
return 0;
}