File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / src / vars.c
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Thu May 30 09:07:34 2013 UTC (11 years ago) by misho
Branches: MAIN
CVS tags: elwix2_3, elwix2_2, elwix2_1, elwix2_0, elwix1_9, elwix1_8, elwix1_7, elwix1_6, elwix1_5, elwix1_4, HEAD, ELWIX2_2, ELWIX2_1, ELWIX2_0, ELWIX1_9, ELWIX1_8, ELWIX1_7, ELWIX1_6, ELWIX1_5, ELWIX1_4, ELWIX1_3
version 1.3

    1: /*************************************************************************
    2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
    3: *  by Michael Pounov <misho@elwix.org>
    4: *
    5: * $Author: misho $
    6: * $Id: vars.c,v 1.4 2013/05/30 09:07:34 misho Exp $
    7: *
    8: **************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: 
   48: 
   49: static inline int
   50: vars2buffer(u_char * __restrict buf, int buflen, int be, array_t * __restrict vars)
   51: {
   52: 	int Limit = 0;
   53: 	register int i;
   54: 	ait_val_t *v, *val;
   55: 	u_char *dat;
   56: 
   57: 	assert(buf);
   58: 	assert(vars);
   59: 	if (!buf || !vars)
   60: 		return -1;
   61: 	if (!buflen || !array_Size(vars))
   62: 		return 0;
   63: 	be = !!be;
   64: 
   65: 	Limit = sizeof(ait_val_t) * array_Size(vars);
   66: 	if (Limit > buflen) {
   67: 		elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
   68: 				buflen, Limit);
   69: 		return -1;
   70: 	} else {
   71: 		memset(buf, 0, buflen);
   72: 
   73: 		v = (ait_val_t*) buf;
   74: 		dat = buf + Limit;
   75: 	}
   76: 
   77: 	/* marshaling */
   78: 	for (i = 0; i < array_Size(vars); i++) {
   79: 		val = array(vars, i, ait_val_t*);
   80: 
   81: 		v[i].val_type = val->val_type;
   82: 		AIT_IN(&v[i]) = 1;
   83: 		AIT_BE(&v[i]) = be;
   84: 		AIT_LE(&v[i]) = !be;
   85: 		if (AIT_BE(&v[i])) {
   86: 			AIT_KEY(&v[i]) = htobe16(AIT_KEY(val));
   87: 			AIT_LEN(&v[i]) = htobe32(AIT_LEN(val));
   88: 		}
   89: 		if (AIT_LE(&v[i])) {
   90: 			AIT_KEY(&v[i]) = htole16(AIT_KEY(val));
   91: 			AIT_LEN(&v[i]) = htole32(AIT_LEN(val));
   92: 		}
   93: 
   94: 		switch (AIT_TYPE(val)) {
   95: 			case blob:
   96: 			case f32:
   97: 			case f64:
   98: 			case i8:
   99: 			case i16:
  100: 			case i32:
  101: 			case i64:
  102: 			case u8:
  103: 			case u16:
  104: 			case u32:
  105: 			case u64:
  106: 				if (AIT_BE(&v[i]))
  107: 					v[i].val.net = htobe64(val->val.net);
  108: 				if (AIT_LE(&v[i]))
  109: 					v[i].val.net = htole64(val->val.net);
  110: 				break;
  111: 			case data:
  112: 				if (AIT_LEN(val) > buflen - Limit) {
  113: 					elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d "
  114: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  115: 					return -1;
  116: 				} else
  117: 					Limit += AIT_LEN(val);
  118: 
  119: 				memcpy(dat, val->val_data, AIT_LEN(val));
  120: 				/* Debug:: data offset in packet, not matter for anything! */
  121: 				v[i].val.net = dat - buf;
  122: 				dat += AIT_LEN(val);
  123: 				break;
  124: 			case buffer:
  125: 			case string:
  126: 				if (AIT_LEN(val) > buflen - Limit) {
  127: 					elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d "
  128: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  129: 					return -1;
  130: 				} else
  131: 					Limit += AIT_LEN(val);
  132: 
  133: 				memcpy(dat, val->val.buffer, AIT_LEN(val));
  134: 				/* Debug:: data offset in packet, not matter for anything! */
  135: 				v[i].val.net = dat - buf;
  136: 				dat += AIT_LEN(val);
  137: 				break;
  138: 			default:
  139: 				elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  140: 						AIT_TYPE(val), i);
  141: 				return -1;
  142: 		}
  143: 	}
  144: 
  145: 	return Limit;
  146: }
  147: 
  148: static inline array_t *
  149: buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
  150: {
  151: 	array_t *vars;
  152: 	int Limit = 0;
  153: 	register int i;
  154: 	ait_val_t *v, *val;
  155: 	u_char *dat;
  156: 
  157: 	assert(buf);
  158: 	if (!buf || !buflen || !vnum)
  159: 		return NULL;
  160: 
  161: 	Limit = sizeof(ait_val_t) * vnum;
  162: 	if (Limit > buflen) {
  163: 		elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
  164: 				buflen, Limit);
  165: 		return NULL;
  166: 	} else {
  167: 		if (!(vars = array_Init(vnum)))
  168: 			return NULL;
  169: 
  170: 		v = (ait_val_t*) buf;
  171: 		dat = buf + Limit;
  172: 	}
  173: 
  174: 	/* de-marshaling */
  175: 	for (i = 0; i < array_Size(vars); i++) {
  176: 		if (!zcpy) {
  177: 			val = e_malloc(sizeof(ait_val_t));
  178: 			if (!val) {
  179: 				if (!zcpy)
  180: 					array_Free(vars);
  181: 				array_Destroy(&vars);
  182: 				return NULL;
  183: 			}
  184: 			AIT_IN(val) = 0;
  185: 		} else {
  186: 			val = v + i;
  187: 			AIT_IN(val) = 1;
  188: 		}
  189: 		array_Set(vars, i, val);
  190: 
  191: 		val->val_type = v[i].val_type;
  192: 		AIT_BE(val) = AIT_BE(&v[i]);
  193: 		AIT_LE(val) = AIT_LE(&v[i]);
  194: 		if (AIT_BE(val)) {
  195: 			AIT_LEN(val) = be32toh(AIT_LEN(&v[i]));
  196: 			AIT_KEY(val) = be16toh(AIT_KEY(&v[i]));
  197: 		}
  198: 		if (AIT_LE(val)) {
  199: 			AIT_LEN(val) = le32toh(AIT_LEN(&v[i]));
  200: 			AIT_KEY(val) = le16toh(AIT_KEY(&v[i]));
  201: 		}
  202: 
  203: 		switch (AIT_TYPE(val)) {
  204: 			case blob:
  205: 			case f32:
  206: 			case f64:
  207: 			case i8:
  208: 			case i16:
  209: 			case i32:
  210: 			case i64:
  211: 			case u8:
  212: 			case u16:
  213: 			case u32:
  214: 			case u64:
  215: 				if (AIT_BE(val))
  216: 					val->val.net = be64toh(v[i].val.net);
  217: 				if (AIT_LE(val))
  218: 					val->val.net = le64toh(v[i].val.net);
  219: 				break;
  220: 			case data:
  221: 				/* WARNING:: remap data type to buffer */
  222: 				val->val_type = buffer;
  223: 			case buffer:
  224: 			case string:
  225: 				if (!zcpy) {
  226: 					val->val.buffer = e_malloc(AIT_LEN(val));
  227: 					if (!val->val.buffer) {
  228: 						array_Free(vars);
  229: 						array_Destroy(&vars);
  230: 						return NULL;
  231: 					} else
  232: 						memcpy(val->val.buffer, dat, AIT_LEN(val));
  233: 				} else
  234: 					val->val.buffer = dat;
  235: 				dat += AIT_LEN(val);
  236: 				break;
  237: 			default:
  238: 				elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  239: 						AIT_TYPE(val), i);
  240: 				if (!zcpy)
  241: 					array_Free(vars);
  242: 				array_Destroy(&vars);
  243: 				return NULL;
  244: 		}
  245: 	}
  246: 
  247: 	return vars;
  248: }
  249: 
  250: 
  251: /* buffer marshaling with swapping bytes to network order */
  252: 
  253: /*
  254:  * ait_vars2buffer() - Marshaling data from array with variables to buffer
  255:  *
  256:  * @buf = Buffer
  257:  * @buflen = Size of buffer
  258:  * @vars = Variable array
  259:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  260:  */
  261: int
  262: ait_vars2buffer(u_char * __restrict buf, int buflen, array_t * __restrict vars)
  263: {
  264: 	return vars2buffer(buf, buflen, 42, vars);
  265: }
  266: 
  267: /*
  268:  * ait_buffer2vars() - De-marshaling data from buffer to array with variables
  269:  *
  270:  * @buf = Buffer
  271:  * @buflen = Size of buffer
  272:  * @vnum = Number of variables into buffer
  273:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
  274:  		*DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
  275:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
  276:  */
  277: array_t *
  278: ait_buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
  279: {
  280: 	return buffer2vars(buf, buflen, vnum, zcpy);
  281: }
  282: 
  283: /* buffer marshaling without swapping bytes to network order */
  284: 
  285: /*
  286:  * ait_vars2map() - Marshaling data from array with variables to memory map
  287:  *
  288:  * @buf = Buffer
  289:  * @buflen = Size of buffer
  290:  * @vars = Variable array
  291:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  292:  */
  293: int
  294: ait_vars2map(u_char *buf, int buflen, array_t *vars)
  295: {
  296: 	return vars2buffer(buf, buflen, 0, vars);
  297: }
  298: 
  299: /*
  300:  * ait_map2vars() - De-marshaling data from memory map to array with variables
  301:  *
  302:  * @buf = Buffer
  303:  * @buflen = Size of buffer
  304:  * @vnum = Number of variables into buffer
  305:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
  306:  		*DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
  307:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
  308:  */
  309: array_t *
  310: ait_map2vars(u_char *buf, int buflen, int vnum, int zcpy)
  311: {
  312: 	return buffer2vars(buf, buflen, vnum, zcpy);
  313: }
  314: 
  315: 
  316: /* variables array */
  317: 
  318: /*
  319:  * ait_allocVars() - Allocate ait_val_t array
  320:  *
  321:  * @varnum = Number of variables
  322:  * return: =NULL error or !=NULL allocated array
  323:  */
  324: array_t *
  325: ait_allocVars(int varnum)
  326: {
  327: 	array_t *arr;
  328: 	register int i;
  329: 	ait_val_t *v;
  330: 
  331: 	if (!(arr = array_Init(varnum)))
  332: 		return NULL;
  333: 
  334: 	for (i = 0; i < array_Size(arr); i++) {
  335: 		if (!(v = ait_allocVar())) {
  336: 			ait_freeVars(&arr);
  337: 			return NULL;
  338: 		} else
  339: 			array_Set(arr, i, v);
  340: 	}
  341: 
  342: 	return arr;
  343: }
  344: 
  345: /*
  346:  * ait_getVars() - Get ait_val_t element from array and if not exists allocate it
  347:  *
  348:  * @vars = Variable array
  349:  * @n = index of variable into array
  350:  * return: NULL error or !=NULL ait_val_t element
  351:  */
  352: ait_val_t *
  353: ait_getVars(array_t ** __restrict vars, int n)
  354: {
  355: 	register int i;
  356: 	ait_val_t *v;
  357: 
  358: 	if (!vars)
  359: 		return NULL;
  360: 
  361: 	if (!*vars) {
  362: 		if (!(*vars = ait_allocVars(n + 1)))
  363: 			return NULL;
  364: 	} else if (n >= (i = array_Size(*vars))) {
  365: 		if (array_Grow(*vars, n + 1, 0))
  366: 			return NULL;
  367: 		for (; i < array_Size(*vars); i++)
  368: 			if (!array_Get(*vars, i)) {
  369: 				if (!(v = ait_allocVar()))
  370: 					return NULL;
  371: 				else
  372: 					array_Set(*vars, i, v);
  373: 			}
  374: 	}
  375: 
  376: 	return array(*vars, n, ait_val_t*);
  377: }
  378: 
  379: /*
  380:  * ait_clrVars() - Clear ait_val_t elements from array
  381:  *
  382:  * @vars = Variable array
  383:  * return: -1 error or size of array
  384:  */
  385: int
  386: ait_clrVars(array_t * __restrict vars)
  387: {
  388: 	register int i;
  389: 	ait_val_t *v;
  390: 
  391: 	if (!vars)
  392: 		return -1;
  393: 
  394: 	for (i = 0; i < array_Size(vars); i++)
  395: 		if ((v = array(vars, i, ait_val_t*)))
  396: 			AIT_FREE_VAL(v);
  397: 
  398: 	return array_Size(vars);
  399: }
  400: 
  401: /*
  402:  * ait_freeVars() - Free ait_val_t array
  403:  *
  404:  * @vars = Variable array
  405:  * return: none
  406:  */
  407: void
  408: ait_freeVars(array_t ** __restrict vars)
  409: {
  410: 	if (!vars || !*vars)
  411: 		return;
  412: 
  413: 	ait_clrVars(*vars);
  414: 	array_Free(*vars);
  415: 	array_Destroy(vars);
  416: }
  417: 
  418: 
  419: /*
  420:  * ait_allocVar() - Allocate memory for variable
  421:  *
  422:  * return: NULL error or new variable, after use free variable with ait_freeVar()
  423:  */
  424: ait_val_t *
  425: ait_allocVar(void)
  426: {
  427: 	ait_val_t *v = NULL;
  428: 
  429: 	v = e_malloc(sizeof(ait_val_t));
  430: 	if (!v)
  431: 		return NULL;
  432: 	else
  433: 		memset(v, 0, sizeof(ait_val_t));
  434: 	v->val_type = empty;
  435: 
  436: 	return v;
  437: }
  438: 
  439: /*
  440:  * ait_freeVar() - Free allocated memory for variable
  441:  *
  442:  * @val = Variable
  443:  * return: none
  444:  */
  445: void
  446: ait_freeVar(ait_val_t ** __restrict val)
  447: {
  448: 	if (val && *val) {
  449: 		AIT_FREE_VAL(*val);
  450: 		e_free(*val);
  451: 		*val = NULL;
  452: 	}
  453: }
  454: 
  455: /*
  456:  * ait_makeVar() - Allocate memory and fill variable
  457:  *
  458:  * @type = type of variable
  459:  * @... = arg1 is value of variable
  460:  * @... = arg2 is length of variabla. Not required for numbers and strings!
  461:  * return: NULL error or new variable, after use free variable with io_freeVar()
  462:  */
  463: ait_val_t *
  464: ait_makeVar(ait_type_t type, ...)
  465: {
  466: 	ait_val_t *v = NULL;
  467: 	va_list lst;
  468: 	void *p = NULL;
  469: 	uint32_t len = 0;
  470: 	uint64_t n = 0LL;
  471: 
  472: 	v = ait_allocVar();
  473: 	if (!v)
  474: 		return NULL;
  475: 
  476: 	va_start(lst, type);
  477: 	switch (type) {
  478: 		case empty:
  479: 			v->val_type = (uint8_t) empty;
  480: 			break;
  481: 		case ptr:
  482: 			p = va_arg(lst, void*);
  483: 			len = va_arg(lst, uint32_t);
  484: 			AIT_SET_PTR(v, p, len);
  485: 			break;
  486: 		case data:
  487: 			p = va_arg(lst, void*);
  488: 			len = va_arg(lst, uint32_t);
  489: 			AIT_SET_DATA(v, p, len);
  490: 			break;
  491: 		case buffer:
  492: 			p = va_arg(lst, void*);
  493: 			len = va_arg(lst, uint32_t);
  494: 			AIT_SET_BUF(v, p, len);
  495: 			break;
  496: 		case string:
  497: 			p = va_arg(lst, char*);
  498: 			AIT_SET_STR(v, (char*) p);
  499: 			break;
  500: 		case blob:
  501: 			n = va_arg(lst, uint32_t);
  502: 			len = va_arg(lst, uint32_t);
  503: 			AIT_SET_BLOB(v, n, len);
  504: 			break;
  505: 		case f32:
  506: 			AIT_SET_F32(v, (float) va_arg(lst, double));
  507: 			break;
  508: 		case f64:
  509: 			AIT_SET_F64(v, va_arg(lst, double));
  510: 			break;
  511: 		case u8:
  512: 			AIT_SET_U8(v, (uint8_t) va_arg(lst, int));
  513: 			break;
  514: 		case u16:
  515: 			AIT_SET_U16(v, (uint16_t) va_arg(lst, int));
  516: 			break;
  517: 		case u32:
  518: 			AIT_SET_U32(v, va_arg(lst, uint32_t));
  519: 			break;
  520: 		case u64:
  521: 			AIT_SET_U64(v, va_arg(lst, uint64_t));
  522: 			break;
  523: 		case i8:
  524: 			AIT_SET_I8(v, (int8_t) va_arg(lst, int));
  525: 			break;
  526: 		case i16:
  527: 			AIT_SET_I16(v, (int16_t) va_arg(lst, int));
  528: 			break;
  529: 		case i32:
  530: 			AIT_SET_I32(v, va_arg(lst, int32_t));
  531: 			break;
  532: 		case i64:
  533: 			AIT_SET_I64(v, va_arg(lst, int64_t));
  534: 			break;
  535: 	}
  536: 	va_end(lst);
  537: 
  538: 	return v;
  539: }
  540: 
  541: static int
  542: _cmp_arr_key_asc(const void *a, const void *b)
  543: {
  544: 	return AIT_KEY(*(ait_val_t**) a) - AIT_KEY(*(ait_val_t**) b);
  545: }
  546: 
  547: static int
  548: _cmp_arr_key_desc(const void *a, const void *b)
  549: {
  550: 	return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a);
  551: }
  552: 
  553: static int
  554: _cmp_arr_val_asc(const void *a, const void *b)
  555: {
  556: 	return AIT_RAW(*(ait_val_t**) a) - AIT_RAW(*(ait_val_t**) b);
  557: }
  558: 
  559: static int
  560: _cmp_arr_val_desc(const void *a, const void *b)
  561: {
  562: 	return AIT_RAW(*(ait_val_t**) b) - AIT_RAW(*(ait_val_t**) a);
  563: }
  564: 
  565: /*
  566:  * ait_sortVarsByVal() - Sorting array with variables by value
  567:  *
  568:  * @vars = Variable array
  569:  * @order = Sort order. If =0 ascend or !=0 descend
  570:  * @cmp = Custom compare function for sorting. If =NULL compare by value
  571:  * return: none
  572:  */
  573: void
  574: ait_sortVarsByVal(array_t * __restrict vars, int order,  int (*cmp)(const void*, const void*))
  575: {
  576: 	if (!vars)
  577: 		return;
  578: 
  579: 	if (cmp)
  580: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), cmp);
  581: 	else if (order)
  582: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_desc);
  583: 	else
  584: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_asc);
  585: }
  586: 
  587: /*
  588:  * ait_sortVarsByKey() - Sorting array with variables by key
  589:  *
  590:  * @vars = Variable array
  591:  * @order = Sort order. If =0 ascend or !=0 descend
  592:  * return: none
  593:  */
  594: void
  595: ait_sortVarsByKey(array_t * __restrict vars, int order)
  596: {
  597: 	if (!vars)
  598: 		return;
  599: 
  600: 	if (order)
  601: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_desc);
  602: 	else
  603: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
  604: }
  605: 
  606: /*
  607:  * ait_findKeyVars() - Find variable by key from array
  608:  *
  609:  * @vars = Variables
  610:  * @key = Search key
  611:  * return: NULL error or not found, !=NULL valid element
  612:  */
  613: ait_val_t *
  614: ait_findKeyVars(array_t * __restrict vars, u_short key)
  615: {
  616: 	array_t *tmp;
  617: 	ait_val_t **vv, *v = NULL;
  618: 	register int i;
  619: 	const u_char *p;
  620: 
  621: 	if (!vars)
  622: 		return NULL;
  623: 
  624: 	if (array_Copy(&tmp, vars) == -1)
  625: 		return NULL;
  626: 	else
  627: 		qsort(tmp->arr_data, tmp->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
  628: 
  629: 	/* binary search */
  630: 	for (p = (const u_char*) tmp->arr_data, i = array_Size(tmp); i; i >>= 1) {
  631: 		vv = (ait_val_t**) (p + (i >> 1) * sizeof(uintptr_t));
  632: 		if (!(key - AIT_KEY(*vv))) {	/* found! */
  633: 			v = *vv;
  634: 			break;
  635: 		}
  636: 		if ((key - AIT_KEY(*vv)) > 0) {	/* move right key > current */
  637: 			p = (const u_char*) vv + sizeof(uintptr_t);
  638: 			i--;
  639: 		}				/* else move left */
  640: 	}
  641: 
  642: 	array_Destroy(&tmp);
  643: 	return v;
  644: }
  645: 
  646: /*
  647:  * ait_hashVar() - Generate hash key for variable from string or value
  648:  *
  649:  * @v = variable
  650:  * @key = key string for hash, if =NULL hash will built from variable
  651:  * return: hash key
  652:  */
  653: u_short
  654: ait_hashVar(ait_val_t * __restrict v, const char * __restrict key)
  655: {
  656: 	void *p;
  657: 	u_short cksum;
  658: 	int l;
  659: 
  660: 	if (!v)
  661: 		return 0;
  662: 
  663: 	if (key) {
  664: 		p = (void*) key;
  665: 		l = (strlen(key) + 1) / 2;
  666: 	} else {
  667: 		switch (AIT_TYPE(v)) {
  668: 			case empty:
  669: 				AIT_KEY(v) = 0;
  670: 				return 0;
  671: 			case string:
  672: 			case buffer:
  673: 				p = AIT_ADDR(v);
  674: 				l = AIT_LEN(v) / 2;
  675: 				break;
  676: 			case data:
  677: 				p = v->val_data;
  678: 				l = AIT_LEN(v) / 2;
  679: 				break;
  680: 			default:
  681: 				p = &AIT_RAW(v);
  682: 				l = sizeof AIT_RAW(v) / 2;
  683: 				break;
  684: 		}
  685: 	}
  686: 
  687: 	cksum = crcFletcher16((u_short*) p, l);
  688: 
  689: 	if (AIT_BE(v))
  690: 		AIT_KEY(v) = htobe16(cksum);
  691: 	else if (AIT_LE(v))
  692: 		AIT_KEY(v) = htole16(cksum);
  693: 	else
  694: 		AIT_KEY(v) = cksum;
  695: 
  696: 	return AIT_KEY(v);
  697: }
  698: 
  699: /*
  700:  * ait_hashKeyVars() - Generate hash keys for variables
  701:  *
  702:  * @vars = Variables
  703:  * return -1 error or 0 ok
  704:  */
  705: int
  706: ait_hashKeyVars(array_t * __restrict vars)
  707: {
  708: 	register int i;
  709: 
  710: 	if (!vars)
  711: 		return -1;
  712: 
  713: 	for (i = 0; i < array_Size(vars); i++)
  714: 		ait_hashVar(array(vars, i, ait_val_t*), NULL);
  715: 
  716: 	return 0;
  717: }
  718: 
  719: /*
  720:  * ait_findKeyHash() - Find variable by hash string from array
  721:  *
  722:  * @vars = Variables
  723:  * @key = Search string
  724:  * return: NULL error or not found, !=NULL valid element
  725:  */
  726: ait_val_t *
  727: ait_findKeyHash(array_t * __restrict vars, const char * __restrict key)
  728: {
  729: 	u_short k = 0;
  730: 
  731: 	if (!vars || !key)
  732: 		return NULL;
  733: 
  734: 	k = crcFletcher16((u_short*) key, (strlen(key) + 1) / 2);
  735: 	return ait_findKeyVars(vars, k);
  736: }
  737: 
  738: /*
  739:  * ait_sprintfVar() - Builtin string variable from formatted input
  740:  *
  741:  * @v = variable
  742:  * @fmt = format string
  743:  * @... = argument(s)
  744:  * return: -1 error or >0 copied bytes to variable
  745:  */
  746: int
  747: ait_sprintfVar(ait_val_t * __restrict v, const char *fmt, ...)
  748: {
  749: 	int ret = 0;
  750: 	va_list lst;
  751: 	char *str = NULL;
  752: 
  753: 	if (!v || !fmt)
  754: 		return -1;
  755: 
  756: 	va_start(lst, fmt);
  757: 	ret = vasprintf(&str, fmt, lst);
  758: 	va_end(lst);
  759: 
  760: 	if (str && ret > -1) {
  761: 		AIT_FREE_VAL(v);
  762: 		AIT_SET_STR(v, str);
  763: 	} else
  764: 		LOGERR;
  765: 
  766: 	if (str)
  767: 		free(str);
  768: 	return ret;
  769: }
  770: 
  771: /*
  772:  * ait_setlikeVar() - Set variable like ...
  773:  *
  774:  * @v = variable
  775:  * @t = type of data
  776:  * @l = length of data
  777:  * @... = data
  778:  * return: -1 error or 0 ok
  779:  */
  780: int
  781: ait_setlikeVar(ait_val_t * __restrict v, ait_type_t t, u_int l, ...)
  782: {
  783: 	va_list lst;
  784: 
  785: 	if (!v)
  786: 		return -1;
  787: 
  788: 	AIT_FREE_VAL(v);
  789: 	AIT_INIT_VAL2(v, t);
  790: 	AIT_LEN(v) = l;
  791: 	AIT_IN(v) = 1;
  792: 
  793: 	va_start(lst, l);
  794: 	switch (AIT_TYPE(v)) {
  795: 		case ptr:
  796: 		case buffer:
  797: 		case string:
  798: 			AIT_ADDR(v) = va_arg(lst, void*);
  799: 			break;
  800: 		default:
  801: 			AIT_RAW(v) = va_arg(lst, uint64_t);
  802: 			break;
  803: 	}
  804: 	va_end(lst);
  805: 
  806: 	return 0;
  807: }
  808: 
  809: /*
  810:  * ait_getlikeVar() - Get variable like ...
  811:  *
  812:  * @v = variable
  813:  * return: return raw data
  814:  */
  815: uint64_t
  816: ait_getlikeVar(ait_val_t * __restrict v)
  817: {
  818: 	if (!v)
  819: 		return (uintptr_t) -1;
  820: 
  821: 	return AIT_RAW(v);
  822: }
  823: 
  824: /*
  825:  * ait_cmpVar() - Compare two variables
  826:  *
  827:  * @a = 1st variable
  828:  * @b = 2nd variable
  829:  * return: 0 is equal or !=0 is different
  830:  */
  831: int
  832: ait_cmpVar(ait_val_t * __restrict a, ait_val_t * __restrict b)
  833: {
  834: 	intptr_t ret;
  835: 
  836: 	if (!(ret = (a - b)))
  837: 		return ret;
  838: 	if ((ret = AIT_TYPE(a) - AIT_TYPE(b)))
  839: 		return ret;
  840: 	if ((ret = AIT_LEN(a) - AIT_LEN(b)))
  841: 		return ret;
  842: 
  843: 	switch (AIT_TYPE(a)) {
  844: 		case buffer:
  845: 			ret = memcmp(AIT_GET_BUF(a), AIT_GET_BUF(b), AIT_LEN(a));
  846: 			break;
  847: 		case string:
  848: 			ret = strncmp(AIT_GET_STR(a), AIT_GET_STR(b), AIT_LEN(a));
  849: 			break;
  850: 		case data:
  851: 			ret = memcmp(AIT_GET_DATA(a), AIT_GET_DATA(b), AIT_LEN(a));
  852: 			break;
  853: 		case ptr:
  854: 			ret = AIT_ADDR(a) - AIT_ADDR(b);
  855: 			break;
  856: 		default:
  857: 			ret = AIT_RAW(a) - AIT_RAW(b);
  858: 			break;
  859: 	}
  860: 
  861: 	return (int) ret;
  862: }

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