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