⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apr_tables.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 2 页
字号:
	}    }#endif    for (i = 0; i < t->a.nelts; ) {	if (!strcasecmp(elts[i].key, key)) {	    if (!done) {		elts[i].val = (char *)val;		done = 1;		++i;	    }	    else {		/* delete an extraneous element */		for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {		    elts[j].key = elts[k].key;		    elts[j].val = elts[k].val;		}		--t->a.nelts;	    }	}	else {	    ++i;	}    }    if (!done) {	elts = (apr_table_entry_t *) table_push(t);	elts->key = (char *)key;	elts->val = (char *)val;    }}APR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key){    register int i, j, k;    apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts;    for (i = 0; i < t->a.nelts; ) {	if (!strcasecmp(elts[i].key, key)) {	    /* found an element to skip over	     * there are any number of ways to remove an element from	     * a contiguous block of memory.  I've chosen one that	     * doesn't do a memcpy/bcopy/array_delete, *shrug*...	     */	    for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {		elts[j].key = elts[k].key;		elts[j].val = elts[k].val;	    }	    --t->a.nelts;	}	else {	    ++i;	}    }}APR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key,				 const char *val){    apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts;    int i;    for (i = 0; i < t->a.nelts; ++i) {	if (!strcasecmp(elts[i].key, key)) {	    elts[i].val = apr_pstrcat(t->a.cont, elts[i].val, ", ", val, NULL);	    return;	}    }    elts = (apr_table_entry_t *) table_push(t);    elts->key = apr_pstrdup(t->a.cont, key);    elts->val = apr_pstrdup(t->a.cont, val);}APR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key,				  const char *val){    apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts;    int i;#ifdef POOL_DEBUG    {	if (!apr_pool_is_ancestor(apr_find_pool(key), t->a.cont)) {	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");	    abort();	}	if (!apr_pool_is_ancestor(apr_find_pool(val), t->a.cont)) {	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");	    abort();	}    }#endif    for (i = 0; i < t->a.nelts; ++i) {	if (!strcasecmp(elts[i].key, key)) {	    elts[i].val = apr_pstrcat(t->a.cont, elts[i].val, ", ", val, NULL);	    return;	}    }    elts = (apr_table_entry_t *) table_push(t);    elts->key = (char *)key;    elts->val = (char *)val;}APR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key,			       const char *val){    apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts;    elts = (apr_table_entry_t *) table_push(t);    elts->key = apr_pstrdup(t->a.cont, key);    elts->val = apr_pstrdup(t->a.cont, val);}APR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key,				const char *val){    apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts;#ifdef POOL_DEBUG    {	if (!apr_pool_is_ancestor(apr_find_pool(key), t->a.cont)) {	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");	    abort();	}	if (!apr_pool_is_ancestor(apr_find_pool(val), t->a.cont)) {	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");	    abort();	}    }#endif    elts = (apr_table_entry_t *) table_push(t);    elts->key = (char *)key;    elts->val = (char *)val;}APR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p,					     const apr_table_t *overlay,					     const apr_table_t *base){    apr_table_t *res;#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.cont, p)) {	fprintf(stderr,		"overlay_tables: overlay's pool is not an ancestor of p\n");	abort();    }    if (!apr_pool_is_ancestor(base->a.cont, p)) {	fprintf(stderr,		"overlay_tables: base's pool is not an ancestor of p\n");	abort();    }#endif    res = apr_palloc(p, sizeof(apr_table_t));    /* behave like append_arrays */    res->a.cont = p;    copy_array_hdr_core(&res->a, &overlay->a);    apr_array_cat(&res->a, &base->a);    return res;}/* And now for something completely abstract ... * For each key value given as a vararg: *   run the function pointed to as *     int comp(void *r, char *key, char *value); *   on each valid key-value pair in the apr_table_t t that matches the vararg key, *   or once for every valid key-value pair if the vararg list is empty, *   until the function returns false (0) or we finish the table. * * Note that we restart the traversal for each vararg, which means that * duplicate varargs will result in multiple executions of the function * for each matching key.  Note also that if the vararg list is empty, * only one traversal will be made and will cut short if comp returns 0. * * Note that the table_get and table_merge functions assume that each key in * the apr_table_t is unique (i.e., no multiple entries with the same key).  This * function does not make that assumption, since it (unfortunately) isn't * true for some of Apache's tables. * * Note that rec is simply passed-on to the comp function, so that the * caller can pass additional info for the task. * * ADDENDUM for apr_table_vdo(): *  * The caching api will allow a user to walk the header values: * * apr_status_t apr_cache_el_header_walk(apr_cache_el *el,  *    int (*comp)(void *, const char *, const char *), void *rec, ...); * * So it can be ..., however from there I use a  callback that use a va_list: * * apr_status_t (*cache_el_header_walk)(apr_cache_el *el,  *    int (*comp)(void *, const char *, const char *), void *rec, va_list); * * To pass those ...'s on down to the actual module that will handle walking * their headers, in the file case this is actually just an apr_table - and * rather than reimplementing apr_table_do (which IMHO would be bad) I just * called it with the va_list. For mod_shmem_cache I don't need it since I * can't use apr_table's, but mod_file_cache should (though a good hash would * be better, but that's a different issue :).  * * So to make mod_file_cache easier to maintain, it's a good thing */APR_DECLARE(void) apr_table_do(int (*comp) (void *, const char *, const char *),			      void *rec, const apr_table_t *t, ...){    va_list vp;    va_start(vp, t);    apr_table_vdo(comp, rec, t, vp);    va_end(vp);  } APR_DECLARE(void) apr_table_vdo(int (*comp) (void *, const char *, const char *),				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;    argp = va_arg(vp, char *);    do {	for (rv = 1, i = 0; rv && (i < t->a.nelts); ++i) {	    if (elts[i].key && (!argp || !strcasecmp(elts[i].key, argp))) {		rv = (*comp) (rec, elts[i].key, elts[i].val);	    }	}    } while (argp && ((argp = va_arg(vp, char *)) != NULL));}/* Curse libc and the fact that it doesn't guarantee a stable sort.  We * have to enforce stability ourselves by using the order field.  If it * provided a stable sort then we wouldn't even need temporary storage to * do the work below. -djg * * ("stable sort" means that equal keys retain their original relative * ordering in the output.) */typedef struct {    char *key;    char *val;    int order;} overlap_key;static int sort_overlap(const void *va, const void *vb){    const overlap_key *a = va;    const overlap_key *b = vb;    int r;    r = strcasecmp(a->key, b->key);    if (r) {	return r;    }    return a->order - b->order;}/* prefer to use the stack for temp storage for overlaps smaller than this */#ifndef APR_OVERLAP_TABLES_ON_STACK#define APR_OVERLAP_TABLES_ON_STACK	(512)#endifAPR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b,				    unsigned flags){    overlap_key cat_keys_buf[APR_OVERLAP_TABLES_ON_STACK];    overlap_key *cat_keys;    int nkeys;    apr_table_entry_t *e;    apr_table_entry_t *last_e;    overlap_key *left;    overlap_key *right;    overlap_key *last;    nkeys = a->a.nelts + b->a.nelts;    if (nkeys < APR_OVERLAP_TABLES_ON_STACK) {	cat_keys = cat_keys_buf;    }    else {	/* XXX: could use scratch free space in a or b's pool instead...	 * which could save an allocation in b's pool.	 */	cat_keys = apr_palloc(b->a.cont, sizeof(overlap_key) * nkeys);    }    nkeys = 0;    /* Create a list of the entries from a concatenated with the entries     * from b.     */    e = (apr_table_entry_t *)a->a.elts;    last_e = e + a->a.nelts;    while (e < last_e) {	cat_keys[nkeys].key = e->key;	cat_keys[nkeys].val = e->val;	cat_keys[nkeys].order = nkeys;	++nkeys;	++e;    }    e = (apr_table_entry_t *)b->a.elts;    last_e = e + b->a.nelts;    while (e < last_e) {	cat_keys[nkeys].key = e->key;	cat_keys[nkeys].val = e->val;	cat_keys[nkeys].order = nkeys;	++nkeys;	++e;    }    qsort(cat_keys, nkeys, sizeof(overlap_key), sort_overlap);    /* Now iterate over the sorted list and rebuild a.     * Start by making sure it has enough space.     */    a->a.nelts = 0;    if (a->a.nalloc < nkeys) {	a->a.elts = apr_palloc(a->a.cont, a->a.elt_size * nkeys * 2);	a->a.nalloc = nkeys * 2;    }    /*     * In both the merge and set cases we retain the invariant:     *     * left->key, (left+1)->key, (left+2)->key, ..., (right-1)->key     * are all equal keys.  (i.e. strcasecmp returns 0)     *     * We essentially need to find the maximal     * right for each key, then we can do a quick merge or set as     * appropriate.     */    if (flags & APR_OVERLAP_TABLES_MERGE) {	left = cat_keys;	last = left + nkeys;	while (left < last) {	    right = left + 1;	    if (right == last		|| strcasecmp(left->key, right->key)) {		apr_table_addn(a, left->key, left->val);		left = right;	    }	    else {		char *strp;		char *value;		size_t len;		/* Have to merge some headers.  Let's re-use the order field,		 * since it's handy... we'll store the length of val there.		 */		left->order = strlen(left->val);		len = left->order;		do {		    right->order = strlen(right->val);		    len += 2 + right->order;		    ++right;		} while (right < last			 && !strcasecmp(left->key, right->key));		/* right points one past the last header to merge */		value = apr_palloc(a->a.cont, len + 1);		strp = value;		for (;;) {		    memcpy(strp, left->val, left->order);		    strp += left->order;		    ++left;		    if (left == right) {			break;		    }		    *strp++ = ',';		    *strp++ = ' ';		}		*strp = 0;		apr_table_addn(a, (left-1)->key, value);	    }	}    }    else {	left = cat_keys;	last = left + nkeys;	while (left < last) {	    right = left + 1;	    while (right < last && !strcasecmp(left->key, right->key)) {		++right;	    }	    apr_table_addn(a, (right-1)->key, (right-1)->val);	    left = right;	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -