File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / src / vars.c
Revision 1.4.20.1: download - view: text, annotated - select for diffs - revision graph
Wed Aug 21 16:04:14 2013 UTC (10 years, 9 months ago) by misho
Branches: elwix2_3
Diff to: branchpoint 1.4: preferred, unified
add new api for total bytes into variables array

    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.20.1 2013/08/21 16:04:14 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:  * ait_resideVars() - Calculate footprint of resided variables into array
  420:  *
  421:  * @vars = Variable array
  422:  * return: -1 error or !=-1 bytes for whole array
  423:  */
  424: ssize_t
  425: ait_resideVars(array_t * __restrict vars)
  426: {
  427: 	ssize_t ret = 0;
  428: 	register int i;
  429: 
  430: 	if (!vars)
  431: 		return -1;
  432: 
  433: 	ret = array_Size(vars) * sizeof(ait_val_t);
  434: 	for (i = 0; i < array_Size(vars); i++)
  435: 		switch (AIT_TYPE(array(vars, i, ait_val_t*))) {
  436: 			case buffer:
  437: 			case string:
  438: 			case data:
  439: 			case ptr:
  440: 				ret += AIT_LEN(array(vars, i, ait_val_t*));
  441: 				break;
  442: 			default:
  443: 				break;
  444: 		}
  445: 
  446: 	return ret;
  447: }
  448: 
  449: 
  450: /*
  451:  * ait_allocVar() - Allocate memory for variable
  452:  *
  453:  * return: NULL error or new variable, after use free variable with ait_freeVar()
  454:  */
  455: ait_val_t *
  456: ait_allocVar(void)
  457: {
  458: 	ait_val_t *v = NULL;
  459: 
  460: 	v = e_malloc(sizeof(ait_val_t));
  461: 	if (!v)
  462: 		return NULL;
  463: 	else
  464: 		memset(v, 0, sizeof(ait_val_t));
  465: 	v->val_type = empty;
  466: 
  467: 	return v;
  468: }
  469: 
  470: /*
  471:  * ait_freeVar() - Free allocated memory for variable
  472:  *
  473:  * @val = Variable
  474:  * return: none
  475:  */
  476: void
  477: ait_freeVar(ait_val_t ** __restrict val)
  478: {
  479: 	if (val && *val) {
  480: 		AIT_FREE_VAL(*val);
  481: 		e_free(*val);
  482: 		*val = NULL;
  483: 	}
  484: }
  485: 
  486: /*
  487:  * ait_makeVar() - Allocate memory and fill variable
  488:  *
  489:  * @type = type of variable
  490:  * @... = arg1 is value of variable
  491:  * @... = arg2 is length of variabla. Not required for numbers and strings!
  492:  * return: NULL error or new variable, after use free variable with io_freeVar()
  493:  */
  494: ait_val_t *
  495: ait_makeVar(ait_type_t type, ...)
  496: {
  497: 	ait_val_t *v = NULL;
  498: 	va_list lst;
  499: 	void *p = NULL;
  500: 	uint32_t len = 0;
  501: 	uint64_t n = 0LL;
  502: 
  503: 	v = ait_allocVar();
  504: 	if (!v)
  505: 		return NULL;
  506: 
  507: 	va_start(lst, type);
  508: 	switch (type) {
  509: 		case empty:
  510: 			v->val_type = (uint8_t) empty;
  511: 			break;
  512: 		case ptr:
  513: 			p = va_arg(lst, void*);
  514: 			len = va_arg(lst, uint32_t);
  515: 			AIT_SET_PTR(v, p, len);
  516: 			break;
  517: 		case data:
  518: 			p = va_arg(lst, void*);
  519: 			len = va_arg(lst, uint32_t);
  520: 			AIT_SET_DATA(v, p, len);
  521: 			break;
  522: 		case buffer:
  523: 			p = va_arg(lst, void*);
  524: 			len = va_arg(lst, uint32_t);
  525: 			AIT_SET_BUF(v, p, len);
  526: 			break;
  527: 		case string:
  528: 			p = va_arg(lst, char*);
  529: 			AIT_SET_STR(v, (char*) p);
  530: 			break;
  531: 		case blob:
  532: 			n = va_arg(lst, uint32_t);
  533: 			len = va_arg(lst, uint32_t);
  534: 			AIT_SET_BLOB(v, n, len);
  535: 			break;
  536: 		case f32:
  537: 			AIT_SET_F32(v, (float) va_arg(lst, double));
  538: 			break;
  539: 		case f64:
  540: 			AIT_SET_F64(v, va_arg(lst, double));
  541: 			break;
  542: 		case u8:
  543: 			AIT_SET_U8(v, (uint8_t) va_arg(lst, int));
  544: 			break;
  545: 		case u16:
  546: 			AIT_SET_U16(v, (uint16_t) va_arg(lst, int));
  547: 			break;
  548: 		case u32:
  549: 			AIT_SET_U32(v, va_arg(lst, uint32_t));
  550: 			break;
  551: 		case u64:
  552: 			AIT_SET_U64(v, va_arg(lst, uint64_t));
  553: 			break;
  554: 		case i8:
  555: 			AIT_SET_I8(v, (int8_t) va_arg(lst, int));
  556: 			break;
  557: 		case i16:
  558: 			AIT_SET_I16(v, (int16_t) va_arg(lst, int));
  559: 			break;
  560: 		case i32:
  561: 			AIT_SET_I32(v, va_arg(lst, int32_t));
  562: 			break;
  563: 		case i64:
  564: 			AIT_SET_I64(v, va_arg(lst, int64_t));
  565: 			break;
  566: 	}
  567: 	va_end(lst);
  568: 
  569: 	return v;
  570: }
  571: 
  572: static int
  573: _cmp_arr_key_asc(const void *a, const void *b)
  574: {
  575: 	return AIT_KEY(*(ait_val_t**) a) - AIT_KEY(*(ait_val_t**) b);
  576: }
  577: 
  578: static int
  579: _cmp_arr_key_desc(const void *a, const void *b)
  580: {
  581: 	return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a);
  582: }
  583: 
  584: static int
  585: _cmp_arr_val_asc(const void *a, const void *b)
  586: {
  587: 	return AIT_RAW(*(ait_val_t**) a) - AIT_RAW(*(ait_val_t**) b);
  588: }
  589: 
  590: static int
  591: _cmp_arr_val_desc(const void *a, const void *b)
  592: {
  593: 	return AIT_RAW(*(ait_val_t**) b) - AIT_RAW(*(ait_val_t**) a);
  594: }
  595: 
  596: /*
  597:  * ait_sortVarsByVal() - Sorting array with variables by value
  598:  *
  599:  * @vars = Variable array
  600:  * @order = Sort order. If =0 ascend or !=0 descend
  601:  * @cmp = Custom compare function for sorting. If =NULL compare by value
  602:  * return: none
  603:  */
  604: void
  605: ait_sortVarsByVal(array_t * __restrict vars, int order,  int (*cmp)(const void*, const void*))
  606: {
  607: 	if (!vars)
  608: 		return;
  609: 
  610: 	if (cmp)
  611: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), cmp);
  612: 	else if (order)
  613: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_desc);
  614: 	else
  615: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_asc);
  616: }
  617: 
  618: /*
  619:  * ait_sortVarsByKey() - Sorting array with variables by key
  620:  *
  621:  * @vars = Variable array
  622:  * @order = Sort order. If =0 ascend or !=0 descend
  623:  * return: none
  624:  */
  625: void
  626: ait_sortVarsByKey(array_t * __restrict vars, int order)
  627: {
  628: 	if (!vars)
  629: 		return;
  630: 
  631: 	if (order)
  632: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_desc);
  633: 	else
  634: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
  635: }
  636: 
  637: /*
  638:  * ait_findKeyVars() - Find variable by key from array
  639:  *
  640:  * @vars = Variables
  641:  * @key = Search key
  642:  * return: NULL error or not found, !=NULL valid element
  643:  */
  644: ait_val_t *
  645: ait_findKeyVars(array_t * __restrict vars, u_short key)
  646: {
  647: 	array_t *tmp;
  648: 	ait_val_t **vv, *v = NULL;
  649: 	register int i;
  650: 	const u_char *p;
  651: 
  652: 	if (!vars)
  653: 		return NULL;
  654: 
  655: 	if (array_Copy(&tmp, vars) == -1)
  656: 		return NULL;
  657: 	else
  658: 		qsort(tmp->arr_data, tmp->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
  659: 
  660: 	/* binary search */
  661: 	for (p = (const u_char*) tmp->arr_data, i = array_Size(tmp); i; i >>= 1) {
  662: 		vv = (ait_val_t**) (p + (i >> 1) * sizeof(uintptr_t));
  663: 		if (!(key - AIT_KEY(*vv))) {	/* found! */
  664: 			v = *vv;
  665: 			break;
  666: 		}
  667: 		if ((key - AIT_KEY(*vv)) > 0) {	/* move right key > current */
  668: 			p = (const u_char*) vv + sizeof(uintptr_t);
  669: 			i--;
  670: 		}				/* else move left */
  671: 	}
  672: 
  673: 	array_Destroy(&tmp);
  674: 	return v;
  675: }
  676: 
  677: /*
  678:  * ait_hashVar() - Generate hash key for variable from string or value
  679:  *
  680:  * @v = variable
  681:  * @key = key string for hash, if =NULL hash will built from variable
  682:  * return: hash key
  683:  */
  684: u_short
  685: ait_hashVar(ait_val_t * __restrict v, const char * __restrict key)
  686: {
  687: 	void *p;
  688: 	u_short cksum;
  689: 	int l;
  690: 
  691: 	if (!v)
  692: 		return 0;
  693: 
  694: 	if (key) {
  695: 		p = (void*) key;
  696: 		l = (strlen(key) + 1) / 2;
  697: 	} else {
  698: 		switch (AIT_TYPE(v)) {
  699: 			case empty:
  700: 				AIT_KEY(v) = 0;
  701: 				return 0;
  702: 			case string:
  703: 			case buffer:
  704: 				p = AIT_ADDR(v);
  705: 				l = AIT_LEN(v) / 2;
  706: 				break;
  707: 			case data:
  708: 				p = v->val_data;
  709: 				l = AIT_LEN(v) / 2;
  710: 				break;
  711: 			default:
  712: 				p = &AIT_RAW(v);
  713: 				l = sizeof AIT_RAW(v) / 2;
  714: 				break;
  715: 		}
  716: 	}
  717: 
  718: 	cksum = crcFletcher16((u_short*) p, l);
  719: 
  720: 	if (AIT_BE(v))
  721: 		AIT_KEY(v) = htobe16(cksum);
  722: 	else if (AIT_LE(v))
  723: 		AIT_KEY(v) = htole16(cksum);
  724: 	else
  725: 		AIT_KEY(v) = cksum;
  726: 
  727: 	return AIT_KEY(v);
  728: }
  729: 
  730: /*
  731:  * ait_hashKeyVars() - Generate hash keys for variables
  732:  *
  733:  * @vars = Variables
  734:  * return -1 error or 0 ok
  735:  */
  736: int
  737: ait_hashKeyVars(array_t * __restrict vars)
  738: {
  739: 	register int i;
  740: 
  741: 	if (!vars)
  742: 		return -1;
  743: 
  744: 	for (i = 0; i < array_Size(vars); i++)
  745: 		ait_hashVar(array(vars, i, ait_val_t*), NULL);
  746: 
  747: 	return 0;
  748: }
  749: 
  750: /*
  751:  * ait_findKeyHash() - Find variable by hash string from array
  752:  *
  753:  * @vars = Variables
  754:  * @key = Search string
  755:  * return: NULL error or not found, !=NULL valid element
  756:  */
  757: ait_val_t *
  758: ait_findKeyHash(array_t * __restrict vars, const char * __restrict key)
  759: {
  760: 	u_short k = 0;
  761: 
  762: 	if (!vars || !key)
  763: 		return NULL;
  764: 
  765: 	k = crcFletcher16((u_short*) key, (strlen(key) + 1) / 2);
  766: 	return ait_findKeyVars(vars, k);
  767: }
  768: 
  769: /*
  770:  * ait_sprintfVar() - Builtin string variable from formatted input
  771:  *
  772:  * @v = variable
  773:  * @fmt = format string
  774:  * @... = argument(s)
  775:  * return: -1 error or >0 copied bytes to variable
  776:  */
  777: int
  778: ait_sprintfVar(ait_val_t * __restrict v, const char *fmt, ...)
  779: {
  780: 	int ret = 0;
  781: 	va_list lst;
  782: 	char *str = NULL;
  783: 
  784: 	if (!v || !fmt)
  785: 		return -1;
  786: 
  787: 	va_start(lst, fmt);
  788: 	ret = vasprintf(&str, fmt, lst);
  789: 	va_end(lst);
  790: 
  791: 	if (str && ret > -1) {
  792: 		AIT_FREE_VAL(v);
  793: 		AIT_SET_STR(v, str);
  794: 	} else
  795: 		LOGERR;
  796: 
  797: 	if (str)
  798: 		free(str);
  799: 	return ret;
  800: }
  801: 
  802: /*
  803:  * ait_setlikeVar() - Set variable like ...
  804:  *
  805:  * @v = variable
  806:  * @t = type of data
  807:  * @l = length of data
  808:  * @... = data
  809:  * return: -1 error or 0 ok
  810:  */
  811: int
  812: ait_setlikeVar(ait_val_t * __restrict v, ait_type_t t, u_int l, ...)
  813: {
  814: 	va_list lst;
  815: 
  816: 	if (!v)
  817: 		return -1;
  818: 
  819: 	AIT_FREE_VAL(v);
  820: 	AIT_INIT_VAL2(v, t);
  821: 	AIT_LEN(v) = l;
  822: 	AIT_IN(v) = 1;
  823: 
  824: 	va_start(lst, l);
  825: 	switch (AIT_TYPE(v)) {
  826: 		case ptr:
  827: 		case buffer:
  828: 		case string:
  829: 			AIT_ADDR(v) = va_arg(lst, void*);
  830: 			break;
  831: 		default:
  832: 			AIT_RAW(v) = va_arg(lst, uint64_t);
  833: 			break;
  834: 	}
  835: 	va_end(lst);
  836: 
  837: 	return 0;
  838: }
  839: 
  840: /*
  841:  * ait_getlikeVar() - Get variable like ...
  842:  *
  843:  * @v = variable
  844:  * return: return raw data
  845:  */
  846: uint64_t
  847: ait_getlikeVar(ait_val_t * __restrict v)
  848: {
  849: 	if (!v)
  850: 		return (uintptr_t) -1;
  851: 
  852: 	return AIT_RAW(v);
  853: }
  854: 
  855: /*
  856:  * ait_cmpVar() - Compare two variables
  857:  *
  858:  * @a = 1st variable
  859:  * @b = 2nd variable
  860:  * return: 0 is equal or !=0 is different
  861:  */
  862: int
  863: ait_cmpVar(ait_val_t * __restrict a, ait_val_t * __restrict b)
  864: {
  865: 	intptr_t ret;
  866: 
  867: 	if (!(ret = (a - b)))
  868: 		return ret;
  869: 	if ((ret = AIT_TYPE(a) - AIT_TYPE(b)))
  870: 		return ret;
  871: 	if ((ret = AIT_LEN(a) - AIT_LEN(b)))
  872: 		return ret;
  873: 
  874: 	switch (AIT_TYPE(a)) {
  875: 		case buffer:
  876: 			ret = memcmp(AIT_GET_BUF(a), AIT_GET_BUF(b), AIT_LEN(a));
  877: 			break;
  878: 		case string:
  879: 			ret = strncmp(AIT_GET_STR(a), AIT_GET_STR(b), AIT_LEN(a));
  880: 			break;
  881: 		case data:
  882: 			ret = memcmp(AIT_GET_DATA(a), AIT_GET_DATA(b), AIT_LEN(a));
  883: 			break;
  884: 		case ptr:
  885: 			ret = AIT_ADDR(a) - AIT_ADDR(b);
  886: 			break;
  887: 		default:
  888: 			ret = AIT_RAW(a) - AIT_RAW(b);
  889: 			break;
  890: 	}
  891: 
  892: 	return (int) ret;
  893: }

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