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