File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / src / vars.c
Revision 1.9: download - view: text, annotated - select for diffs - revision graph
Wed May 18 12:47:42 2016 UTC (8 years ago) by misho
Branches: MAIN
CVS tags: elwix5_1, elwix5_0, elwix4_9, elwix4_8, elwix4_7, elwix4_6, elwix4_5, elwix4_4, elwix4_3, elwix4_26, elwix4_25, elwix4_24, elwix4_23, elwix4_22, elwix4_21, elwix4_20, elwix4_2, elwix4_19, elwix4_18, elwix4_17, elwix4_16, elwix4_15, elwix4_14, elwix4_13, elwix4_12, elwix4_11, elwix4_10, elwix4_1, HEAD, ELWIX5_0, ELWIX4_9, ELWIX4_8, ELWIX4_7, ELWIX4_6, ELWIX4_5, ELWIX4_4, ELWIX4_3, ELWIX4_26, ELWIX4_25, ELWIX4_24, ELWIX4_23, ELWIX4_22, ELWIX4_21, ELWIX4_20, ELWIX4_2, ELWIX4_19, ELWIX4_18, ELWIX4_17, ELWIX4_16, ELWIX4_15, ELWIX4_14, ELWIX4_13, ELWIX4_12, ELWIX4_11, ELWIX4_10, ELWIX4_1, ELWIX4_0
version 4.0

    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.9 2016/05/18 12:47:42 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 - 2015
   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: 			case ptr:
  127: 				if (AIT_LEN(val) > buflen - Limit) {
  128: 					elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d "
  129: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  130: 					return -1;
  131: 				} else
  132: 					Limit += AIT_LEN(val);
  133: 
  134: 				memcpy(dat, val->val.buffer, AIT_LEN(val));
  135: 				/* Debug:: data offset in packet, not matter for anything! */
  136: 				v[i].val.net = dat - buf;
  137: 				dat += AIT_LEN(val);
  138: 				break;
  139: 			default:
  140: 				elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  141: 						AIT_TYPE(val), i);
  142: 				return -1;
  143: 		}
  144: 	}
  145: 
  146: 	return Limit;
  147: }
  148: 
  149: static inline array_t *
  150: buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
  151: {
  152: 	array_t *vars;
  153: 	int Limit = 0;
  154: 	register int i;
  155: 	ait_val_t *v, *val;
  156: 	u_char *dat;
  157: 
  158: 	assert(buf);
  159: 	if (!buf || !buflen || !vnum)
  160: 		return NULL;
  161: 
  162: 	Limit = sizeof(ait_val_t) * vnum;
  163: 	if (Limit > buflen) {
  164: 		elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
  165: 				buflen, Limit);
  166: 		return NULL;
  167: 	} else {
  168: 		if (!(vars = array_Init(vnum)))
  169: 			return NULL;
  170: 
  171: 		v = (ait_val_t*) buf;
  172: 		dat = buf + Limit;
  173: 	}
  174: 
  175: 	/* de-marshaling */
  176: 	for (i = 0; i < array_Size(vars); i++) {
  177: 		if (!zcpy) {
  178: 			val = e_malloc(sizeof(ait_val_t));
  179: 			if (!val) {
  180: 				if (!zcpy)
  181: 					array_Free(vars);
  182: 				array_Destroy(&vars);
  183: 				return NULL;
  184: 			}
  185: 			AIT_IN(val) = 0;
  186: 		} else {
  187: 			val = v + i;
  188: 			AIT_IN(val) = 1;
  189: 		}
  190: 		array_Set(vars, i, val);
  191: 
  192: 		val->val_type = v[i].val_type;
  193: 		AIT_BE(val) = AIT_BE(&v[i]);
  194: 		AIT_LE(val) = AIT_LE(&v[i]);
  195: 		if (AIT_BE(val)) {
  196: 			AIT_LEN(val) = be32toh(AIT_LEN(&v[i]));
  197: 			AIT_KEY(val) = be16toh(AIT_KEY(&v[i]));
  198: 		}
  199: 		if (AIT_LE(val)) {
  200: 			AIT_LEN(val) = le32toh(AIT_LEN(&v[i]));
  201: 			AIT_KEY(val) = le16toh(AIT_KEY(&v[i]));
  202: 		}
  203: 
  204: 		switch (AIT_TYPE(val)) {
  205: 			case blob:
  206: 			case f32:
  207: 			case f64:
  208: 			case i8:
  209: 			case i16:
  210: 			case i32:
  211: 			case i64:
  212: 			case u8:
  213: 			case u16:
  214: 			case u32:
  215: 			case u64:
  216: 				if (AIT_BE(val))
  217: 					val->val.net = be64toh(v[i].val.net);
  218: 				if (AIT_LE(val))
  219: 					val->val.net = le64toh(v[i].val.net);
  220: 				break;
  221: 			case data:
  222: 			case ptr:
  223: 				/* WARNING:: remap data and ptr type to buffer! */
  224: 				val->val_type = buffer;
  225: 			case buffer:
  226: 			case string:
  227: 				if (!zcpy) {
  228: 					val->val.buffer = e_malloc(AIT_LEN(val));
  229: 					if (!val->val.buffer) {
  230: 						array_Free(vars);
  231: 						array_Destroy(&vars);
  232: 						return NULL;
  233: 					} else
  234: 						memcpy(val->val.buffer, dat, AIT_LEN(val));
  235: 				} else
  236: 					val->val.buffer = dat;
  237: 				dat += AIT_LEN(val);
  238: 				break;
  239: 			default:
  240: 				elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  241: 						AIT_TYPE(val), i);
  242: 				if (!zcpy)
  243: 					array_Free(vars);
  244: 				array_Destroy(&vars);
  245: 				return NULL;
  246: 		}
  247: 	}
  248: 
  249: 	return vars;
  250: }
  251: 
  252: 
  253: /* buffer marshaling with swapping bytes to network order */
  254: 
  255: /*
  256:  * ait_vars2buffer() - Marshaling data from array with variables to buffer
  257:  *
  258:  * @buf = Buffer
  259:  * @buflen = Size of buffer
  260:  * @vars = Variable array
  261:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  262:  */
  263: int
  264: ait_vars2buffer(u_char * __restrict buf, int buflen, array_t * __restrict vars)
  265: {
  266: 	return vars2buffer(buf, buflen, 42, vars);
  267: }
  268: 
  269: /*
  270:  * ait_buffer2vars() - De-marshaling data from buffer to array with variables
  271:  *
  272:  * @buf = Buffer
  273:  * @buflen = Size of buffer
  274:  * @vnum = Number of variables into buffer
  275:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
  276:  		*DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
  277:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
  278:  */
  279: array_t *
  280: ait_buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
  281: {
  282: 	return buffer2vars(buf, buflen, vnum, zcpy);
  283: }
  284: 
  285: /* buffer marshaling without swapping bytes to network order */
  286: 
  287: /*
  288:  * ait_vars2map() - Marshaling data from array with variables to memory map
  289:  *
  290:  * @buf = Buffer
  291:  * @buflen = Size of buffer
  292:  * @vars = Variable array
  293:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  294:  */
  295: int
  296: ait_vars2map(u_char *buf, int buflen, array_t *vars)
  297: {
  298: 	return vars2buffer(buf, buflen, 0, vars);
  299: }
  300: 
  301: /*
  302:  * ait_map2vars() - De-marshaling data from memory map to array with variables
  303:  *
  304:  * @buf = Buffer
  305:  * @buflen = Size of buffer
  306:  * @vnum = Number of variables into buffer
  307:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
  308:  		*DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
  309:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
  310:  */
  311: array_t *
  312: ait_map2vars(u_char *buf, int buflen, int vnum, int zcpy)
  313: {
  314: 	return buffer2vars(buf, buflen, vnum, zcpy);
  315: }
  316: 
  317: 
  318: /* variables array */
  319: 
  320: /*
  321:  * ait_allocVars() - Allocate ait_val_t array
  322:  *
  323:  * @varnum = Number of variables
  324:  * return: =NULL error or !=NULL allocated array
  325:  */
  326: array_t *
  327: ait_allocVars(int varnum)
  328: {
  329: 	array_t *arr;
  330: 	register int i;
  331: 	ait_val_t *v;
  332: 
  333: 	if (!(arr = array_Init(varnum)))
  334: 		return NULL;
  335: 
  336: 	for (i = 0; i < array_Size(arr); i++) {
  337: 		if (!(v = ait_allocVar())) {
  338: 			ait_freeVars(&arr);
  339: 			return NULL;
  340: 		} else
  341: 			array_Set(arr, i, v);
  342: 	}
  343: 
  344: 	return arr;
  345: }
  346: 
  347: /*
  348:  * ait_getVars() - Get ait_val_t element from array and if not exists allocate it
  349:  *
  350:  * @vars = Variable array
  351:  * @n = index of variable into array
  352:  * return: NULL error or !=NULL ait_val_t element
  353:  */
  354: ait_val_t *
  355: ait_getVars(array_t ** __restrict vars, int n)
  356: {
  357: 	register int i;
  358: 	ait_val_t *v;
  359: 
  360: 	if (!vars)
  361: 		return NULL;
  362: 
  363: 	if (!*vars) {
  364: 		if (!(*vars = ait_allocVars(n + 1)))
  365: 			return NULL;
  366: 	} else if (n >= (i = array_Size(*vars))) {
  367: 		if (array_Grow(*vars, n + 1, 0))
  368: 			return NULL;
  369: 		for (; i < array_Size(*vars); i++)
  370: 			if (!array_Get(*vars, i)) {
  371: 				if (!(v = ait_allocVar()))
  372: 					return NULL;
  373: 				else
  374: 					array_Set(*vars, i, v);
  375: 			}
  376: 	}
  377: 
  378: 	return array(*vars, n, ait_val_t*);
  379: }
  380: 
  381: /*
  382:  * ait_clrVars() - Clear ait_val_t elements from array
  383:  *
  384:  * @vars = Variable array
  385:  * return: -1 error or size of array
  386:  */
  387: int
  388: ait_clrVars(array_t * __restrict vars)
  389: {
  390: 	register int i;
  391: 	ait_val_t *v;
  392: 
  393: 	if (!vars)
  394: 		return -1;
  395: 
  396: 	for (i = 0; i < array_Size(vars); i++)
  397: 		if ((v = array(vars, i, ait_val_t*)))
  398: 			AIT_FREE_VAL(v);
  399: 
  400: 	return array_Size(vars);
  401: }
  402: 
  403: /*
  404:  * ait_freeVars() - Free ait_val_t array
  405:  *
  406:  * @vars = Variable array
  407:  * return: none
  408:  */
  409: void
  410: ait_freeVars(array_t ** __restrict vars)
  411: {
  412: 	register int i;
  413: 	ait_val_t *v;
  414: 
  415: 	if (!vars || !*vars)
  416: 		return;
  417: 
  418: 	for (i = 0; i < array_Size(*vars); i++)
  419: 		if ((v = array(*vars, i, ait_val_t*))) {
  420: 			/* free memory if isn't zero copy */
  421: 			if (!AIT_IN(v)) {
  422: 				AIT_FREE_VAL(v);
  423: 				if ((*vars)->arr_data[i])
  424: 					e_free((*vars)->arr_data[i]);
  425: 			} else
  426: 				AIT_FREE_VAL(v);
  427: 			(*vars)->arr_data[i] = NULL;
  428: 		}
  429: 	(*vars)->arr_last = -1;
  430: 
  431: 	array_Destroy(vars);
  432: }
  433: 
  434: /*
  435:  * ait_resideVars() - Calculate footprint of resided variables into array
  436:  *
  437:  * @vars = Variable array
  438:  * return: bytes for whole array
  439:  */
  440: size_t
  441: ait_resideVars(array_t * __restrict vars)
  442: {
  443: 	size_t ret = 0;
  444: 	register int i;
  445: 
  446: 	if (vars) {
  447: 		ret = array_Size(vars) * sizeof(ait_val_t);
  448: 		for (i = 0; i < array_Size(vars); i++)
  449: 			switch (AIT_TYPE(array(vars, i, ait_val_t*))) {
  450: 				case buffer:
  451: 				case string:
  452: 				case data:
  453: 				case ptr:
  454: 					ret += AIT_LEN(array(vars, i, ait_val_t*));
  455: 					break;
  456: 				default:
  457: 					break;
  458: 			}
  459: 	}
  460: 
  461: 	return ret;
  462: }
  463: 
  464: 
  465: /*
  466:  * ait_allocVar() - Allocate memory for variable
  467:  *
  468:  * return: NULL error or new variable, after use free variable with ait_freeVar()
  469:  */
  470: ait_val_t *
  471: ait_allocVar(void)
  472: {
  473: 	ait_val_t *v = NULL;
  474: 
  475: 	v = e_malloc(sizeof(ait_val_t));
  476: 	if (!v)
  477: 		return NULL;
  478: 	else
  479: 		memset(v, 0, sizeof(ait_val_t));
  480: 	v->val_type = empty;
  481: 
  482: 	return v;
  483: }
  484: 
  485: /*
  486:  * ait_freeVar() - Free allocated memory for variable
  487:  *
  488:  * @val = Variable
  489:  * return: none
  490:  */
  491: void
  492: ait_freeVar(ait_val_t ** __restrict val)
  493: {
  494: 	if (val && *val) {
  495: 		AIT_FREE_VAL(*val);
  496: 		e_free(*val);
  497: 		*val = NULL;
  498: 	}
  499: }
  500: 
  501: /*
  502:  * ait_makeVar() - Allocate memory and fill variable
  503:  *
  504:  * @type = type of variable
  505:  * @... = arg1 is value of variable
  506:  * @... = arg2 is length of variabla. Not required for numbers and strings!
  507:  * return: NULL error or new variable, after use free variable with io_freeVar()
  508:  */
  509: ait_val_t *
  510: ait_makeVar(ait_type_t type, ...)
  511: {
  512: 	ait_val_t *v = NULL;
  513: 	va_list lst;
  514: 	void *p = NULL;
  515: 	uint32_t len = 0;
  516: 	uint64_t n = 0LL;
  517: 
  518: 	v = ait_allocVar();
  519: 	if (!v)
  520: 		return NULL;
  521: 
  522: 	va_start(lst, type);
  523: 	switch (type) {
  524: 		case empty:
  525: 			v->val_type = (uint8_t) empty;
  526: 			break;
  527: 		case ptr:
  528: 			p = va_arg(lst, void*);
  529: 			len = va_arg(lst, uint32_t);
  530: 			AIT_SET_PTR(v, p, len);
  531: 			break;
  532: 		case data:
  533: 			p = va_arg(lst, void*);
  534: 			len = va_arg(lst, uint32_t);
  535: 			AIT_SET_DATA(v, p, len);
  536: 			break;
  537: 		case buffer:
  538: 			p = va_arg(lst, void*);
  539: 			len = va_arg(lst, uint32_t);
  540: 			AIT_SET_BUF(v, p, len);
  541: 			break;
  542: 		case string:
  543: 			p = va_arg(lst, char*);
  544: 			AIT_SET_STR(v, (char*) p);
  545: 			break;
  546: 		case blob:
  547: 			n = va_arg(lst, uint32_t);
  548: 			len = va_arg(lst, uint32_t);
  549: 			AIT_SET_BLOB(v, n, len);
  550: 			break;
  551: 		case f32:
  552: 			AIT_SET_F32(v, (float) va_arg(lst, double));
  553: 			break;
  554: 		case f64:
  555: 			AIT_SET_F64(v, va_arg(lst, double));
  556: 			break;
  557: 		case u8:
  558: 			AIT_SET_U8(v, (uint8_t) va_arg(lst, int));
  559: 			break;
  560: 		case u16:
  561: 			AIT_SET_U16(v, (uint16_t) va_arg(lst, int));
  562: 			break;
  563: 		case u32:
  564: 			AIT_SET_U32(v, va_arg(lst, uint32_t));
  565: 			break;
  566: 		case u64:
  567: 			AIT_SET_U64(v, va_arg(lst, uint64_t));
  568: 			break;
  569: 		case i8:
  570: 			AIT_SET_I8(v, (int8_t) va_arg(lst, int));
  571: 			break;
  572: 		case i16:
  573: 			AIT_SET_I16(v, (int16_t) va_arg(lst, int));
  574: 			break;
  575: 		case i32:
  576: 			AIT_SET_I32(v, va_arg(lst, int32_t));
  577: 			break;
  578: 		case i64:
  579: 			AIT_SET_I64(v, va_arg(lst, int64_t));
  580: 			break;
  581: 	}
  582: 	va_end(lst);
  583: 
  584: 	return v;
  585: }
  586: 
  587: static int
  588: _cmp_arr_key_asc(const void *a, const void *b)
  589: {
  590: 	return AIT_KEY(*(ait_val_t**) a) - AIT_KEY(*(ait_val_t**) b);
  591: }
  592: 
  593: static int
  594: _cmp_arr_key_desc(const void *a, const void *b)
  595: {
  596: 	return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a);
  597: }
  598: 
  599: static int
  600: _cmp_arr_val_asc(const void *a, const void *b)
  601: {
  602: 	return AIT_RAW(*(ait_val_t**) a) - AIT_RAW(*(ait_val_t**) b);
  603: }
  604: 
  605: static int
  606: _cmp_arr_val_desc(const void *a, const void *b)
  607: {
  608: 	return AIT_RAW(*(ait_val_t**) b) - AIT_RAW(*(ait_val_t**) a);
  609: }
  610: 
  611: /*
  612:  * ait_sortVarsByVal() - Sorting array with variables by value
  613:  *
  614:  * @vars = Variable array
  615:  * @order = Sort order. If =0 ascend or !=0 descend
  616:  * @cmp = Custom compare function for sorting. If =NULL compare by value
  617:  * return: none
  618:  */
  619: void
  620: ait_sortVarsByVal(array_t * __restrict vars, int order,  int (*cmp)(const void*, const void*))
  621: {
  622: 	if (!vars)
  623: 		return;
  624: 
  625: 	if (cmp)
  626: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), cmp);
  627: 	else if (order)
  628: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_desc);
  629: 	else
  630: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_asc);
  631: }
  632: 
  633: /*
  634:  * ait_sortVarsByKey() - Sorting array with variables by key
  635:  *
  636:  * @vars = Variable array
  637:  * @order = Sort order. If =0 ascend or !=0 descend
  638:  * return: none
  639:  */
  640: void
  641: ait_sortVarsByKey(array_t * __restrict vars, int order)
  642: {
  643: 	if (!vars)
  644: 		return;
  645: 
  646: 	if (order)
  647: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_desc);
  648: 	else
  649: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
  650: }
  651: 
  652: /*
  653:  * ait_findKeyVars() - Find variable by key from array
  654:  *
  655:  * @vars = Variables
  656:  * @key = Search key
  657:  * return: NULL error or not found, !=NULL valid element
  658:  */
  659: ait_val_t *
  660: ait_findKeyVars(array_t * __restrict vars, u_short key)
  661: {
  662: 	array_t *tmp;
  663: 	ait_val_t **vv, *v = NULL;
  664: 	register int i;
  665: 	const u_char *p;
  666: 
  667: 	if (!vars)
  668: 		return NULL;
  669: 
  670: 	if (array_Copy(&tmp, vars) == -1)
  671: 		return NULL;
  672: 	else
  673: 		qsort(tmp->arr_data, tmp->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
  674: 
  675: 	/* binary search */
  676: 	for (p = (const u_char*) tmp->arr_data, i = array_Size(tmp); i; i >>= 1) {
  677: 		vv = (ait_val_t**) (p + (i >> 1) * sizeof(uintptr_t));
  678: 		if (!(key - AIT_KEY(*vv))) {	/* found! */
  679: 			v = *vv;
  680: 			break;
  681: 		}
  682: 		if ((key - AIT_KEY(*vv)) > 0) {	/* move right key > current */
  683: 			p = (const u_char*) vv + sizeof(uintptr_t);
  684: 			i--;
  685: 		}				/* else move left */
  686: 	}
  687: 
  688: 	array_Destroy(&tmp);
  689: 	return v;
  690: }
  691: 
  692: /*
  693:  * ait_hashVar() - Generate hash key for variable from string or value
  694:  *
  695:  * @v = variable
  696:  * @key = key string for hash, if =NULL hash will built from variable
  697:  * return: hash key
  698:  */
  699: u_short
  700: ait_hashVar(ait_val_t * __restrict v, const char * __restrict key)
  701: {
  702: 	void *p;
  703: 	u_short cksum;
  704: 	int l;
  705: 
  706: 	if (!v)
  707: 		return 0;
  708: 
  709: 	if (key) {
  710: 		p = (void*) key;
  711: 		l = (strlen(key) + 1) / 2;
  712: 	} else {
  713: 		switch (AIT_TYPE(v)) {
  714: 			case empty:
  715: 				AIT_KEY(v) = 0;
  716: 				return 0;
  717: 			case string:
  718: 			case buffer:
  719: 				p = AIT_ADDR(v);
  720: 				l = AIT_LEN(v) / 2;
  721: 				break;
  722: 			case data:
  723: 				p = v->val_data;
  724: 				l = AIT_LEN(v) / 2;
  725: 				break;
  726: 			default:
  727: 				p = &AIT_RAW(v);
  728: 				l = sizeof AIT_RAW(v) / 2;
  729: 				break;
  730: 		}
  731: 	}
  732: 
  733: 	cksum = crcFletcher16((u_short*) p, l);
  734: 
  735: 	if (AIT_BE(v))
  736: 		AIT_KEY(v) = htobe16(cksum);
  737: 	else if (AIT_LE(v))
  738: 		AIT_KEY(v) = htole16(cksum);
  739: 	else
  740: 		AIT_KEY(v) = cksum;
  741: 
  742: 	return AIT_KEY(v);
  743: }
  744: 
  745: /*
  746:  * ait_hashKeyVars() - Generate hash keys for variables
  747:  *
  748:  * @vars = Variables
  749:  * return -1 error or 0 ok
  750:  */
  751: int
  752: ait_hashKeyVars(array_t * __restrict vars)
  753: {
  754: 	register int i;
  755: 
  756: 	if (!vars)
  757: 		return -1;
  758: 
  759: 	for (i = 0; i < array_Size(vars); i++)
  760: 		ait_hashVar(array(vars, i, ait_val_t*), NULL);
  761: 
  762: 	return 0;
  763: }
  764: 
  765: /*
  766:  * ait_findKeyHash() - Find variable by hash string from array
  767:  *
  768:  * @vars = Variables
  769:  * @key = Search string
  770:  * return: NULL error or not found, !=NULL valid element
  771:  */
  772: ait_val_t *
  773: ait_findKeyHash(array_t * __restrict vars, const char * __restrict key)
  774: {
  775: 	u_short k = 0;
  776: 
  777: 	if (!vars || !key)
  778: 		return NULL;
  779: 
  780: 	k = crcFletcher16((u_short*) key, (strlen(key) + 1) / 2);
  781: 	return ait_findKeyVars(vars, k);
  782: }
  783: 
  784: /*
  785:  * ait_sprintfVar() - Builtin string variable from formatted input
  786:  *
  787:  * @v = variable
  788:  * @fmt = format string
  789:  * @... = argument(s)
  790:  * return: -1 error or >0 copied bytes to variable
  791:  */
  792: int
  793: ait_sprintfVar(ait_val_t * __restrict v, const char *fmt, ...)
  794: {
  795: 	int ret = 0;
  796: 	va_list lst;
  797: 	char str[STRSIZ] = { [0 ... STRSIZ - 1] = 0 };
  798: 
  799: 	if (!v || !fmt)
  800: 		return -1;
  801: 
  802: 	va_start(lst, fmt);
  803: 	ret = vsnprintf(str, sizeof str - 1, fmt, lst);
  804: 	va_end(lst);
  805: 
  806: 	if (ret > -1) {
  807: 		AIT_FREE_VAL(v);
  808: 		AIT_SET_STR(v, str);
  809: 	} else
  810: 		LOGERR;
  811: 
  812: 	return ret;
  813: }
  814: 
  815: /*
  816:  * ait_setlikeVar() - Set variable like ...
  817:  *
  818:  * @v = variable
  819:  * @t = type of data
  820:  * @l = length of data
  821:  * @... = data
  822:  * return: -1 error or 0 ok
  823:  */
  824: int
  825: ait_setlikeVar(ait_val_t * __restrict v, ait_type_t t, u_int l, ...)
  826: {
  827: 	va_list lst;
  828: 
  829: 	if (!v)
  830: 		return -1;
  831: 
  832: 	AIT_FREE_VAL(v);
  833: 	AIT_INIT_VAL2(v, t);
  834: 	AIT_LEN(v) = l;
  835: 	AIT_IN(v) = 1;
  836: 
  837: 	va_start(lst, l);
  838: 	switch (AIT_TYPE(v)) {
  839: 		case ptr:
  840: 		case buffer:
  841: 		case string:
  842: 			AIT_ADDR(v) = va_arg(lst, void*);
  843: 			break;
  844: 		default:
  845: 			AIT_RAW(v) = va_arg(lst, uint64_t);
  846: 			break;
  847: 	}
  848: 	va_end(lst);
  849: 
  850: 	return 0;
  851: }
  852: 
  853: /*
  854:  * ait_getlikeVar() - Get variable like ...
  855:  *
  856:  * @v = variable
  857:  * return: return raw data
  858:  */
  859: uint64_t
  860: ait_getlikeVar(ait_val_t * __restrict v)
  861: {
  862: 	if (!v)
  863: 		return (uintptr_t) -1;
  864: 
  865: 	return AIT_RAW(v);
  866: }
  867: 
  868: /*
  869:  * ait_cmpVar() - Compare two variables
  870:  *
  871:  * @a = 1st variable
  872:  * @b = 2nd variable
  873:  * return: 0 is equal or !=0 is different
  874:  */
  875: int
  876: ait_cmpVar(ait_val_t * __restrict a, ait_val_t * __restrict b)
  877: {
  878: 	intptr_t ret;
  879: 
  880: 	if (!(ret = (a - b)))
  881: 		return ret;
  882: 	if ((ret = AIT_TYPE(a) - AIT_TYPE(b)))
  883: 		return ret;
  884: 	if ((ret = AIT_LEN(a) - AIT_LEN(b)))
  885: 		return ret;
  886: 
  887: 	switch (AIT_TYPE(a)) {
  888: 		case buffer:
  889: 			ret = memcmp(AIT_GET_BUF(a), AIT_GET_BUF(b), AIT_LEN(a));
  890: 			break;
  891: 		case string:
  892: 			ret = strncmp(AIT_GET_STR(a), AIT_GET_STR(b), AIT_LEN(a));
  893: 			break;
  894: 		case data:
  895: 			ret = memcmp(AIT_GET_DATA(a), AIT_GET_DATA(b), AIT_LEN(a));
  896: 			break;
  897: 		case ptr:
  898: 			ret = AIT_ADDR(a) - AIT_ADDR(b);
  899: 			break;
  900: 		default:
  901: 			ret = AIT_RAW(a) - AIT_RAW(b);
  902: 			break;
  903: 	}
  904: 
  905: 	return (int) ret;
  906: }

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