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