jwoolley 2002/06/28 15:45:38
Modified: . CHANGES
include apr_tables.h
tables apr_tables.c
Log:
A compromise for now: changing the return type of apr_table_do() and
apr_table_vdo() to return int instead of void so that the caller can
know whether or not any of the iterations trigged an "early return".
However, I've left the wacky old semantics of _vdo for a while. This
solves my immediate need at least.
Revision Changes Path
1.300 +4 -0 apr/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apr/CHANGES,v
retrieving revision 1.299
retrieving revision 1.300
diff -u -d -u -r1.299 -r1.300
--- CHANGES 28 Jun 2002 11:38:50 -0000 1.299
+++ CHANGES 28 Jun 2002 22:45:37 -0000 1.300
@@ -1,5 +1,9 @@
Changes with APR b1
+ *) apr_table_do() and apr_table_vdo() now return an int rather than
+ void to indicate whether or not any of its iterations returned 0.
+ [Cliff Woolley]
+
*) Fix the definition of union semun so that it is valid on systems
where sizeof(long) != sizeof(int). This resolves a hang on
HP-UX/Itanium.
1.30 +9 -4 apr/include/apr_tables.h
Index: apr_tables.h
===================================================================
RCS file: /home/cvs/apr/include/apr_tables.h,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -u -r1.29 -r1.30
--- apr_tables.h 28 Jun 2002 14:04:36 -0000 1.29
+++ apr_tables.h 28 Jun 2002 22:45:38 -0000 1.30
@@ -374,10 +374,12 @@
* @param ... The vararg. If this is NULL, then all elements in the table are
* run through the function, otherwise only those whose key matches
* are run.
+ * @return FALSE if one of the comp() iterations returned zero; TRUE if all
+ * iterations returned non-zero
* @see apr_table_do_callback_fn_t
*/
-APR_DECLARE_NONSTD(void) apr_table_do(apr_table_do_callback_fn_t *comp,
- void *rec, const apr_table_t *t, ...);
+APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp,
+ void *rec, const apr_table_t *t, ...);
/**
* Iterate over a table running the provided function once for every
@@ -391,9 +393,12 @@
* @param vp The vararg table. If this is NULL, then all elements in the
* table are run through the function, otherwise only those
* whose key matches are run.
+ * @return FALSE if one of the comp() iterations returned zero; TRUE if all
+ * iterations returned non-zero
+ * @see apr_table_do_callback_fn_t
*/
-APR_DECLARE(void) apr_table_vdo(apr_table_do_callback_fn_t *comp,
- void *rec, const apr_table_t *t, va_list);
+APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp,
+ void *rec, const apr_table_t *t, va_list);
/** flag for overlap to use apr_table_setn */
#define APR_OVERLAP_TABLES_SET (0)
1.28 +47 -7 apr/tables/apr_tables.c
Index: apr_tables.c
===================================================================
RCS file: /home/cvs/apr/tables/apr_tables.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -u -r1.27 -r1.28
--- apr_tables.c 28 Jun 2002 14:04:36 -0000 1.27
+++ apr_tables.c 28 Jun 2002 22:45:38 -0000 1.28
@@ -695,21 +695,56 @@
*
* So to make mod_file_cache easier to maintain, it's a good thing
*/
-APR_DECLARE_NONSTD(void) apr_table_do(apr_table_do_callback_fn_t *comp,
- void *rec, const apr_table_t *t, ...)
+APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp,
+ void *rec, const apr_table_t *t, ...)
{
+ int rv;
+
va_list vp;
va_start(vp, t);
- apr_table_vdo(comp, rec, t, vp);
- va_end(vp);
+ rv = apr_table_vdo(comp, rec, t, vp);
+ va_end(vp);
+
+ return rv;
}
-APR_DECLARE(void) apr_table_vdo(apr_table_do_callback_fn_t *comp,
- void *rec, const apr_table_t *t, va_list vp)
+/* XXX: do the semantics of this routine make any sense? Right now,
+ * if the caller passed in a non-empty va_list of keys to search for,
+ * the "early termination" facility only terminates on *that* key; other
+ * keys will continue to process. Note that this only has any effect
+ * at all if there are multiple entries in the table with the same key,
+ * otherwise the called function can never effectively early-terminate
+ * this function, as the zero return value is effectively ignored.
+ *
+ * Note also that this behavior is at odds with the behavior seen if an
+ * empty va_list is passed in -- in that case, a zero return value terminates
+ * the entire apr_table_vdo (which is what I think should happen in
+ * both cases).
+ *
+ * If nobody objects soon, I'm going to change the order of the nested
+ * loops in this function so that any zero return value from the (*comp)
+ * function will cause a full termination of apr_table_vdo. I'm hesitant
+ * at the moment because these (funky) semantics have been around for a
+ * very long time, and although Apache doesn't seem to use them at all,
+ * some third-party vendor might. I can only think of one possible reason
+ * the existing semantics would make any sense, and it's very Apache-centric,
+ * which is this: if (*comp) is looking for matches of a particular
+ * substring in request headers (let's say it's looking for a particular
+ * cookie name in the Set-Cookie headers), then maybe it wants to be
+ * able to stop searching early as soon as it finds that one and move
+ * on to the next key. That's only an optimization of course, but changing
+ * the behavior of this function would mean that any code that tried
+ * to do that would stop working right.
+ *
+ * Sigh. --JCW, 06/28/02
+ */
+APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp,
+ void *rec, const apr_table_t *t, va_list vp)
{
char *argp;
apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts;
- int rv, i;
+ int vdorv = 1, rv, i;
+
argp = va_arg(vp, char *);
do {
apr_uint32_t checksum = 0;
@@ -723,7 +758,12 @@
rv = (*comp) (rec, elts[i].key, elts[i].val);
}
}
+ if (rv == 0) {
+ vdorv = 0;
+ }
} while (argp && ((argp = va_arg(vp, char *)) != NULL));
+
+ return vdorv;
}
/* During apr_table_overlap(), we build an overlap key for
|