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;
  }