You are viewing a plain text version of this content. The canonical link for it is here.
Posted to apreq-cvs@httpd.apache.org by jo...@apache.org on 2003/04/21 18:09:10 UTC

cvs commit: httpd-apreq-2/t tables.c

joes        2003/04/21 09:09:10

  Modified:    src      apreq.h apreq_params.c apreq_params.h
                        apreq_parsers.c apreq_tables.c apreq_tables.h
               t        tables.c
  Log:
  Table Iterator API simplified (back to using apr-style table_elts); table_keys() added.  apreq_params returns a table, and apreq_param returns a param again (instead of a char *) .
  
  Revision  Changes    Path
  1.14      +0 -3      httpd-apreq-2/src/apreq.h
  
  Index: apreq.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq.h,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- apreq.h	21 Apr 2003 04:29:46 -0000	1.13
  +++ apreq.h	21 Apr 2003 16:09:09 -0000	1.14
  @@ -77,9 +77,6 @@
   APREQ_DECLARE(apr_ssize_t) apreq_unescape(char *str);
   #define apreq_unescape(str) apreq_decode(str,str,strlen(str))
   
  -#define APREQ_ARRAY_VALUE(a,i) (*(apreq_value_t **)( (a)->elts + \
  -                                 ((a)->elt_size * (i)) ))
  -
   /**
    * Returns an RFC-822 formatted time string. Similar to ap_gm_timestr_822.
    *
  
  
  
  1.10      +14 -12    httpd-apreq-2/src/apreq_params.c
  
  Index: apreq_params.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_params.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- apreq_params.c	15 Apr 2003 09:36:11 -0000	1.9
  +++ apreq_params.c	21 Apr 2003 16:09:09 -0000	1.10
  @@ -148,23 +148,25 @@
       return req;
   }
   
  -
  -APREQ_DECLARE(const char *)apreq_param(const apreq_request_t *req, 
  -                                       const char *name)
  +APR_INLINE
  +APREQ_DECLARE(apreq_param_t *)apreq_param(const apreq_request_t *req, 
  +                                          const char *name)
   {
  -    const char *param = apreq_table_get(req->args, name);
  -    return  param ? param : 
  -        req->body ? apreq_table_get(req->body, name) : NULL;
  +    const char *arg = apreq_table_get(req->args, name);
  +
  +    if (arg)
  +        return UPGRADE(arg);
  +    else
  +        return req->body ? UPGRADE(apreq_table_get(req->body, name)) : NULL;
   }
   
   
  -APREQ_DECLARE(apr_array_header_t *) apreq_params(apr_pool_t *pool,
  -                                                 const apreq_request_t *req, 
  -                                                 const char *name)
  +APR_INLINE
  +APREQ_DECLARE(apreq_table_t *) apreq_params(apr_pool_t *pool,
  +                                            const apreq_request_t *req)
   {
  -    apr_array_header_t *arr = apreq_table_values(pool, req->args, name);
  -    apr_array_cat(arr, apreq_table_values(pool, req->body, name));
  -    return arr;
  +    return req->body ? apreq_table_overlay(pool, req->args, req->body) :
  +        apreq_table_copy(pool, req->args);
   }
   
   
  
  
  
  1.10      +7 -10     httpd-apreq-2/src/apreq_params.h
  
  Index: apreq_params.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_params.h,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- apreq_params.h	18 Apr 2003 20:15:50 -0000	1.9
  +++ apreq_params.h	21 Apr 2003 16:09:09 -0000	1.10
  @@ -122,12 +122,9 @@
    * @remark Also parses the request as necessary.
    */
   
  -APREQ_DECLARE(const char *) apreq_param(const apreq_request_t *req, 
  -                                        const char *name); 
  -
  -APREQ_DECLARE(const char *) apreq_arg(const apreq_request_t *req, 
  -                                      const char *name);
  -#define apreq_arg(req,k) apreq_table_get((req)->args, k)
  +APR_INLINE
  +APREQ_DECLARE(apreq_param_t *) apreq_param(const apreq_request_t *req, 
  +                                           const char *name); 
   
   /**
    * Returns all parameters for the requested key,
  @@ -138,10 +135,10 @@
    * @remark Also parses the request as necessary.
    */
   
  -APREQ_DECLARE(apr_array_header_t *) apreq_params(
  -                                            apr_pool_t *p,
  -                                            const apreq_request_t *req,
  -                                            const char *name);
  +APR_INLINE
  +APREQ_DECLARE(apreq_table_t *) apreq_params(apr_pool_t *p,
  +                                            const apreq_request_t *req);
  +
   
   /**
    * Returns a ", " -separated string containing all parameters 
  
  
  
  1.18      +2 -1      httpd-apreq-2/src/apreq_parsers.c
  
  Index: apreq_parsers.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_parsers.c,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- apreq_parsers.c	21 Apr 2003 04:29:46 -0000	1.17
  +++ apreq_parsers.c	21 Apr 2003 16:09:09 -0000	1.18
  @@ -920,7 +920,8 @@
               const apr_array_header_t *arr;
   
               arr = apreq_table_elts(req->body);
  -            param = apreq_value_to_param(APREQ_ARRAY_VALUE(arr,arr->nelts-1));
  +            param = apreq_value_to_param(*(apreq_value_t **)
  +                       (arr->elts + (arr->elt_size * arr->nelts-1)));
   
               switch (s) {
   
  
  
  
  1.18      +75 -121   httpd-apreq-2/src/apreq_tables.c
  
  Index: apreq_tables.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.c,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- apreq_tables.c	21 Apr 2003 04:45:23 -0000	1.17
  +++ apreq_tables.c	21 Apr 2003 16:09:09 -0000	1.18
  @@ -112,9 +112,8 @@
   #define UNLOCK_TREE(t,n)
   #define TREE_IS_LOCKED(t,n)
   
  -#define TF_MERGE     1
  -#define TF_BALANCE   2
  -#define TF_LOCK      4
  +#define TF_BALANCE   1
  +#define TF_LOCK      2
   
   
   struct apreq_table_t {
  @@ -125,13 +124,7 @@
       apreq_value_merge_t *merge;
   
       int                  root[TABLE_HASH_SIZE];
  -    unsigned long        locks; /* XXX ??? */
  -
       unsigned char        flags;
  -
  -#ifdef MAKE_TABLE_PROFILE
  -    int creator; /* XXX Is this the right type ??? */
  -#endif
   };
   
   
  @@ -522,18 +515,7 @@
       return arr->elts + (arr->elt_size * (arr->nelts - 1));
   }
   
  -#ifdef MAKE_TABLE_PROFILE
  -static apreq_table_entry_t *table_push(apreq_table_t *t)
  -{
  -    if (t->a.nelts == t->a.nalloc) {
  -        return NULL;
  -    }
  -    return (apreq_table_entry_t *) apr_array_push_noclear(&t->a);
  -}
  -#else /* MAKE_TABLE_PROFILE */
   #define table_push(t) ((apreq_table_entry_t *)apr_array_push_noclear(&(t)->a))
  -#endif /* MAKE_TABLE_PROFILE */
  -
   
   
   /********************* table ctors ********************/
  @@ -551,9 +533,6 @@
       apreq_table_t *t = apr_palloc(p, sizeof *t);
   
       make_array_core(&t->a, p, nelts, sizeof(apreq_table_entry_t), 0);
  -#ifdef MAKE_TABLE_PROFILE
  -    t->creator = __builtin_return_address(0);
  -#endif
   
       /* XXX: is memset(*,-1,*) portable ??? */
       memset(t->root, -1, TABLE_HASH_SIZE * sizeof(int));
  @@ -570,19 +549,10 @@
   {
       apreq_table_t *new = apr_palloc(p, sizeof *new);
   
  -#ifdef POOL_DEBUG
  -    /* we don't copy keys and values, so it's necessary that t->a.pool
  -     * have a life span at least as long as p
  -     */
  -    if (!apr_pool_is_ancestor(t->a.pool, p)) {
  -	fprintf(stderr, "copy_table: t's pool is not an ancestor of p\n");
  -	abort();
  -    }
  -#endif
  -
       make_array_core(&new->a, p, t->a.nalloc, sizeof(apreq_table_entry_t), 0);
       memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(apreq_table_entry_t));
       new->a.nelts = t->a.nelts;
  +    new->ghosts = t->ghosts;
       memcpy(new->root, t->root, TABLE_HASH_SIZE * sizeof(int));
       new->merge = t->merge;
       new->copy = t->copy;
  @@ -600,7 +570,7 @@
       for (idx = 0; idx < t->a.nelts; ++idx) {
           if (! DEAD(idx)) {
               const apreq_value_t *v = idx[o].val; 
  -            apr_table_addn(s, v->name, v->data);
  +            apr_table_add(s, v->name, v->data);
           }
       }
   
  @@ -633,7 +603,7 @@
   /********************* unary table ops ********************/
   
   
  -
  +APR_INLINE
   APREQ_DECLARE(void) apreq_table_clear(apreq_table_t *t)
   {
       memset(t->root,-1,TABLE_HASH_SIZE * sizeof(int));
  @@ -641,11 +611,19 @@
       t->ghosts = 0;
   }
   
  +APR_INLINE
   APREQ_DECLARE(int) apreq_table_nelts(const apreq_table_t *t)
   {
       return t->a.nelts - t->ghosts;
   }
   
  +APR_INLINE
  +APREQ_DECLARE(int) apreq_table_ghosts(apreq_table_t *t)
  +{
  +    return t->ghosts;
  +}
  +
  +APR_INLINE
   APREQ_DECLARE(apreq_value_copy_t *)apreq_table_copier(apreq_table_t *t, 
                                                         apreq_value_copy_t *c)
   {
  @@ -656,6 +634,7 @@
       return original;
   }
   
  +APR_INLINE
   APREQ_DECLARE(apreq_value_merge_t *)apreq_table_merger(apreq_table_t *t, 
                                                          apreq_value_merge_t *m)
   {
  @@ -690,57 +669,55 @@
   
   APREQ_DECLARE(apr_status_t) apreq_table_normalize(apreq_table_t *t)
   {
  -    if (t->flags & TF_MERGE) {
  -        apr_status_t status = APR_SUCCESS;
  -        int idx;
  -        apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -        apreq_value_t *a[APREQ_NELTS];
  -        apr_array_header_t arr = { t->a.pool, sizeof(apreq_value_t *), 0,
  -                                         APREQ_NELTS, (char *)a };
  -        
  -        for (idx = 0; idx < t->a.nelts; ++idx) {
  -            int j = idx[o].tree[NEXT];
  - 
  -            if ( j >= 0 && IN_FOREST(t,idx) ) {
  -                apreq_value_t *v;
  +    apr_status_t status = APR_SUCCESS;
  +    int idx;
  +    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  +    apreq_value_t *a[APREQ_NELTS];
  +    apr_array_header_t arr = { t->a.pool, sizeof(apreq_value_t *), 0,
  +                               APREQ_NELTS, (char *)a };
   
  -                LOCK_TABLE(t);
  -                arr.nelts = 0;
  +    if (t->merge == NULL)
  +        return APR_ENOTIMPL;
   
  -                *(const apreq_value_t **)apr_array_push(&arr) = idx[o].val;
  +    for (idx = 0; idx < t->a.nelts; ++idx) {
  +        int j = idx[o].tree[NEXT];
  + 
  +        if ( j >= 0 && IN_FOREST(t,idx) ) {
  +            apreq_value_t *v;
   
  -                for ( ; j >= 0; j = j[o].tree[NEXT]) {
  -                    *(const apreq_value_t **)apr_array_push(&arr) = j[o].val;
  -                    KILL(t,j);
  -                }
  +            LOCK_TABLE(t);
  +            arr.nelts = 0;
   
  -                v = t->merge(t->a.pool, &arr);
  +            *(const apreq_value_t **)apr_array_push(&arr) = idx[o].val;
   
  -                if (v == NULL) {
  -                    status = APR_EINCOMPLETE;
  -                    for (j = idx[o].tree[NEXT] ; j >= 0; 
  -                         j = j[o].tree[NEXT])
  -                        RESURRECT(t,j);
  -                }
  -                else {
  -                    v->name = idx[o].val->name;
  -                    idx[o].val = v;
  -                    idx[o].tree[NEXT] = -1;
  -                }
  +            for ( ; j >= 0; j = j[o].tree[NEXT]) {
  +                *(const apreq_value_t **)apr_array_push(&arr) = j[o].val;
  +                KILL(t,j);
  +            }
   
  -                UNLOCK_TABLE(t);
  +            v = t->merge(t->a.pool, &arr);
  +
  +            if (v == NULL) {
  +                status = APR_EINCOMPLETE;
  +                for (j = idx[o].tree[NEXT] ; j >= 0; 
  +                     j = j[o].tree[NEXT])
  +                    RESURRECT(t,j);
  +            }
  +            else {
  +                v->name = idx[o].val->name;
  +                idx[o].val = v;
  +                idx[o].tree[NEXT] = -1;
               }
  +
  +            UNLOCK_TABLE(t);
           }
  -        return status;
       }
  -    else
  -        return APR_EGENERAL;
  +    return status;
  +
   }
   
   static int bury_table_entries(apreq_table_t *t, apr_array_header_t *q)
   {
  -    /* EXPENSIVE: ~O(4 * t->a.nelts * q->nelts) */
  -
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
       int j, m, rv=0, *p = (int *)q->elts;
       register int n;
  @@ -759,6 +736,7 @@
       t->a.nelts -= q->nelts;
   
       /* reindex trees */
  +    /* EXPENSIVE: ~O(4 * t->a.nelts * q->nelts) */
   
   #define REINDEX(P) for (n=0; P > p[n]; ++n) ; P -= n; rv += n
   
  @@ -779,10 +757,6 @@
       return rv;
   }
   
  -APREQ_DECLARE(int) apreq_table_ghosts(apreq_table_t *t)
  -{
  -    return t->ghosts;
  -}
   
   APREQ_DECLARE(int) apreq_table_exorcise(apreq_table_t *t)
   {
  @@ -841,6 +815,23 @@
   }
   
   
  +APREQ_DECLARE(apr_array_header_t *) apreq_table_keys(apr_pool_t *p,
  +                                                     const apreq_table_t *t)
  +{
  +    int idx;
  +    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  +    apr_array_header_t *a = apr_array_make(p,t->a.nelts - t->ghosts,
  +                                           sizeof(char *));
  +
  +    for (idx = 0; idx < t->a.nelts; ++idx)
  +        if (IN_FOREST(t,idx))
  +            *(const char **)apr_array_push(a) = idx[o].key;
  +
  +    return a;
  +
  +}
  +
  +
   APREQ_DECLARE(apr_array_header_t *) apreq_table_values(apr_pool_t *p,
                                                          const apreq_table_t *t,
                                                          const char *key)
  @@ -867,10 +858,6 @@
   }
   
   
  -
  -/********************* table_set* & table_unset ********************/
  -
  -
   APREQ_DECLARE(void) apreq_table_set(apreq_table_t *t, const apreq_value_t *val)
   {
       const char *key = val->name;
  @@ -922,9 +909,6 @@
   }
   
   
  -
  -/********************* table_merge* *********************/
  -
   APREQ_DECLARE(apr_status_t) apreq_table_merge(apreq_table_t *t,
                                         const apreq_value_t *val)
   {
  @@ -963,12 +947,6 @@
           return val->status;
       }
       else {
  -
  -#ifdef POOL_DEBUG
  -    {
  -        /* Xxx */
  -    }
  -#endif
           e = table_push(t);
           e->key = val->name;
           e->val = val;
  @@ -980,8 +958,6 @@
   }
   
   
  -/********************* table_add* *********************/
  -
   APREQ_DECLARE(apr_status_t) apreq_table_add(apreq_table_t *t, 
                                               const apreq_value_t *val)
   {
  @@ -997,11 +973,6 @@
           int *root = &t->root[TABLE_HASH(key)];
           apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
   
  -#ifdef POOL_DEBUG
  -        {
  -        /* XXX */
  -        }
  -#endif
           elt->key = val->name;
           elt->val = val;
           elt->tree[NEXT] = -1;
  @@ -1077,23 +1048,6 @@
   {
       apreq_table_t *t = apr_palloc(p, sizeof *t);
   
  -#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,
  -		"overlay_tables: overlay's pool is not an ancestor of p\n");
  -	abort();
  -    }
  -    if (!apr_pool_is_ancestor(base->a.pool, p)) {
  -	fprintf(stderr,
  -		"overlay_tables: base's pool is not an ancestor of p\n");
  -	abort();
  -    }
  -#endif
  -
       t->a.pool = p;
       t->a.elt_size = sizeof(apreq_table_entry_t);
       t->copy = overlay->copy;
  @@ -1103,13 +1057,14 @@
   
       memcpy(t->root, overlay->root, TABLE_HASH_SIZE * sizeof(int));
   
  -    /* copy overlay array */
  -    t->a.elts = overlay->a.elts;
  -    t->a.nelts = overlay->a.nelts;
  -    t->a.nalloc = overlay->a.nelts;
  -    (void)apr_array_push(&t->a); /* induce copying */
  -    t->a.nelts--;
  +    t->a.elts = apr_palloc(p, t->a.elt_size *
  +                           (overlay->a.nalloc + base->a.nalloc));
   
  +    memcpy(t->a.elts, overlay->a.elts, overlay->a.elt_size * 
  +                                       overlay->a.nelts);
  +
  +    t->a.nelts = overlay->a.nelts;
  +    t->a.nalloc = overlay->a.nelts + base->a.nalloc;
   
       if (base->a.nelts) {
           if (t->a.nelts)
  @@ -1140,7 +1095,6 @@
       }
   
       apreq_table_cat(a, b);
  -    a->flags |= TF_MERGE;
   
       if (flags == APR_OVERLAP_TABLES_SET) {
           apreq_value_merge_t *f = a->merge;
  
  
  
  1.12      +29 -3     httpd-apreq-2/src/apreq_tables.h
  
  Index: apreq_tables.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.h,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- apreq_tables.h	21 Apr 2003 04:29:46 -0000	1.11
  +++ apreq_tables.h	21 Apr 2003 16:09:09 -0000	1.12
  @@ -134,12 +134,14 @@
    * Delete all of the elements from a table
    * @param t The table to clear
    */
  +APR_INLINE
   APREQ_DECLARE(void) apreq_table_clear(apreq_table_t *t);
   
   /**
    * Return the number of elements within the table.
    * @param t The table to clear
    */
  +APR_INLINE
   APREQ_DECLARE(int) apreq_table_nelts(const apreq_table_t *t);
   #define apreq_table_is_empty(t) ( apreq_table_nelts(t) == 0 )
   
  @@ -150,7 +152,7 @@
    *          a non-NULL value replaces the table's internal copier.
    * @return The original t->copy callback (prior to any assignment).
    */
  -
  +APR_INLINE
   APREQ_DECLARE(apreq_value_copy_t *) apreq_table_copier(apreq_table_t *t, 
                                              apreq_value_copy_t *c);
   
  @@ -161,7 +163,7 @@
    *          a non-NULL value replaces the table's internal merger.
    * @return The original t->merge callback (prior to any assignment).
    */
  -
  +APR_INLINE
   APREQ_DECLARE(apreq_value_merge_t *) apreq_table_merger(apreq_table_t *t,
                                              apreq_value_merge_t *m);
   
  @@ -196,6 +198,7 @@
    *
    * @param t Table.
    */
  +APR_INLINE
   APREQ_DECLARE(int) apreq_table_ghosts(apreq_table_t *t);
   
   /**
  @@ -236,6 +239,15 @@
                                                 const char *key);
   
   /**
  + * Return the keys (i.e. value names) in an (char *) array,
  + * preserving their original order.
  + * @param t Table.
  + * @param p Pool used to allocate the resulting array struct.
  + */
  +
  +APREQ_DECLARE(apr_array_header_t *) apreq_table_keys(apr_pool_t *p,
  +                                                     const apreq_table_t *t);
  +/**
    * Return the (unique) values in an (apreq_value_t *) array,
    * preserving their original order.
    * @param t Table.
  @@ -352,9 +364,23 @@
                                                   const unsigned flags);
   
   /** Iterator API */
  +
  +/**
  + *  NOTE: elt_size > sizeof(apreq_value_t *) !!!
  + *  So iterating over the values in the array must go something like this:
  + *
  + *  apr_array_header_t *arr = apreq_table_elts(t);
  + *  char *current, *end = arr->elts + arr->elt_size * arr->nelts;
  + *
  + *  for (current = arr->elts; current < end; current += arr->elt_size) {
  + *      apreq_value_t *v = *(apreq_value_t **)current;
  + *
  + *       ... do something with "v" ..
  + *  }
  + */
  +
   APR_INLINE
   APREQ_DECLARE(const apr_array_header_t *)apreq_table_elts(apreq_table_t *t);
  -
   
   /**
    * Declaration prototype for the iterator callback function of apr_table_do()
  
  
  
  1.5       +27 -17    httpd-apreq-2/t/tables.c
  
  Index: tables.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/t/tables.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- tables.c	21 Apr 2003 04:29:47 -0000	1.4
  +++ tables.c	21 Apr 2003 16:09:10 -0000	1.5
  @@ -181,52 +181,62 @@
       /* APR_OVERLAP_TABLES_SET had funky semantics, so we ignore it here */
       s = apreq_table_overlap(t1, t2, APR_OVERLAP_TABLES_MERGE);
       CuAssertIntEquals(tc, APR_SUCCESS, s);
  -    CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
  -    CuAssertIntEquals(tc, 3, apreq_table_ghosts(t1));
  -    CuAssertIntEquals(tc, 9, apreq_table_exorcise(t1));
   
  -    val = apreq_table_get(t1, "a");
  +    t2 = apreq_table_copy(p,t1);
  +    CuAssertIntEquals(tc, 7, apreq_table_nelts(t2));
  +    CuAssertIntEquals(tc, 3, apreq_table_ghosts(t2));
  +    CuAssertIntEquals(tc, 9, apreq_table_exorcise(t2));
  +    CuAssertIntEquals(tc, 0, apreq_table_ghosts(t2));
  +
  +    val = apreq_table_get(t2, "a");
       CuAssertStrEquals(tc, "0, 1",val);
  -    val = apreq_table_get(t1, "b");
  +    val = apreq_table_get(t2, "b");
       CuAssertStrEquals(tc, "2, 2.0, 2.",val);
  -    val = apreq_table_get(t1, "c");
  +    val = apreq_table_get(t2, "c");
       CuAssertStrEquals(tc, "3",val);
  -    val = apreq_table_get(t1, "d");
  +    val = apreq_table_get(t2, "d");
       CuAssertStrEquals(tc, "4",val);
  -    val = apreq_table_get(t1, "e");
  +    val = apreq_table_get(t2, "e");
       CuAssertStrEquals(tc, "5",val);
  -    val = apreq_table_get(t1, "f");
  +    val = apreq_table_get(t2, "f");
       CuAssertStrEquals(tc, "6",val);
  -    val = apreq_table_get(t1, "g");
  +    val = apreq_table_get(t2, "g");
       CuAssertStrEquals(tc, "7",val);
  +
   }
   
  +#define APREQ_ELT(a,i) (*(apreq_value_t **)((a)->elts + (i) * (a)->elt_size))
  +
   static void table_elts(CuTest *tc)
   {
       const char *val;
       const apreq_value_t *v;
       const apr_array_header_t *a;
   
  +    CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
  +    CuAssertIntEquals(tc, 3, apreq_table_ghosts(t1));
  +
       a = apreq_table_elts(t1);
   
       CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
       CuAssertIntEquals(tc, 0, apreq_table_ghosts(t1));
   
  -    v = APREQ_ARRAY_VALUE(a,0);
  +    v = APREQ_ELT(a,0);
       CuAssertStrEquals(tc,"0, 1", v->data);
  -    v = APREQ_ARRAY_VALUE(a,1);
  +    v = APREQ_ELT(a,1);
       CuAssertStrEquals(tc,"7", v->data);
  -    v = APREQ_ARRAY_VALUE(a,2);
  +    v = APREQ_ELT(a,2);
       CuAssertStrEquals(tc,"2, 2.0, 2.", v->data);
  -    v = APREQ_ARRAY_VALUE(a,3);
  +    v = APREQ_ELT(a,3);
       CuAssertStrEquals(tc,"3", v->data);
   
  -    v = APREQ_ARRAY_VALUE(a,a->nelts-1);
  +    v = APREQ_ELT(a,a->nelts-1);
       CuAssertStrEquals(tc,"6", v->data);
  -    v = APREQ_ARRAY_VALUE(a,a->nelts-2);
  +    v = APREQ_ELT(a,a->nelts-2);
       CuAssertStrEquals(tc,"5", v->data);
  -    v = APREQ_ARRAY_VALUE(a,a->nelts-3);
  +    v = APREQ_ELT(a,a->nelts-3);
       CuAssertStrEquals(tc,"4", v->data);
  +
   }