File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / src / vars.c
Revision 1.12: download - view: text, annotated - select for diffs - revision graph
Tue Feb 1 20:46:57 2022 UTC (2 years, 3 months ago) by misho
Branches: MAIN
CVS tags: elwix5_6, elwix5_5, elwix5_4, HEAD, ELWIX5_5, ELWIX5_4, ELWIX5_3
version 5.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.12 2022/02/01 20:46:57 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 - 2022
   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:  * ait_var2tlv() - Marshaling data from variable to TLV buffer
  254:  *
  255:  * @buf = Buffer, If =NULL then we return only needed buffer size
  256:  * @buflen = Size of buffer
  257:  * @var = Variable
  258:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  259:  */
  260: int
  261: ait_var2tlv(u_char * __restrict buf, int buflen, ait_val_t * __restrict v)
  262: {
  263: 	int Limit = 0;
  264: 	u_char *dat;
  265: 
  266: 	assert(v);
  267: 	if (!v)
  268: 		return -1;
  269: 	if (AIT_TYPE(v) == empty)
  270: 		return 0;
  271: 
  272: 	/* calculate amount of data into buffer */
  273: 	Limit = 5 + AIT_LEN(v);
  274: 	/* check only needed buffer size */
  275: 	if (!buf)
  276: 		return Limit;
  277: 	else
  278: 		dat = buf;
  279: 
  280: 	if (Limit > buflen) {
  281: 		elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
  282: 				buflen, Limit);
  283: 		return -1;
  284: 	} else
  285: 		memset(buf, 0, buflen);
  286: 
  287: 	/* marshaling */
  288: 	*dat++ = AIT_TYPE(v); 
  289: 
  290: 	*((uint32_t*) dat) = htonl(AIT_LEN(v));
  291: 	dat += sizeof(uint32_t);
  292: 
  293: 	switch (AIT_TYPE(v)) {
  294: 		case i8:
  295: 			*((int8_t*) dat) = AIT_GET_I8(v);
  296: 			break;
  297: 		case u8:
  298: 			*((uint8_t*) dat) = AIT_GET_U8(v);
  299: 			break;
  300: 		case i16:
  301: 			*((int16_t*) dat) = AIT_GET_I16(v);
  302: 			break;
  303: 		case u16:
  304: 			*((uint16_t*) dat) = AIT_GET_U16(v);
  305: 			break;
  306: 		case i32:
  307: 			*((int32_t*) dat) = AIT_GET_I32(v);
  308: 			break;
  309: 		case blob:
  310: 		case u32:
  311: 			*((uint32_t*) dat) = AIT_GET_U32(v);
  312: 			break;
  313: 		case i64:
  314: 			*((int64_t*) dat) = AIT_GET_I64(v);
  315: 			break;
  316: 		case u64:
  317: 			*((uint64_t*) dat) = AIT_GET_U64(v);
  318: 			break;
  319: 		case f32:
  320: 			*((float*) dat) = AIT_GET_F32(v);
  321: 			break;
  322: 		case f64:
  323: 			*((double*) dat) = AIT_GET_F64(v);
  324: 			break;
  325: 		case data:
  326: 			memcpy(dat, AIT_GET_DATA(v), AIT_LEN(v));
  327: 			break;
  328: 		case buffer:
  329: 			memcpy(dat, AIT_GET_BUF(v), AIT_LEN(v));
  330: 			break;
  331: 		case string:
  332: 			memcpy(dat, AIT_GET_STR(v), AIT_LEN(v));
  333: 			break;
  334: 		case ptr:
  335: 			memcpy(dat, AIT_GET_PTR(v), AIT_LEN(v));
  336: 			break;
  337: 		default:
  338: 			elwix_SetErr(EINVAL, "Unsupported variable type=%d", AIT_TYPE(v));
  339: 			return -1;
  340: 	}
  341: 
  342: 	return Limit;
  343: }
  344: 
  345: /*
  346:  * ait_vars2tlv() - Marshaling data from array with variables to TLV buffer
  347:  *
  348:  * @buf = Buffer, If =NULL then we return only needed buffer size
  349:  * @buflen = Size of buffer
  350:  * @vars = Variable array
  351:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  352:  */
  353: int
  354: ait_vars2tlv(u_char * __restrict buf, int buflen, array_t * __restrict vars)
  355: {
  356: 	int Limit = 0;
  357: 	register int i;
  358: 	ait_val_t *val;
  359: 	u_char *dat;
  360: 
  361: 	assert(vars);
  362: 	if (!vars)
  363: 		return -1;
  364: 	if (!array_Size(vars))
  365: 		return 0;
  366: 
  367: 	/* calculate amount of data into buffer */
  368: 	for (i = 0, Limit = 0; i < array_Size(vars); 
  369: 			Limit += 5 + AIT_LEN(array(vars, i, ait_val_t*)), i++);
  370: 	/* check only needed buffer size */
  371: 	if (!buf)
  372: 		return Limit;
  373: 
  374: 	if (Limit > buflen) {
  375: 		elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
  376: 				buflen, Limit);
  377: 		return -1;
  378: 	} else
  379: 		memset(buf, 0, buflen);
  380: 
  381: 	/* marshaling */
  382: 	for (i = 0, dat = buf; i < array_Size(vars) && dat < (buf + Limit); i++) {
  383: 		val = array(vars, i, ait_val_t*);
  384: 
  385: 		*dat++ = AIT_TYPE(val); 
  386: 
  387: 		*((uint32_t*) dat) = htonl(AIT_LEN(val));
  388: 		dat += sizeof(uint32_t);
  389: 
  390: 		switch (AIT_TYPE(val)) {
  391: 			case i8:
  392: 				*((int8_t*) dat) = AIT_GET_I8(val);
  393: 				break;
  394: 			case u8:
  395: 				*((uint8_t*) dat) = AIT_GET_U8(val);
  396: 				break;
  397: 			case i16:
  398: 				*((int16_t*) dat) = AIT_GET_I16(val);
  399: 				break;
  400: 			case u16:
  401: 				*((uint16_t*) dat) = AIT_GET_U16(val);
  402: 				break;
  403: 			case i32:
  404: 				*((int32_t*) dat) = AIT_GET_I32(val);
  405: 				break;
  406: 			case blob:
  407: 			case u32:
  408: 				*((uint32_t*) dat) = AIT_GET_U32(val);
  409: 				break;
  410: 			case i64:
  411: 				*((int64_t*) dat) = AIT_GET_I64(val);
  412: 				break;
  413: 			case u64:
  414: 				*((uint64_t*) dat) = AIT_GET_U64(val);
  415: 				break;
  416: 			case f32:
  417: 				*((float*) dat) = AIT_GET_F32(val);
  418: 				break;
  419: 			case f64:
  420: 				*((double*) dat) = AIT_GET_F64(val);
  421: 				break;
  422: 			case data:
  423: 				memcpy(dat, AIT_GET_DATA(val), AIT_LEN(val));
  424: 				break;
  425: 			case buffer:
  426: 				memcpy(dat, AIT_GET_BUF(val), AIT_LEN(val));
  427: 				break;
  428: 			case string:
  429: 				memcpy(dat, AIT_GET_STR(val), AIT_LEN(val));
  430: 				break;
  431: 			case ptr:
  432: 				memcpy(dat, AIT_GET_PTR(val), AIT_LEN(val));
  433: 				break;
  434: 			default:
  435: 				elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  436: 						AIT_TYPE(val), i);
  437: 				return -1;
  438: 		}
  439: 		dat += AIT_LEN(val);
  440: 	}
  441: 
  442: 	return Limit;
  443: }
  444: 
  445: /*
  446:  * ait_tlv2var() - De-marshaling data from TLV buffer to variable
  447:  *
  448:  * @buf = Buffer
  449:  * @buflen = Size of buffer
  450:  * @next_tlv = Next TLV position, if it is !=NULL 
  451:  * return: =NULL error, !=NULL allocated variable array, after use must free with ait_freeVar()
  452:  */
  453: ait_val_t *
  454: ait_tlv2var(u_char * __restrict buf, int buflen, off_t *next_tlv)
  455: {
  456: 	ait_val_t *val;
  457: 	u_char *dat;
  458: 
  459: 	assert(buf);
  460: 	if (!buf || !buflen)
  461: 		return NULL;
  462: 
  463: 	if (!(val = ait_allocVar()))
  464: 		return NULL;
  465: 	else
  466: 		dat = buf;
  467: 
  468: 	/* de-marshaling */
  469: 	if (*dat != empty) {
  470: 		val->val_type = *dat++;
  471: 		AIT_LEN(val) = ntohl(*((uint32_t*) dat));
  472: 		dat += sizeof(uint32_t);
  473: 		
  474: 		switch (AIT_TYPE(val)) {
  475: 			case f32:
  476: 				AIT_SET_F32(val, *((float*) dat));
  477: 				break;
  478: 			case f64:
  479: 				AIT_SET_F64(val, *((double*) dat));
  480: 				break;
  481: 			case i8:
  482: 				AIT_SET_I8(val, *((int8_t*) dat));
  483: 				break;
  484: 			case i16:
  485: 				AIT_SET_I16(val, *((int16_t*) dat));
  486: 				break;
  487: 			case i32:
  488: 				AIT_SET_I32(val, *((int32_t*) dat));
  489: 				break;
  490: 			case i64:
  491: 				AIT_SET_I64(val, *((int64_t*) dat));
  492: 				break;
  493: 			case u8:
  494: 				AIT_SET_U8(val, *((uint8_t*) dat));
  495: 				break;
  496: 			case u16:
  497: 				AIT_SET_U16(val, *((uint16_t*) dat));
  498: 				break;
  499: 			case blob:
  500: 			case u32:
  501: 				AIT_SET_U32(val, *((uint32_t*) dat));
  502: 				break;
  503: 			case u64:
  504: 				AIT_SET_U64(val, *((uint64_t*) dat));
  505: 				break;
  506: 			case data:
  507: 				AIT_SET_DATA(val, dat, AIT_LEN(val));
  508: 				break;
  509: 			case ptr:
  510: 			case buffer:
  511: 				AIT_SET_BUF(val, dat, AIT_LEN(val));
  512: 				break;
  513: 			case string:
  514: 				AIT_SET_STR(val, (char*) dat);
  515: 				break;
  516: 			default:
  517: 				elwix_SetErr(EINVAL, "Unsupported variable type=%d", AIT_TYPE(val));
  518: 				ait_freeVar(&val);
  519: 				return NULL;
  520: 		}
  521: 		dat += AIT_LEN(val);
  522: 	}
  523: 
  524: 	if (next_tlv)
  525: 		*next_tlv = dat - buf;
  526: 
  527: 	return val;
  528: }
  529: 
  530: /*
  531:  * ait_tlv2vars() - De-marshaling data from TLV buffer to array with variables
  532:  *
  533:  * @buf = Buffer
  534:  * @buflen = Size of buffer
  535:  * return: =NULL error, !=NULL allocated variable array, after use must free with ait_freeVars()
  536:  */
  537: array_t *
  538: ait_tlv2vars(u_char * __restrict buf, int buflen)
  539: {
  540: 	array_t *vars;
  541: 	register int i;
  542: 	ait_val_t *val;
  543: 	u_char *dat;
  544: 
  545: 	assert(buf);
  546: 	if (!buf || !buflen)
  547: 		return NULL;
  548: 
  549: 	if (!(vars = ait_allocVars(1)))
  550: 		return NULL;
  551: 
  552: 	/* de-marshaling */
  553: 	for (i = 0, dat = buf; *dat != empty && dat < (buf + buflen); i++) {
  554: 		val = ait_getVars(&vars, i);
  555: 		if (!val) {
  556: 			ait_freeVars(&vars);
  557: 			return NULL;
  558: 		}
  559: 
  560: 		val->val_type = *dat++;
  561: 		AIT_LEN(val) = ntohl(*((uint32_t*) dat));
  562: 		dat += sizeof(uint32_t);
  563: 		
  564: 		switch (AIT_TYPE(val)) {
  565: 			case f32:
  566: 				AIT_SET_F32(val, *((float*) dat));
  567: 				break;
  568: 			case f64:
  569: 				AIT_SET_F64(val, *((double*) dat));
  570: 				break;
  571: 			case i8:
  572: 				AIT_SET_I8(val, *((int8_t*) dat));
  573: 				break;
  574: 			case i16:
  575: 				AIT_SET_I16(val, *((int16_t*) dat));
  576: 				break;
  577: 			case i32:
  578: 				AIT_SET_I32(val, *((int32_t*) dat));
  579: 				break;
  580: 			case i64:
  581: 				AIT_SET_I64(val, *((int64_t*) dat));
  582: 				break;
  583: 			case u8:
  584: 				AIT_SET_U8(val, *((uint8_t*) dat));
  585: 				break;
  586: 			case u16:
  587: 				AIT_SET_U16(val, *((uint16_t*) dat));
  588: 				break;
  589: 			case blob:
  590: 			case u32:
  591: 				AIT_SET_U32(val, *((uint32_t*) dat));
  592: 				break;
  593: 			case u64:
  594: 				AIT_SET_U64(val, *((uint64_t*) dat));
  595: 				break;
  596: 			case data:
  597: 				AIT_SET_DATA(val, dat, AIT_LEN(val));
  598: 				break;
  599: 			case ptr:
  600: 			case buffer:
  601: 				AIT_SET_BUF(val, dat, AIT_LEN(val));
  602: 				break;
  603: 			case string:
  604: 				AIT_SET_STR(val, (char*) dat);
  605: 				break;
  606: 			default:
  607: 				elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
  608: 						AIT_TYPE(val), i);
  609: 				ait_freeVars(&vars);
  610: 				return NULL;
  611: 		}
  612: 		dat += AIT_LEN(val);
  613: 	}
  614: 
  615: 	return vars;
  616: }
  617: 
  618: /* buffer marshaling with swapping bytes to network order */
  619: 
  620: /*
  621:  * ait_vars2buffer() - Marshaling data from array with variables to buffer
  622:  *
  623:  * @buf = Buffer
  624:  * @buflen = Size of buffer
  625:  * @vars = Variable array
  626:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  627:  */
  628: int
  629: ait_vars2buffer(u_char * __restrict buf, int buflen, array_t * __restrict vars)
  630: {
  631: 	return vars2buffer(buf, buflen, 42, vars);
  632: }
  633: 
  634: /*
  635:  * ait_buffer2vars() - De-marshaling data from buffer to array with variables
  636:  *
  637:  * @buf = Buffer
  638:  * @buflen = Size of buffer
  639:  * @vnum = Number of variables into buffer
  640:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
  641:  		*DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
  642:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
  643:  */
  644: array_t *
  645: ait_buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
  646: {
  647: 	return buffer2vars(buf, buflen, vnum, zcpy);
  648: }
  649: 
  650: /* buffer marshaling without swapping bytes to network order */
  651: 
  652: /*
  653:  * ait_vars2map() - Marshaling data from array with variables to memory map
  654:  *
  655:  * @buf = Buffer
  656:  * @buflen = Size of buffer
  657:  * @vars = Variable array
  658:  * return: -1 error, 0 nothing done or >0 size of marshaled data
  659:  */
  660: int
  661: ait_vars2map(u_char *buf, int buflen, array_t *vars)
  662: {
  663: 	return vars2buffer(buf, buflen, 0, vars);
  664: }
  665: 
  666: /*
  667:  * ait_map2vars() - De-marshaling data from memory map to array with variables
  668:  *
  669:  * @buf = Buffer
  670:  * @buflen = Size of buffer
  671:  * @vnum = Number of variables into buffer
  672:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
  673:  		*DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
  674:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
  675:  */
  676: array_t *
  677: ait_map2vars(u_char *buf, int buflen, int vnum, int zcpy)
  678: {
  679: 	return buffer2vars(buf, buflen, vnum, zcpy);
  680: }
  681: 
  682: /*
  683:  * ait_array2vars() - Build array with variables from Null Terminated String Array
  684:  *
  685:  * @args = Null-terminated array with strings
  686:  * @dn = Convert numbers from strings to numbers into variables
  687:  * return: =NULL error, !=NULL allocated variable array, after use must free with ait_freeVars()
  688:  */
  689: array_t *
  690: ait_array2vars(const char **args, int dn)
  691: {
  692: 	array_t *vars;
  693: 	ait_val_t *val;
  694: 	register int i;
  695: 	long n;
  696: 	double d;
  697: 	char *str;
  698: 
  699: 	if (!args)
  700: 		return NULL;
  701: 
  702: 	vars = ait_allocVars(0);
  703: 	if (!vars)
  704: 		return NULL;
  705: 
  706: 	for (i = 0; *args; i++, args++) {
  707: 		val = ait_getVars(&vars, i);
  708: 		if (!val) {
  709: 			ait_freeVars(&vars);
  710: 			return NULL;
  711: 		}
  712: 
  713: 		if (dn) {
  714: 			n = strtol(*args, &str, 0);
  715: 			if (!str || !*str) {
  716: 				AIT_SET_I64(val, (int64_t) n);
  717: 				continue;
  718: 			}
  719: 			d = strtod(*args, &str);
  720: 			if (!str || !*str) {
  721: 				AIT_SET_F64(val, d);
  722: 				continue;
  723: 			}
  724: 			AIT_SET_STR(val, *args);
  725: 		} else
  726: 			AIT_SET_STR(val, *args);
  727: 	}
  728: 
  729: 	return vars;
  730: }
  731: 
  732: /* variables array */
  733: 
  734: /*
  735:  * ait_allocVars() - Allocate ait_val_t array
  736:  *
  737:  * @varnum = Number of variables
  738:  * return: =NULL error or !=NULL allocated array
  739:  */
  740: array_t *
  741: ait_allocVars(int varnum)
  742: {
  743: 	array_t *arr;
  744: 	register int i;
  745: 	ait_val_t *v;
  746: 
  747: 	if (!(arr = array_Init(varnum)))
  748: 		return NULL;
  749: 
  750: 	for (i = 0; i < array_Size(arr); i++) {
  751: 		if (!(v = ait_allocVar())) {
  752: 			ait_freeVars(&arr);
  753: 			return NULL;
  754: 		} else
  755: 			array_Set(arr, i, v);
  756: 	}
  757: 
  758: 	return arr;
  759: }
  760: 
  761: /*
  762:  * ait_getVars() - Get ait_val_t element from array and if not exists allocate it
  763:  *
  764:  * @vars = Variable array
  765:  * @n = index of variable into array
  766:  * return: NULL error or !=NULL ait_val_t element
  767:  */
  768: ait_val_t *
  769: ait_getVars(array_t ** __restrict vars, int n)
  770: {
  771: 	register int i;
  772: 	ait_val_t *v;
  773: 
  774: 	if (!vars)
  775: 		return NULL;
  776: 
  777: 	if (!*vars) {
  778: 		if (!(*vars = ait_allocVars(n + 1)))
  779: 			return NULL;
  780: 	} else if (n >= (i = array_Size(*vars))) {
  781: 		if (array_Grow(*vars, n + 1, 0))
  782: 			return NULL;
  783: 		for (; i < array_Size(*vars); i++)
  784: 			if (!array_Get(*vars, i)) {
  785: 				if (!(v = ait_allocVar()))
  786: 					return NULL;
  787: 				else
  788: 					array_Set(*vars, i, v);
  789: 			}
  790: 	}
  791: 
  792: 	return array(*vars, n, ait_val_t*);
  793: }
  794: 
  795: /*
  796:  * ait_clrVars() - Clear ait_val_t elements from array
  797:  *
  798:  * @vars = Variable array
  799:  * return: -1 error or size of array
  800:  */
  801: int
  802: ait_clrVars(array_t * __restrict vars)
  803: {
  804: 	register int i;
  805: 	ait_val_t *v;
  806: 
  807: 	if (!vars)
  808: 		return -1;
  809: 
  810: 	for (i = 0; i < array_Size(vars); i++)
  811: 		if ((v = array(vars, i, ait_val_t*)))
  812: 			AIT_FREE_VAL(v);
  813: 
  814: 	return array_Size(vars);
  815: }
  816: 
  817: /*
  818:  * ait_freeVars() - Free ait_val_t array
  819:  *
  820:  * @vars = Variable array
  821:  * return: none
  822:  */
  823: void
  824: ait_freeVars(array_t ** __restrict vars)
  825: {
  826: 	register int i;
  827: 	ait_val_t *v;
  828: 
  829: 	if (!vars || !*vars)
  830: 		return;
  831: 
  832: 	for (i = 0; i < array_Size(*vars); i++)
  833: 		if ((v = array(*vars, i, ait_val_t*))) {
  834: 			/* free memory if isn't zero copy */
  835: 			if (!AIT_IN(v)) {
  836: 				AIT_FREE_VAL(v);
  837: 				if ((*vars)->arr_data[i])
  838: 					e_free((*vars)->arr_data[i]);
  839: 			} else
  840: 				AIT_FREE_VAL(v);
  841: 			(*vars)->arr_data[i] = NULL;
  842: 		}
  843: 	(*vars)->arr_last = -1;
  844: 
  845: 	array_Destroy(vars);
  846: }
  847: 
  848: /*
  849:  * ait_resideVars() - Calculate footprint of resided variables into array
  850:  *
  851:  * @vars = Variable array
  852:  * return: bytes for whole array
  853:  */
  854: size_t
  855: ait_resideVars(array_t * __restrict vars)
  856: {
  857: 	size_t ret = 0;
  858: 	register int i;
  859: 
  860: 	if (vars) {
  861: 		ret = array_Size(vars) * sizeof(ait_val_t);
  862: 		for (i = 0; i < array_Size(vars); i++)
  863: 			switch (AIT_TYPE(array(vars, i, ait_val_t*))) {
  864: 				case buffer:
  865: 				case string:
  866: 				case data:
  867: 				case ptr:
  868: 					ret += AIT_LEN(array(vars, i, ait_val_t*));
  869: 					break;
  870: 				default:
  871: 					break;
  872: 			}
  873: 	}
  874: 
  875: 	return ret;
  876: }
  877: 
  878: 
  879: /*
  880:  * ait_allocVar() - Allocate memory for variable
  881:  *
  882:  * return: NULL error or new variable, after use free variable with ait_freeVar()
  883:  */
  884: ait_val_t *
  885: ait_allocVar(void)
  886: {
  887: 	ait_val_t *v = NULL;
  888: 
  889: 	v = e_malloc(sizeof(ait_val_t));
  890: 	if (!v)
  891: 		return NULL;
  892: 	else
  893: 		memset(v, 0, sizeof(ait_val_t));
  894: 	v->val_type = empty;
  895: 
  896: 	return v;
  897: }
  898: 
  899: /*
  900:  * ait_freeVar() - Free allocated memory for variable
  901:  *
  902:  * @val = Variable
  903:  * return: none
  904:  */
  905: void
  906: ait_freeVar(ait_val_t ** __restrict val)
  907: {
  908: 	if (val && *val) {
  909: 		AIT_FREE_VAL(*val);
  910: 		e_free(*val);
  911: 		*val = NULL;
  912: 	}
  913: }
  914: 
  915: /*
  916:  * ait_makeVar() - Allocate memory and fill variable
  917:  *
  918:  * @type = type of variable
  919:  * @... = arg1 is value of variable
  920:  * @... = arg2 is length of variabla. Not required for numbers and strings!
  921:  * return: NULL error or new variable, after use free variable with io_freeVar()
  922:  */
  923: ait_val_t *
  924: ait_makeVar(ait_type_t type, ...)
  925: {
  926: 	ait_val_t *v = NULL;
  927: 	va_list lst;
  928: 	void *p = NULL;
  929: 	uint32_t len = 0;
  930: 	uint64_t n = 0LL;
  931: 
  932: 	v = ait_allocVar();
  933: 	if (!v)
  934: 		return NULL;
  935: 
  936: 	va_start(lst, type);
  937: 	switch (type) {
  938: 		case empty:
  939: 			v->val_type = (uint8_t) empty;
  940: 			break;
  941: 		case ptr:
  942: 			p = va_arg(lst, void*);
  943: 			len = va_arg(lst, uint32_t);
  944: 			AIT_SET_PTR(v, p, len);
  945: 			break;
  946: 		case data:
  947: 			p = va_arg(lst, void*);
  948: 			len = va_arg(lst, uint32_t);
  949: 			AIT_SET_DATA(v, p, len);
  950: 			break;
  951: 		case buffer:
  952: 			p = va_arg(lst, void*);
  953: 			len = va_arg(lst, uint32_t);
  954: 			AIT_SET_BUF(v, p, len);
  955: 			break;
  956: 		case string:
  957: 			p = va_arg(lst, char*);
  958: 			AIT_SET_STR(v, (char*) p);
  959: 			break;
  960: 		case blob:
  961: 			n = va_arg(lst, uint32_t);
  962: 			len = va_arg(lst, uint32_t);
  963: 			AIT_SET_BLOB(v, n, len);
  964: 			break;
  965: 		case f32:
  966: 			AIT_SET_F32(v, (float) va_arg(lst, double));
  967: 			break;
  968: 		case f64:
  969: 			AIT_SET_F64(v, va_arg(lst, double));
  970: 			break;
  971: 		case u8:
  972: 			AIT_SET_U8(v, (uint8_t) va_arg(lst, int));
  973: 			break;
  974: 		case u16:
  975: 			AIT_SET_U16(v, (uint16_t) va_arg(lst, int));
  976: 			break;
  977: 		case u32:
  978: 			AIT_SET_U32(v, va_arg(lst, uint32_t));
  979: 			break;
  980: 		case u64:
  981: 			AIT_SET_U64(v, va_arg(lst, uint64_t));
  982: 			break;
  983: 		case i8:
  984: 			AIT_SET_I8(v, (int8_t) va_arg(lst, int));
  985: 			break;
  986: 		case i16:
  987: 			AIT_SET_I16(v, (int16_t) va_arg(lst, int));
  988: 			break;
  989: 		case i32:
  990: 			AIT_SET_I32(v, va_arg(lst, int32_t));
  991: 			break;
  992: 		case i64:
  993: 			AIT_SET_I64(v, va_arg(lst, int64_t));
  994: 			break;
  995: 	}
  996: 	va_end(lst);
  997: 
  998: 	return v;
  999: }
 1000: 
 1001: static int
 1002: _cmp_arr_key_asc(const void *a, const void *b)
 1003: {
 1004: 	return AIT_KEY(*(ait_val_t**) a) - AIT_KEY(*(ait_val_t**) b);
 1005: }
 1006: 
 1007: static int
 1008: _cmp_arr_key_desc(const void *a, const void *b)
 1009: {
 1010: 	return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a);
 1011: }
 1012: 
 1013: static int
 1014: _cmp_arr_val_asc(const void *a, const void *b)
 1015: {
 1016: 	return AIT_RAW(*(ait_val_t**) a) - AIT_RAW(*(ait_val_t**) b);
 1017: }
 1018: 
 1019: static int
 1020: _cmp_arr_val_desc(const void *a, const void *b)
 1021: {
 1022: 	return AIT_RAW(*(ait_val_t**) b) - AIT_RAW(*(ait_val_t**) a);
 1023: }
 1024: 
 1025: /*
 1026:  * ait_sortVarsByVal() - Sorting array with variables by value
 1027:  *
 1028:  * @vars = Variable array
 1029:  * @order = Sort order. If =0 ascend or !=0 descend
 1030:  * @cmp = Custom compare function for sorting. If =NULL compare by value
 1031:  * return: none
 1032:  */
 1033: void
 1034: ait_sortVarsByVal(array_t * __restrict vars, int order,  int (*cmp)(const void*, const void*))
 1035: {
 1036: 	if (!vars)
 1037: 		return;
 1038: 
 1039: 	if (cmp)
 1040: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), cmp);
 1041: 	else if (order)
 1042: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_desc);
 1043: 	else
 1044: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_asc);
 1045: }
 1046: 
 1047: /*
 1048:  * ait_sortVarsByKey() - Sorting array with variables by key
 1049:  *
 1050:  * @vars = Variable array
 1051:  * @order = Sort order. If =0 ascend or !=0 descend
 1052:  * return: none
 1053:  */
 1054: void
 1055: ait_sortVarsByKey(array_t * __restrict vars, int order)
 1056: {
 1057: 	if (!vars)
 1058: 		return;
 1059: 
 1060: 	if (order)
 1061: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_desc);
 1062: 	else
 1063: 		qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
 1064: }
 1065: 
 1066: /*
 1067:  * ait_findKeyVars() - Find variable by key from array
 1068:  *
 1069:  * @vars = Variables
 1070:  * @key = Search key
 1071:  * return: NULL error or not found, !=NULL valid element
 1072:  */
 1073: ait_val_t *
 1074: ait_findKeyVars(array_t * __restrict vars, u_short key)
 1075: {
 1076: 	array_t *tmp;
 1077: 	ait_val_t **vv, *v = NULL;
 1078: 	register int i;
 1079: 	const u_char *p;
 1080: 
 1081: 	if (!vars)
 1082: 		return NULL;
 1083: 
 1084: 	if (array_Copy(&tmp, vars) == -1)
 1085: 		return NULL;
 1086: 	else
 1087: 		qsort(tmp->arr_data, tmp->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
 1088: 
 1089: 	/* binary search */
 1090: 	for (p = (const u_char*) tmp->arr_data, i = array_Size(tmp); i; i >>= 1) {
 1091: 		vv = (ait_val_t**) (p + (i >> 1) * sizeof(uintptr_t));
 1092: 		if (!(key - AIT_KEY(*vv))) {	/* found! */
 1093: 			v = *vv;
 1094: 			break;
 1095: 		}
 1096: 		if ((key - AIT_KEY(*vv)) > 0) {	/* move right key > current */
 1097: 			p = (const u_char*) vv + sizeof(uintptr_t);
 1098: 			i--;
 1099: 		}				/* else move left */
 1100: 	}
 1101: 
 1102: 	array_Destroy(&tmp);
 1103: 	return v;
 1104: }
 1105: 
 1106: /*
 1107:  * ait_hashVar() - Generate hash key for variable from string or value
 1108:  *
 1109:  * @v = variable
 1110:  * @key = key string for hash, if =NULL hash will built from variable
 1111:  * return: hash key
 1112:  */
 1113: u_short
 1114: ait_hashVar(ait_val_t * __restrict v, const char * __restrict key)
 1115: {
 1116: 	void *p;
 1117: 	u_short cksum;
 1118: 	int l;
 1119: 
 1120: 	if (!v)
 1121: 		return 0;
 1122: 
 1123: 	if (key) {
 1124: 		p = (void*) key;
 1125: 		l = (strlen(key) + 1) / 2;
 1126: 	} else {
 1127: 		switch (AIT_TYPE(v)) {
 1128: 			case empty:
 1129: 				AIT_KEY(v) = 0;
 1130: 				return 0;
 1131: 			case string:
 1132: 			case buffer:
 1133: 				p = AIT_ADDR(v);
 1134: 				l = AIT_LEN(v) / 2;
 1135: 				break;
 1136: 			case data:
 1137: 				p = v->val_data;
 1138: 				l = AIT_LEN(v) / 2;
 1139: 				break;
 1140: 			default:
 1141: 				p = &AIT_RAW(v);
 1142: 				l = sizeof AIT_RAW(v) / 2;
 1143: 				break;
 1144: 		}
 1145: 	}
 1146: 
 1147: 	cksum = crcFletcher16((u_short*) p, l);
 1148: 
 1149: 	if (AIT_BE(v))
 1150: 		AIT_KEY(v) = htobe16(cksum);
 1151: 	else if (AIT_LE(v))
 1152: 		AIT_KEY(v) = htole16(cksum);
 1153: 	else
 1154: 		AIT_KEY(v) = cksum;
 1155: 
 1156: 	return AIT_KEY(v);
 1157: }
 1158: 
 1159: /*
 1160:  * ait_hashKeyVars() - Generate hash keys for variables
 1161:  *
 1162:  * @vars = Variables
 1163:  * return -1 error or 0 ok
 1164:  */
 1165: int
 1166: ait_hashKeyVars(array_t * __restrict vars)
 1167: {
 1168: 	register int i;
 1169: 
 1170: 	if (!vars)
 1171: 		return -1;
 1172: 
 1173: 	for (i = 0; i < array_Size(vars); i++)
 1174: 		ait_hashVar(array(vars, i, ait_val_t*), NULL);
 1175: 
 1176: 	return 0;
 1177: }
 1178: 
 1179: /*
 1180:  * ait_findKeyHash() - Find variable by hash string from array
 1181:  *
 1182:  * @vars = Variables
 1183:  * @key = Search string
 1184:  * return: NULL error or not found, !=NULL valid element
 1185:  */
 1186: ait_val_t *
 1187: ait_findKeyHash(array_t * __restrict vars, const char * __restrict key)
 1188: {
 1189: 	u_short k = 0;
 1190: 
 1191: 	if (!vars || !key)
 1192: 		return NULL;
 1193: 
 1194: 	k = crcFletcher16((u_short*) key, (strlen(key) + 1) / 2);
 1195: 	return ait_findKeyVars(vars, k);
 1196: }
 1197: 
 1198: /*
 1199:  * ait_sprintfVar() - Builtin string variable from formatted input
 1200:  *
 1201:  * @v = variable
 1202:  * @fmt = format string
 1203:  * @... = argument(s)
 1204:  * return: -1 error or >0 copied bytes to variable
 1205:  */
 1206: int
 1207: ait_sprintfVar(ait_val_t * __restrict v, const char *fmt, ...)
 1208: {
 1209: 	int ret = 0;
 1210: 	va_list lst;
 1211: 	char str[STRSIZ] = { [0 ... STRSIZ - 1] = 0 };
 1212: 
 1213: 	if (!v || !fmt)
 1214: 		return -1;
 1215: 
 1216: 	va_start(lst, fmt);
 1217: 	ret = vsnprintf(str, sizeof str - 1, fmt, lst);
 1218: 	va_end(lst);
 1219: 
 1220: 	if (ret > -1) {
 1221: 		AIT_FREE_VAL(v);
 1222: 		AIT_SET_STR(v, str);
 1223: 	} else
 1224: 		LOGERR;
 1225: 
 1226: 	return ret;
 1227: }
 1228: 
 1229: /*
 1230:  * ait_setlikeVar() - Set variable like ...
 1231:  *
 1232:  * @v = variable
 1233:  * @t = type of data
 1234:  * @l = length of data
 1235:  * @... = data
 1236:  * return: -1 error or 0 ok
 1237:  */
 1238: int
 1239: ait_setlikeVar(ait_val_t * __restrict v, ait_type_t t, u_int l, ...)
 1240: {
 1241: 	va_list lst;
 1242: 
 1243: 	if (!v)
 1244: 		return -1;
 1245: 
 1246: 	AIT_FREE_VAL(v);
 1247: 	AIT_INIT_VAL2(v, t);
 1248: 	AIT_LEN(v) = l;
 1249: 	AIT_IN(v) = 1;
 1250: 
 1251: 	va_start(lst, l);
 1252: 	switch (AIT_TYPE(v)) {
 1253: 		case ptr:
 1254: 		case buffer:
 1255: 		case string:
 1256: 			AIT_ADDR(v) = va_arg(lst, void*);
 1257: 			break;
 1258: 		default:
 1259: 			AIT_RAW(v) = va_arg(lst, uint64_t);
 1260: 			break;
 1261: 	}
 1262: 	va_end(lst);
 1263: 
 1264: 	return 0;
 1265: }
 1266: 
 1267: /*
 1268:  * ait_getlikeVar() - Get variable like ...
 1269:  *
 1270:  * @v = variable
 1271:  * return: return raw data
 1272:  */
 1273: uint64_t
 1274: ait_getlikeVar(ait_val_t * __restrict v)
 1275: {
 1276: 	if (!v)
 1277: 		return (uintptr_t) -1;
 1278: 
 1279: 	return AIT_RAW(v);
 1280: }
 1281: 
 1282: /*
 1283:  * ait_cmpVar() - Compare two variables
 1284:  *
 1285:  * @a = 1st variable
 1286:  * @b = 2nd variable
 1287:  * return: 0 is equal or !=0 is different
 1288:  */
 1289: int
 1290: ait_cmpVar(ait_val_t * __restrict a, ait_val_t * __restrict b)
 1291: {
 1292: 	intptr_t ret;
 1293: 
 1294: 	if (!(ret = (a - b)))
 1295: 		return ret;
 1296: 	if ((ret = AIT_TYPE(a) - AIT_TYPE(b)))
 1297: 		return ret;
 1298: 	if ((ret = AIT_LEN(a) - AIT_LEN(b)))
 1299: 		return ret;
 1300: 
 1301: 	switch (AIT_TYPE(a)) {
 1302: 		case buffer:
 1303: 			ret = memcmp(AIT_GET_BUF(a), AIT_GET_BUF(b), AIT_LEN(a));
 1304: 			break;
 1305: 		case string:
 1306: 			ret = strncmp(AIT_GET_STR(a), AIT_GET_STR(b), AIT_LEN(a));
 1307: 			break;
 1308: 		case data:
 1309: 			ret = memcmp(AIT_GET_DATA(a), AIT_GET_DATA(b), AIT_LEN(a));
 1310: 			break;
 1311: 		case ptr:
 1312: 			ret = AIT_ADDR(a) - AIT_ADDR(b);
 1313: 			break;
 1314: 		default:
 1315: 			ret = AIT_RAW(a) - AIT_RAW(b);
 1316: 			break;
 1317: 	}
 1318: 
 1319: 	return (int) ret;
 1320: }

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