Annotation of libelwix/src/vars.c, revision 1.13
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.13 ! misho 6: * $Id: vars.c,v 1.12.6.1 2022/10/24 00:09:07 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.10 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.10 misho 252: /*
1.12 misho 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: /*
1.10 misho 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: /*
1.12 misho 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: /*
1.10 misho 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: }
1.1 misho 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: */
1.4 misho 628: int
1.1 misho 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: */
1.4 misho 644: array_t *
1.1 misho 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: */
1.4 misho 660: int
1.1 misho 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: */
1.4 misho 676: array_t *
1.1 misho 677: ait_map2vars(u_char *buf, int buflen, int vnum, int zcpy)
678: {
679: return buffer2vars(buf, buflen, vnum, zcpy);
680: }
681:
1.10 misho 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: }
1.1 misho 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: */
1.4 misho 740: array_t *
1.1 misho 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: */
1.4 misho 768: ait_val_t *
1.1 misho 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: */
1.4 misho 801: int
1.1 misho 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: */
1.4 misho 823: void
1.1 misho 824: ait_freeVars(array_t ** __restrict vars)
825: {
1.6 misho 826: register int i;
827: ait_val_t *v;
828:
1.1 misho 829: if (!vars || !*vars)
830: return;
831:
1.6 misho 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:
1.1 misho 845: array_Destroy(vars);
846: }
847:
1.5 misho 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:
1.1 misho 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: */
1.4 misho 884: ait_val_t *
1.1 misho 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: */
1.4 misho 905: void
1.1 misho 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: */
1.4 misho 1033: void
1.1 misho 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)
1.2 misho 1040: qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), cmp);
1.1 misho 1041: else if (order)
1.2 misho 1042: qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_desc);
1.1 misho 1043: else
1.2 misho 1044: qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_asc);
1.1 misho 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: */
1.4 misho 1054: void
1.1 misho 1055: ait_sortVarsByKey(array_t * __restrict vars, int order)
1056: {
1057: if (!vars)
1058: return;
1059:
1060: if (order)
1.2 misho 1061: qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_desc);
1.1 misho 1062: else
1.2 misho 1063: qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
1.1 misho 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
1.2 misho 1087: qsort(tmp->arr_data, tmp->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
1.1 misho 1088:
1089: /* binary search */
1090: for (p = (const u_char*) tmp->arr_data, i = array_Size(tmp); i; i >>= 1) {
1.2 misho 1091: vv = (ait_val_t**) (p + (i >> 1) * sizeof(uintptr_t));
1.1 misho 1092: if (!(key - AIT_KEY(*vv))) { /* found! */
1093: v = *vv;
1094: break;
1095: }
1096: if ((key - AIT_KEY(*vv)) > 0) { /* move right key > current */
1.2 misho 1097: p = (const u_char*) vv + sizeof(uintptr_t);
1.1 misho 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: */
1.4 misho 1165: int
1.1 misho 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: */
1.4 misho 1186: ait_val_t *
1.1 misho 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
1.2 misho 1207: ait_sprintfVar(ait_val_t * __restrict v, const char *fmt, ...)
1.1 misho 1208: {
1209: int ret = 0;
1210: va_list lst;
1.13 ! misho 1211: char str[65536] = { [0 ... 65535] = 0 };
1.1 misho 1212:
1213: if (!v || !fmt)
1214: return -1;
1215:
1216: va_start(lst, fmt);
1.9 misho 1217: ret = vsnprintf(str, sizeof str - 1, fmt, lst);
1.1 misho 1218: va_end(lst);
1219:
1.9 misho 1220: if (ret > -1) {
1.1 misho 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: */
1.4 misho 1238: int
1.1 misho 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: */
1.4 misho 1273: uint64_t
1.1 misho 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: */
1.4 misho 1289: int
1.1 misho 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>