File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / Attic / vars.c
Revision 1.7.2.6: download - view: text, annotated - select for diffs - revision graph
Fri May 18 13:58:38 2012 UTC (12 years, 1 month ago) by misho
Branches: io2_8
Diff to: branchpoint 1.7: preferred, unified
ouch!!!! pretty bug

    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.7.2.6 2012/05/18 13:58:38 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
   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: /*
   50:  * io_vars2buffer() - Marshaling data from array with variables to buffer
   51:  *
   52:  * @buf = Buffer
   53:  * @buflen = Size of buffer
   54:  * @vars = Variable array
   55:  * return: -1 error, 0 nothing done or >0 size of marshaled data
   56:  */
   57: int
   58: io_vars2buffer(u_char *buf, int buflen, array_t *vars)
   59: {
   60: 	int Limit = 0;
   61: 	register int i;
   62: 	ait_val_t *v, *val;
   63: 	u_char *dat;
   64: 
   65: 	assert(buf);
   66: 	assert(vars);
   67: 	if (!buf || !vars)
   68: 		return -1;
   69: 	if (!buflen || !io_arraySize(vars))
   70: 		return 0;
   71: 
   72: 	Limit = sizeof(ait_val_t) * io_arraySize(vars);
   73: 	if (Limit > buflen) {
   74: 		io_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
   75: 				buflen, Limit);
   76: 		return -1;
   77: 	} else {
   78: 		memset(buf, 0, buflen);
   79: 
   80: 		v = (ait_val_t*) buf;
   81: 		dat = buf + Limit;
   82: 	}
   83: 
   84: 	/* marshaling */
   85: 	for (i = 0; i < io_arraySize(vars); i++) {
   86: 		val = io_array(vars, i, ait_val_t*);
   87: 
   88: 		v[i].val_type = val->val_type;
   89: 		AIT_KEY(&v[i]) = htobe16(AIT_KEY(val));
   90: 		AIT_LEN(&v[i]) = htobe32(AIT_LEN(val));
   91: 
   92: 		switch (AIT_TYPE(val)) {
   93: 			case blob:
   94: 			case f32:
   95: 			case f64:
   96: 			case i8:
   97: 			case i16:
   98: 			case i32:
   99: 			case i64:
  100: 			case u8:
  101: 			case u16:
  102: 			case u32:
  103: 			case u64:
  104: 				v[i].val.net = htobe64(val->val.net);
  105: 				break;
  106: 			case data:
  107: 				if (AIT_LEN(val) > buflen - Limit) {
  108: 					io_SetErr(EMSGSIZE, "Short buffer buflen=%d "
  109: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  110: 					return -1;
  111: 				} else
  112: 					Limit += AIT_LEN(val);
  113: 
  114: 				memcpy(dat, val->val_data, AIT_LEN(val));
  115: 				/* Debug:: data offset in packet, not matter for anything! */
  116: 				v[i].val.net = dat - buf;
  117: 				dat += AIT_LEN(val);
  118: 				break;
  119: 			case buffer:
  120: 			case string:
  121: 				if (AIT_LEN(val) > buflen - Limit) {
  122: 					io_SetErr(EMSGSIZE, "Short buffer buflen=%d "
  123: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  124: 					return -1;
  125: 				} else
  126: 					Limit += AIT_LEN(val);
  127: 
  128: 				memcpy(dat, val->val.buffer, AIT_LEN(val));
  129: 				/* Debug:: data offset in packet, not matter for anything! */
  130: 				v[i].val.net = dat - buf;
  131: 				dat += AIT_LEN(val);
  132: 				break;
  133: 			default:
  134: 				io_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  135: 						AIT_TYPE(val), i);
  136: 				return -1;
  137: 		}
  138: 	}
  139: 
  140: 	return Limit;
  141: }
  142: 
  143: /*
  144:  * io_buffer2vars() - De-marshaling data from buffer to array with variables
  145:  *
  146:  * @buf = Buffer
  147:  * @buflen = Size of buffer
  148:  * @vnum = Number of variables into buffer
  149:  * @zcpy = Zero-copy for variables, if !=0 don't use io_arrayFree() for free variables and 
  150:  		*DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy()
  151:  * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy()
  152:  */
  153: array_t *
  154: io_buffer2vars(u_char *buf, int buflen, int vnum, int zcpy)
  155: {
  156: 	array_t *vars;
  157: 	int Limit = 0;
  158: 	register int i;
  159: 	ait_val_t *v, *val;
  160: 	u_char *dat;
  161: 
  162: 	assert(buf);
  163: 	if (!buf || !buflen || !vnum)
  164: 		return NULL;
  165: 
  166: 	Limit = sizeof(ait_val_t) * vnum;
  167: 	if (Limit > buflen) {
  168: 		io_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
  169: 				buflen, Limit);
  170: 		return NULL;
  171: 	} else {
  172: 		if (!(vars = io_arrayInit(vnum)))
  173: 			return NULL;
  174: 
  175: 		v = (ait_val_t*) buf;
  176: 		dat = buf + Limit;
  177: 	}
  178: 
  179: 	/* de-marshaling */
  180: 	for (i = 0; i < io_arraySize(vars); i++) {
  181: 		if (!zcpy) {
  182: 			val = malloc(sizeof(ait_val_t));
  183: 			if (!val) {
  184: 				LOGERR;
  185: 				io_arrayFree(vars);
  186: 				io_arrayDestroy(&vars);
  187: 				return NULL;
  188: 			}
  189: 		} else
  190: 			val = v + i;
  191: 		io_arraySet(vars, i, val);
  192: 
  193: 		val->val_type = v[i].val_type;
  194: #if defined(__OpenBSD__)
  195: 		AIT_LEN(val) = betoh32(AIT_LEN(&v[i]));
  196: 		AIT_KEY(val) = betoh16(AIT_KEY(&v[i]));
  197: #else
  198: 		AIT_LEN(val) = be32toh(AIT_LEN(&v[i]));
  199: 		AIT_KEY(val) = be16toh(AIT_KEY(&v[i]));
  200: #endif
  201: 
  202: 		switch (AIT_TYPE(val)) {
  203: 			case blob:
  204: 			case f32:
  205: 			case f64:
  206: 			case i8:
  207: 			case i16:
  208: 			case i32:
  209: 			case i64:
  210: 			case u8:
  211: 			case u16:
  212: 			case u32:
  213: 			case u64:
  214: #if defined(__OpenBSD__)
  215: 				val->val.net = betoh64(v[i].val.net);
  216: #else
  217: 				val->val.net = be64toh(v[i].val.net);
  218: #endif
  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 (AIT_LEN(val) > buflen - Limit) {
  226: 					io_SetErr(EMSGSIZE, "Short buffer buflen=%d "
  227: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  228: 					if (!zcpy)
  229: 						io_arrayFree(vars);
  230: 					io_arrayDestroy(&vars);
  231: 					return NULL;
  232: 				} else
  233: 					Limit += AIT_LEN(val);
  234: 
  235: 				if (!zcpy) {
  236: 					val->val.buffer = malloc(AIT_LEN(val));
  237: 					if (!val->val.buffer) {
  238: 						LOGERR;
  239: 						io_arrayFree(vars);
  240: 						io_arrayDestroy(&vars);
  241: 						return NULL;
  242: 					} else
  243: 						memcpy(val->val.buffer, dat, AIT_LEN(val));
  244: 				} else
  245: 					val->val.buffer = dat;
  246: 				dat += AIT_LEN(val);
  247: 				break;
  248: 			default:
  249: 				io_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  250: 						AIT_TYPE(val), i);
  251: 				if (!zcpy)
  252: 					io_arrayFree(vars);
  253: 				io_arrayDestroy(&vars);
  254: 				return NULL;
  255: 		}
  256: 	}
  257: 
  258: 	return vars;
  259: }
  260: 
  261: /* buffer marshaling without swapping bytes to network order */
  262: 
  263: /*
  264:  * io_vars2map() - Marshaling data from array with variables to memory map
  265:  *
  266:  * @buf = Buffer
  267:  * @buflen = Size of buffer
  268:  * @vars = Variable array
  269:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  270:  */
  271: int
  272: io_vars2map(u_char *buf, int buflen, array_t *vars)
  273: {
  274: 	int Limit = 0;
  275: 	register int i;
  276: 	ait_val_t *v, *val;
  277: 	u_char *dat;
  278: 
  279: 	assert(buf);
  280: 	assert(vars);
  281: 	if (!buf || !vars)
  282: 		return -1;
  283: 	if (!buflen || !io_arraySize(vars))
  284: 		return 0;
  285: 
  286: 	Limit = sizeof(ait_val_t) * io_arraySize(vars);
  287: 	if (Limit > buflen) {
  288: 		io_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
  289: 				buflen, Limit);
  290: 		return -1;
  291: 	} else {
  292: 		memset(buf, 0, buflen);
  293: 
  294: 		v = (ait_val_t*) buf;
  295: 		dat = buf + Limit;
  296: 	}
  297: 
  298: 	/* marshaling */
  299: 	for (i = 0; i < io_arraySize(vars); i++) {
  300: 		val = io_array(vars, i, ait_val_t*);
  301: 
  302: 		v[i].val_type = val->val_type;
  303: 		AIT_KEY(&v[i]) = AIT_KEY(val);
  304: 		AIT_LEN(&v[i]) = AIT_LEN(val);
  305: 
  306: 		switch (AIT_TYPE(val)) {
  307: 			case blob:
  308: 			case f32:
  309: 			case f64:
  310: 			case i8:
  311: 			case i16:
  312: 			case i32:
  313: 			case i64:
  314: 			case u8:
  315: 			case u16:
  316: 			case u32:
  317: 			case u64:
  318: 				v[i].val.net = val->val.net;
  319: 				break;
  320: 			case data:
  321: 				if (AIT_LEN(val) > buflen - Limit) {
  322: 					io_SetErr(EMSGSIZE, "Short buffer buflen=%d "
  323: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  324: 					return -1;
  325: 				} else
  326: 					Limit += AIT_LEN(val);
  327: 
  328: 				memcpy(dat, val->val_data, AIT_LEN(val));
  329: 				/* Debug:: data offset in packet, not matter for anything! */
  330: 				v[i].val.net = dat - buf;
  331: 				dat += AIT_LEN(val);
  332: 				break;
  333: 			case buffer:
  334: 			case string:
  335: 				if (AIT_LEN(val) > buflen - Limit) {
  336: 					io_SetErr(EMSGSIZE, "Short buffer buflen=%d "
  337: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  338: 					return -1;
  339: 				} else
  340: 					Limit += AIT_LEN(val);
  341: 
  342: 				memcpy(dat, val->val.buffer, AIT_LEN(val));
  343: 				/* Debug:: data offset in packet, not matter for anything! */
  344: 				v[i].val.net = dat - buf;
  345: 				dat += AIT_LEN(val);
  346: 				break;
  347: 			default:
  348: 				io_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  349: 						AIT_TYPE(val), i);
  350: 				return -1;
  351: 		}
  352: 	}
  353: 
  354: 	return Limit;
  355: }
  356: 
  357: /*
  358:  * io_map2vars() - De-marshaling data from memory map to array with variables
  359:  *
  360:  * @buf = Buffer
  361:  * @buflen = Size of buffer
  362:  * @vnum = Number of variables into buffer
  363:  * @zcpy = Zero-copy for variables, if !=0 don't use io_arrayFree() for free variables and 
  364:  		*DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy()
  365:  * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy()
  366:  */
  367: array_t *
  368: io_map2vars(u_char *buf, int buflen, int vnum, int zcpy)
  369: {
  370: 	array_t *vars;
  371: 	int Limit = 0;
  372: 	register int i;
  373: 	ait_val_t *v, *val;
  374: 	u_char *dat;
  375: 
  376: 	assert(buf);
  377: 	if (!buf || !buflen || !vnum)
  378: 		return NULL;
  379: 
  380: 	Limit = sizeof(ait_val_t) * vnum;
  381: 	if (Limit > buflen) {
  382: 		io_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
  383: 				buflen, Limit);
  384: 		return NULL;
  385: 	} else {
  386: 		if (!(vars = io_arrayInit(vnum)))
  387: 			return NULL;
  388: 
  389: 		v = (ait_val_t*) buf;
  390: 		dat = buf + Limit;
  391: 	}
  392: 
  393: 	/* de-marshaling */
  394: 	for (i = 0; i < io_arraySize(vars); i++) {
  395: 		if (!zcpy) {
  396: 			val = malloc(sizeof(ait_val_t));
  397: 			if (!val) {
  398: 				LOGERR;
  399: 				io_arrayFree(vars);
  400: 				io_arrayDestroy(&vars);
  401: 				return NULL;
  402: 			}
  403: 		} else
  404: 			val = v + i;
  405: 		io_arraySet(vars, i, val);
  406: 
  407: 		val->val_type = v[i].val_type;
  408: 		AIT_KEY(val) = AIT_KEY(&v[i]);
  409: 		AIT_LEN(val) = AIT_LEN(&v[i]);
  410: 
  411: 		switch (AIT_TYPE(val)) {
  412: 			case blob:
  413: 			case f32:
  414: 			case f64:
  415: 			case i8:
  416: 			case i16:
  417: 			case i32:
  418: 			case i64:
  419: 			case u8:
  420: 			case u16:
  421: 			case u32:
  422: 			case u64:
  423: 				val->val.net = v[i].val.net;
  424: 				break;
  425: 			case data:
  426: 				/* WARNING:: remap data type to buffer */
  427: 				val->val_type = buffer;
  428: 			case buffer:
  429: 			case string:
  430: 				if (AIT_LEN(val) > buflen - Limit) {
  431: 					io_SetErr(EMSGSIZE, "short buffer buflen=%d "
  432: 							"needed min %d", buflen, Limit + AIT_LEN(val));
  433: 					if (!zcpy)
  434: 						io_arrayFree(vars);
  435: 					io_arrayDestroy(&vars);
  436: 					return NULL;
  437: 				} else
  438: 					Limit += AIT_LEN(val);
  439: 
  440: 				if (!zcpy) {
  441: 					val->val.buffer = malloc(AIT_LEN(val));
  442: 					if (!val->val.buffer) {
  443: 						LOGERR;
  444: 						io_arrayFree(vars);
  445: 						io_arrayDestroy(&vars);
  446: 						return NULL;
  447: 					} else
  448: 						memcpy(val->val.buffer, dat, AIT_LEN(val));
  449: 				} else
  450: 					val->val.buffer = dat;
  451: 				dat += AIT_LEN(val);
  452: 				break;
  453: 			default:
  454: 				io_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  455: 						AIT_TYPE(val), i);
  456: 				if (!zcpy)
  457: 					io_arrayFree(vars);
  458: 				io_arrayDestroy(&vars);
  459: 				return NULL;
  460: 		}
  461: 	}
  462: 
  463: 	return vars;
  464: }
  465: 
  466: 
  467: /*
  468:  * io_allocVars() - Allocate ait_val_t array
  469:  *
  470:  * @varnum = Number of variables
  471:  * return: =NULL error or !=NULL allocated array
  472:  */
  473: inline array_t *
  474: io_allocVars(int varnum)
  475: {
  476: 	array_t *arr;
  477: 	register int i;
  478: 	ait_val_t *v;
  479: 
  480: 	if (!(arr = io_arrayInit(varnum)))
  481: 		return NULL;
  482: 
  483: 	for (i = 0; i < io_arraySize(arr); i++) {
  484: 		if (!(v = io_allocVar())) {
  485: 			io_freeVars(&arr);
  486: 			return NULL;
  487: 		} else
  488: 			io_arraySet(arr, i, v);
  489: 	}
  490: 
  491: 	return arr;
  492: }
  493: 
  494: /*
  495:  * io_getVars() - Get ait_val_t element from array and if not exists allocate it
  496:  *
  497:  * @vars = Variable array
  498:  * @n = index of variable into array
  499:  * return: NULL error or !=NULL ait_val_t element
  500:  */
  501: inline ait_val_t *
  502: io_getVars(array_t ** __restrict vars, int n)
  503: {
  504: 	register int i;
  505: 	ait_val_t *v;
  506: 
  507: 	if (!vars)
  508: 		return NULL;
  509: 
  510: 	if (!*vars) {
  511: 		if (!(*vars = io_allocVars(n + 1)))
  512: 			return NULL;
  513: 	} else {
  514: 		if (n >= (i = io_arraySize(*vars))) {
  515: 			if (io_arrayGrow(*vars, n + 1, 0))
  516: 				return NULL;
  517: 			for (; i < io_arraySize(*vars); i++)
  518: 				if (!io_arrayGet(*vars, i)) {
  519: 					if (!(v = io_allocVar()))
  520: 						return NULL;
  521: 					else
  522: 						io_arraySet(*vars, n, v);
  523: 				}
  524: 		}
  525: 	}
  526: 
  527: 	return io_array(*vars, n, ait_val_t*);
  528: }
  529: 
  530: /*
  531:  * io_clrVars() - Clear ait_val_t elements from array
  532:  *
  533:  * @vars = Variable array
  534:  * return: -1 error or size of array
  535:  */
  536: inline int
  537: io_clrVars(array_t * __restrict vars)
  538: {
  539: 	register int i;
  540: 	ait_val_t *v;
  541: 
  542: 	if (!vars)
  543: 		return -1;
  544: 
  545: 	for (i = 0; i < io_arraySize(vars); i++)
  546: 		if ((v = io_array(vars, i, ait_val_t*)))
  547: 			AIT_FREE_VAL(v);
  548: 
  549: 	return io_arraySize(vars);
  550: }
  551: 
  552: /*
  553:  * io_freeVars() - Free ait_val_t array
  554:  *
  555:  * @vars = Variable array
  556:  * return: none
  557:  */
  558: inline void
  559: io_freeVars(array_t ** __restrict vars)
  560: {
  561: 	if (!vars || !*vars)
  562: 		return;
  563: 
  564: 	io_clrVars(*vars);
  565: 	io_arrayFree(*vars);
  566: 	io_arrayDestroy(vars);
  567: }
  568: 
  569: /*
  570:  * io_allocVar() - Allocate memory for variable
  571:  *
  572:  * return: NULL error or new variable, after use free variable with io_freeVar()
  573:  */
  574: inline ait_val_t *
  575: io_allocVar(void)
  576: {
  577: 	ait_val_t *v = NULL;
  578: 
  579: 	v = malloc(sizeof(ait_val_t));
  580: 	if (!v) {
  581: 		LOGERR;
  582: 		return NULL;
  583: 	} else
  584: 		memset(v, 0, sizeof(ait_val_t));
  585: 	v->val_type = empty;
  586: 
  587: 	return v;
  588: }
  589: 
  590: /*
  591:  * io_freeVar() - Free allocated memory for variable
  592:  *
  593:  * @val = Variable
  594:  * return: none
  595:  */
  596: inline void
  597: io_freeVar(ait_val_t ** __restrict val)
  598: {
  599: 	if (val && *val) {
  600: 		AIT_FREE_VAL(*val);
  601: 		free(*val);
  602: 		*val = NULL;
  603: 	}
  604: }
  605: 
  606: static int
  607: _cmp_arr_key_asc(const void *a, const void *b)
  608: {
  609: 	return AIT_KEY(*(ait_val_t**) a) - AIT_KEY(*(ait_val_t**) b);
  610: }
  611: 
  612: static int
  613: _cmp_arr_key_desc(const void *a, const void *b)
  614: {
  615: 	return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a);
  616: }
  617: 
  618: /*
  619:  * io_sortVars() - Sorting array with variables
  620:  *
  621:  * @vars = Variable array
  622:  * @order = Sort order. If =0 ascend or !=0 descend
  623:  * @cmp = Compare function for sorting. If =NULL compare by key
  624:  * return: none
  625:  */
  626: inline void
  627: io_sortVars(array_t * __restrict vars, int order,  int (*cmp)(const void*, const void*))
  628: {
  629: 	if (!vars)
  630: 		return;
  631: 
  632: 	if (cmp)
  633: 		qsort(vars->arr_data, vars->arr_num, sizeof(void*), cmp);
  634: 	else if (order)
  635: 		qsort(vars->arr_data, vars->arr_num, sizeof(void*), _cmp_arr_key_desc);
  636: 	else
  637: 		qsort(vars->arr_data, vars->arr_num, sizeof(void*), _cmp_arr_key_asc);
  638: }
  639: 
  640: /*
  641:  * io_findKeyVars() - Find variable by key from array
  642:  *
  643:  * @vars = Variables
  644:  * @key = Search key
  645:  * return: NULL error or not found, !=NULL valid element
  646:  */
  647: ait_val_t *
  648: io_findKeyVars(array_t * __restrict vars, u_short key)
  649: {
  650: 	array_t *tmp;
  651: 	ait_val_t **vv, *v = NULL;
  652: 	register int i;
  653: 	const u_char *p;
  654: 
  655: 	if (!vars)
  656: 		return NULL;
  657: 
  658: 	if (io_arrayCopy(&tmp, vars) == -1)
  659: 		return NULL;
  660: 	else
  661: 		qsort(tmp->arr_data, tmp->arr_num, sizeof(void*), _cmp_arr_key_asc);
  662: 
  663: 	/* binary search */
  664: 	for (p = (const u_char*) tmp->arr_data, i = io_arraySize(tmp); i; i >>= 1) {
  665: 		vv = (ait_val_t**) (p + (i >> 1) * sizeof(void*));
  666: 		if (!(key - AIT_KEY(*vv))) {	/* found! */
  667: 			v = *vv;
  668: 			break;
  669: 		}
  670: 		if ((key - AIT_KEY(*vv)) > 0) {	/* move right key > current */
  671: 			p = (const u_char*) vv + sizeof(void*);
  672: 			i--;
  673: 		}				/* else move left */
  674: 	}
  675: 
  676: 	io_arrayDestroy(&tmp);
  677: 	return v;
  678: }

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