Annotation of libelwix/src/vars.c, revision 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>