File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / array.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 10:32:47 2013 UTC (10 years, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_33, HEAD
1.4.33

    1: #include "array.h"
    2: #include "buffer.h"
    3: 
    4: #include <string.h>
    5: #include <stdio.h>
    6: #include <stdlib.h>
    7: #include <limits.h>
    8: 
    9: #include <errno.h>
   10: #include <assert.h>
   11: 
   12: array *array_init(void) {
   13: 	array *a;
   14: 
   15: 	a = calloc(1, sizeof(*a));
   16: 	assert(a);
   17: 
   18: 	a->next_power_of_2 = 1;
   19: 
   20: 	return a;
   21: }
   22: 
   23: array *array_init_array(array *src) {
   24: 	size_t i;
   25: 	array *a = array_init();
   26: 
   27: 	a->used = src->used;
   28: 	a->size = src->size;
   29: 	a->next_power_of_2 = src->next_power_of_2;
   30: 	a->unique_ndx = src->unique_ndx;
   31: 
   32: 	a->data = malloc(sizeof(*src->data) * src->size);
   33: 	for (i = 0; i < src->size; i++) {
   34: 		if (src->data[i]) a->data[i] = src->data[i]->copy(src->data[i]);
   35: 		else a->data[i] = NULL;
   36: 	}
   37: 
   38: 	a->sorted = malloc(sizeof(*src->sorted)   * src->size);
   39: 	memcpy(a->sorted, src->sorted, sizeof(*src->sorted)   * src->size);
   40: 	return a;
   41: }
   42: 
   43: void array_free(array *a) {
   44: 	size_t i;
   45: 	if (!a) return;
   46: 
   47: 	if (!a->is_weakref) {
   48: 		for (i = 0; i < a->size; i++) {
   49: 			if (a->data[i]) a->data[i]->free(a->data[i]);
   50: 		}
   51: 	}
   52: 
   53: 	if (a->data) free(a->data);
   54: 	if (a->sorted) free(a->sorted);
   55: 
   56: 	free(a);
   57: }
   58: 
   59: void array_reset(array *a) {
   60: 	size_t i;
   61: 	if (!a) return;
   62: 
   63: 	if (!a->is_weakref) {
   64: 		for (i = 0; i < a->used; i++) {
   65: 			a->data[i]->reset(a->data[i]);
   66: 		}
   67: 	}
   68: 
   69: 	a->used = 0;
   70: }
   71: 
   72: data_unset *array_pop(array *a) {
   73: 	data_unset *du;
   74: 
   75: 	assert(a->used != 0);
   76: 
   77: 	a->used --;
   78: 	du = a->data[a->used];
   79: 	a->data[a->used] = NULL;
   80: 
   81: 	return du;
   82: }
   83: 
   84: static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
   85: 	int ndx = -1;
   86: 	int i, pos = 0;
   87: 
   88: 	if (key == NULL) return -1;
   89: 
   90: 	/* try to find the string */
   91: 	for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
   92: 		int cmp;
   93: 
   94: 		if (pos < 0) {
   95: 			pos += i;
   96: 		} else if (pos >= (int)a->used) {
   97: 			pos -= i;
   98: 		} else {
   99: 			cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
  100: 
  101: 			if (cmp == 0) {
  102: 				/* found */
  103: 				ndx = a->sorted[pos];
  104: 				break;
  105: 			} else if (cmp < 0) {
  106: 				pos -= i;
  107: 			} else {
  108: 				pos += i;
  109: 			}
  110: 		}
  111: 		if (i == 0) break;
  112: 	}
  113: 
  114: 	if (rndx) *rndx = pos;
  115: 
  116: 	return ndx;
  117: }
  118: 
  119: data_unset *array_get_element(array *a, const char *key) {
  120: 	int ndx;
  121: 
  122: 	if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
  123: 		/* found, leave here */
  124: 
  125: 		return a->data[ndx];
  126: 	}
  127: 
  128: 	return NULL;
  129: }
  130: 
  131: data_unset *array_get_unused_element(array *a, data_type_t t) {
  132: 	data_unset *ds = NULL;
  133: 	unsigned int i;
  134: 
  135: 	for (i = a->used; i < a->size; i++) {
  136: 		if (a->data[i] && a->data[i]->type == t) {
  137: 			ds = a->data[i];
  138: 
  139: 			/* make empty slot at a->used for next insert */
  140: 			a->data[i] = a->data[a->used];
  141: 			a->data[a->used] = NULL;
  142: 
  143: 			return ds;
  144: 		}
  145: 	}
  146: 
  147: 	return NULL;
  148: }
  149: 
  150: void array_set_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
  151: 	data_string *ds_dst;
  152: 
  153: 	if (NULL != (ds_dst = (data_string *)array_get_element(hdrs, key))) {
  154: 		buffer_copy_string_len(ds_dst->value, value, val_len);
  155: 		return;
  156: 	}
  157: 
  158: 	if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
  159: 		ds_dst = data_string_init();
  160: 	}
  161: 
  162: 	buffer_copy_string_len(ds_dst->key, key, key_len);
  163: 	buffer_copy_string_len(ds_dst->value, value, val_len);
  164: 	array_insert_unique(hdrs, (data_unset *)ds_dst);
  165: }
  166: 
  167: /* replace or insert data, return the old one with the same key */
  168: data_unset *array_replace(array *a, data_unset *du) {
  169: 	int ndx;
  170: 
  171: 	if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
  172: 		array_insert_unique(a, du);
  173: 		return NULL;
  174: 	} else {
  175: 		data_unset *old = a->data[ndx];
  176: 		a->data[ndx] = du;
  177: 		return old;
  178: 	}
  179: }
  180: 
  181: int array_insert_unique(array *a, data_unset *str) {
  182: 	int ndx = -1;
  183: 	int pos = 0;
  184: 	size_t j;
  185: 
  186: 	/* generate unique index if neccesary */
  187: 	if (str->key->used == 0 || str->is_index_key) {
  188: 		buffer_copy_long(str->key, a->unique_ndx++);
  189: 		str->is_index_key = 1;
  190: 	}
  191: 
  192: 	/* try to find the string */
  193: 	if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
  194: 		/* found, leave here */
  195: 		if (a->data[ndx]->type == str->type) {
  196: 			str->insert_dup(a->data[ndx], str);
  197: 		} else {
  198: 			SEGFAULT();
  199: 		}
  200: 		return 0;
  201: 	}
  202: 
  203: 	/* insert */
  204: 
  205: 	if (a->used+1 > INT_MAX) {
  206: 		/* we can't handle more then INT_MAX entries: see array_get_index() */
  207: 		return -1;
  208: 	}
  209: 
  210: 	if (a->size == 0) {
  211: 		a->size   = 16;
  212: 		a->data   = malloc(sizeof(*a->data)     * a->size);
  213: 		a->sorted = malloc(sizeof(*a->sorted)   * a->size);
  214: 		assert(a->data);
  215: 		assert(a->sorted);
  216: 		for (j = a->used; j < a->size; j++) a->data[j] = NULL;
  217: 	} else if (a->size == a->used) {
  218: 		a->size  += 16;
  219: 		a->data   = realloc(a->data,   sizeof(*a->data)   * a->size);
  220: 		a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size);
  221: 		assert(a->data);
  222: 		assert(a->sorted);
  223: 		for (j = a->used; j < a->size; j++) a->data[j] = NULL;
  224: 	}
  225: 
  226: 	ndx = (int) a->used;
  227: 
  228: 	/* make sure there is nothing here */
  229: 	if (a->data[ndx]) a->data[ndx]->free(a->data[ndx]);
  230: 
  231: 	a->data[a->used++] = str;
  232: 
  233: 	if (pos != ndx &&
  234: 	    ((pos < 0) ||
  235: 	     buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
  236: 		pos++;
  237: 	}
  238: 
  239: 	/* move everything on step to the right */
  240: 	if (pos != ndx) {
  241: 		memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
  242: 	}
  243: 
  244: 	/* insert */
  245: 	a->sorted[pos] = ndx;
  246: 
  247: 	if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
  248: 
  249: 	return 0;
  250: }
  251: 
  252: void array_print_indent(int depth) {
  253: 	int i;
  254: 	for (i = 0; i < depth; i ++) {
  255: 		fprintf(stdout, "    ");
  256: 	}
  257: }
  258: 
  259: size_t array_get_max_key_length(array *a) {
  260: 	size_t maxlen, i;
  261: 
  262: 	maxlen = 0;
  263: 	for (i = 0; i < a->used; i ++) {
  264: 		data_unset *du = a->data[i];
  265: 		size_t len = strlen(du->key->ptr);
  266: 
  267: 		if (len > maxlen) {
  268: 			maxlen = len;
  269: 		}
  270: 	}
  271: 	return maxlen;
  272: }
  273: 
  274: int array_print(array *a, int depth) {
  275: 	size_t i;
  276: 	size_t maxlen;
  277: 	int oneline = 1;
  278: 
  279: 	if (a->used > 5) {
  280: 		oneline = 0;
  281: 	}
  282: 	for (i = 0; i < a->used && oneline; i++) {
  283: 		data_unset *du = a->data[i];
  284: 		if (!du->is_index_key) {
  285: 			oneline = 0;
  286: 			break;
  287: 		}
  288: 		switch (du->type) {
  289: 			case TYPE_INTEGER:
  290: 			case TYPE_STRING:
  291: 			case TYPE_COUNT:
  292: 				break;
  293: 			default:
  294: 				oneline = 0;
  295: 				break;
  296: 		}
  297: 	}
  298: 	if (oneline) {
  299: 		fprintf(stdout, "(");
  300: 		for (i = 0; i < a->used; i++) {
  301: 			data_unset *du = a->data[i];
  302: 			if (i != 0) {
  303: 				fprintf(stdout, ", ");
  304: 			}
  305: 			du->print(du, depth + 1);
  306: 		}
  307: 		fprintf(stdout, ")");
  308: 		return 0;
  309: 	}
  310: 
  311: 	maxlen = array_get_max_key_length(a);
  312: 	fprintf(stdout, "(\n");
  313: 	for (i = 0; i < a->used; i++) {
  314: 		data_unset *du = a->data[i];
  315: 		array_print_indent(depth + 1);
  316: 		if (!du->is_index_key) {
  317: 			int j;
  318: 
  319: 			if (i && (i % 5) == 0) {
  320: 				fprintf(stdout, "# %zd\n", i);
  321: 				array_print_indent(depth + 1);
  322: 			}
  323: 			fprintf(stdout, "\"%s\"", du->key->ptr);
  324: 			for (j = maxlen - strlen(du->key->ptr); j > 0; j --) {
  325: 				fprintf(stdout, " ");
  326: 			}
  327: 			fprintf(stdout, " => ");
  328: 		}
  329: 		du->print(du, depth + 1);
  330: 		fprintf(stdout, ",\n");
  331: 	}
  332: 	if (!(i && (i - 1 % 5) == 0)) {
  333: 		array_print_indent(depth + 1);
  334: 		fprintf(stdout, "# %zd\n", i);
  335: 	}
  336: 	array_print_indent(depth);
  337: 	fprintf(stdout, ")");
  338: 
  339: 	return 0;
  340: }
  341: 
  342: #ifdef DEBUG_ARRAY
  343: int main (int argc, char **argv) {
  344: 	array *a;
  345: 	data_string *ds;
  346: 	data_count *dc;
  347: 
  348: 	UNUSED(argc);
  349: 	UNUSED(argv);
  350: 
  351: 	a = array_init();
  352: 
  353: 	ds = data_string_init();
  354: 	buffer_copy_string_len(ds->key, CONST_STR_LEN("abc"));
  355: 	buffer_copy_string_len(ds->value, CONST_STR_LEN("alfrag"));
  356: 
  357: 	array_insert_unique(a, (data_unset *)ds);
  358: 
  359: 	ds = data_string_init();
  360: 	buffer_copy_string_len(ds->key, CONST_STR_LEN("abc"));
  361: 	buffer_copy_string_len(ds->value, CONST_STR_LEN("hameplman"));
  362: 
  363: 	array_insert_unique(a, (data_unset *)ds);
  364: 
  365: 	ds = data_string_init();
  366: 	buffer_copy_string_len(ds->key, CONST_STR_LEN("123"));
  367: 	buffer_copy_string_len(ds->value, CONST_STR_LEN("alfrag"));
  368: 
  369: 	array_insert_unique(a, (data_unset *)ds);
  370: 
  371: 	dc = data_count_init();
  372: 	buffer_copy_string_len(dc->key, CONST_STR_LEN("def"));
  373: 
  374: 	array_insert_unique(a, (data_unset *)dc);
  375: 
  376: 	dc = data_count_init();
  377: 	buffer_copy_string_len(dc->key, CONST_STR_LEN("def"));
  378: 
  379: 	array_insert_unique(a, (data_unset *)dc);
  380: 
  381: 	array_print(a, 0);
  382: 
  383: 	array_free(a);
  384: 
  385: 	fprintf(stderr, "%d\n",
  386: 	       buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
  387: 
  388: 	return 0;
  389: }
  390: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>