--- libaitio/src/Attic/vars.c 2012/05/14 16:16:03 1.7 +++ libaitio/src/Attic/vars.c 2012/08/01 00:37:08 1.12 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: vars.c,v 1.7 2012/05/14 16:16:03 misho Exp $ +* $Id: vars.c,v 1.12 2012/08/01 00:37:08 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -46,16 +46,8 @@ SUCH DAMAGE. #include "global.h" -/* - * io_vars2buffer() - Marshaling data from array with variables to buffer - * - * @buf = Buffer - * @buflen = Size of buffer - * @vars = Variable array - * return: -1 error, 0 nothing done or >0 size of marshaled data - */ -int -io_vars2buffer(u_char *buf, int buflen, array_t *vars) +static int +vars2buffer(u_char * __restrict buf, int buflen, int be, array_t * __restrict vars) { int Limit = 0; register int i; @@ -68,6 +60,7 @@ io_vars2buffer(u_char *buf, int buflen, array_t *vars) return -1; if (!buflen || !io_arraySize(vars)) return 0; + be = !!be; Limit = sizeof(ait_val_t) * io_arraySize(vars); if (Limit > buflen) { @@ -86,8 +79,17 @@ io_vars2buffer(u_char *buf, int buflen, array_t *vars) val = io_array(vars, i, ait_val_t*); v[i].val_type = val->val_type; - AIT_KEY(&v[i]) = htobe16(AIT_KEY(val)); - AIT_LEN(&v[i]) = htobe32(AIT_LEN(val)); + AIT_IN(&v[i]) = 1; + AIT_BE(&v[i]) = be; + AIT_LE(&v[i]) = !be; + if (AIT_BE(&v[i])) { + AIT_KEY(&v[i]) = htobe16(AIT_KEY(val)); + AIT_LEN(&v[i]) = htobe32(AIT_LEN(val)); + } + if (AIT_LE(&v[i])) { + AIT_KEY(&v[i]) = htole16(AIT_KEY(val)); + AIT_LEN(&v[i]) = htole32(AIT_LEN(val)); + } switch (AIT_TYPE(val)) { case blob: @@ -101,7 +103,10 @@ io_vars2buffer(u_char *buf, int buflen, array_t *vars) case u16: case u32: case u64: - v[i].val.net = htobe64(val->val.net); + if (AIT_BE(&v[i])) + v[i].val.net = htobe64(val->val.net); + if (AIT_LE(&v[i])) + v[i].val.net = htole64(val->val.net); break; case data: if (AIT_LEN(val) > buflen - Limit) { @@ -140,18 +145,8 @@ io_vars2buffer(u_char *buf, int buflen, array_t *vars) return Limit; } -/* - * io_buffer2vars() - De-marshaling data from buffer to array with variables - * - * @buf = Buffer - * @buflen = Size of buffer - * @vnum = Number of variables into buffer - * @zcpy = Zero-copy for variables, if !=0 don't use io_arrayFree() for free variables and - *DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy() - * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy() - */ -array_t * -io_buffer2vars(u_char *buf, int buflen, int vnum, int zcpy) +static array_t * +buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy) { array_t *vars; int Limit = 0; @@ -179,25 +174,31 @@ io_buffer2vars(u_char *buf, int buflen, int vnum, int /* de-marshaling */ for (i = 0; i < io_arraySize(vars); i++) { if (!zcpy) { - val = malloc(sizeof(ait_val_t)); + val = io_malloc(sizeof(ait_val_t)); if (!val) { LOGERR; io_arrayFree(vars); io_arrayDestroy(&vars); return NULL; } - } else + AIT_IN(val) = 0; + } else { val = v + i; + AIT_IN(val) = 1; + } io_arraySet(vars, i, val); val->val_type = v[i].val_type; -#if defined(__OpenBSD__) - AIT_LEN(val) = betoh32(AIT_LEN(&v[i])); - AIT_KEY(val) = betoh16(AIT_KEY(&v[i])); -#else - AIT_LEN(val) = be32toh(AIT_LEN(&v[i])); - AIT_KEY(val) = be16toh(AIT_KEY(&v[i])); -#endif + AIT_BE(val) = AIT_BE(&v[i]); + AIT_LE(val) = AIT_LE(&v[i]); + if (AIT_BE(val)) { + AIT_LEN(val) = be32toh(AIT_LEN(&v[i])); + AIT_KEY(val) = be16toh(AIT_KEY(&v[i])); + } + if (AIT_LE(val)) { + AIT_LEN(val) = le32toh(AIT_LEN(&v[i])); + AIT_KEY(val) = le16toh(AIT_KEY(&v[i])); + } switch (AIT_TYPE(val)) { case blob: @@ -211,11 +212,10 @@ io_buffer2vars(u_char *buf, int buflen, int vnum, int case u16: case u32: case u64: -#if defined(__OpenBSD__) - val->val.net = betoh64(v[i].val.net); -#else - val->val.net = be64toh(v[i].val.net); -#endif + if (AIT_BE(val)) + val->val.net = be64toh(v[i].val.net); + if (AIT_LE(val)) + val->val.net = le64toh(v[i].val.net); break; case data: /* WARNING:: remap data type to buffer */ @@ -233,7 +233,7 @@ io_buffer2vars(u_char *buf, int buflen, int vnum, int Limit += AIT_LEN(val); if (!zcpy) { - val->val.buffer = malloc(AIT_LEN(val)); + val->val.buffer = io_malloc(AIT_LEN(val)); if (!val->val.buffer) { LOGERR; io_arrayFree(vars); @@ -258,100 +258,53 @@ io_buffer2vars(u_char *buf, int buflen, int vnum, int return vars; } -/* buffer marshaling without swapping bytes to network order */ +/* buffer marshaling with swapping bytes to network order */ + /* - * io_vars2map() - Marshaling data from array with variables to memory map + * io_vars2buffer() - Marshaling data from array with variables to buffer * * @buf = Buffer * @buflen = Size of buffer * @vars = Variable array * return: -1 error, 0 nothing done or >0 size of marshaled data */ -int -io_vars2map(u_char *buf, int buflen, array_t *vars) +inline int +io_vars2buffer(u_char * __restrict buf, int buflen, array_t * __restrict vars) { - int Limit = 0; - register int i; - ait_val_t *v, *val; - u_char *dat; + return vars2buffer(buf, buflen, 42, vars); +} - assert(buf); - assert(vars); - if (!buf || !vars) - return -1; - if (!buflen || !io_arraySize(vars)) - return 0; +/* + * io_buffer2vars() - De-marshaling data from buffer to array with variables + * + * @buf = Buffer + * @buflen = Size of buffer + * @vnum = Number of variables into buffer + * @zcpy = Zero-copy for variables, if !=0 don't use io_arrayFree() for free variables and + *DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy() + * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy() + */ +inline array_t * +io_buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy) +{ + return buffer2vars(buf, buflen, vnum, zcpy); +} - Limit = sizeof(ait_val_t) * io_arraySize(vars); - if (Limit > buflen) { - io_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", - buflen, Limit); - return -1; - } else { - memset(buf, 0, buflen); +/* buffer marshaling without swapping bytes to network order */ - v = (ait_val_t*) buf; - dat = buf + Limit; - } - - /* marshaling */ - for (i = 0; i < io_arraySize(vars); i++) { - val = io_array(vars, i, ait_val_t*); - - v[i].val_type = val->val_type; - AIT_KEY(&v[i]) = AIT_KEY(val); - AIT_LEN(&v[i]) = AIT_LEN(val); - - switch (AIT_TYPE(val)) { - case blob: - case f32: - case f64: - case i8: - case i16: - case i32: - case i64: - case u8: - case u16: - case u32: - case u64: - v[i].val.net = val->val.net; - break; - case data: - if (AIT_LEN(val) > buflen - Limit) { - io_SetErr(EMSGSIZE, "Short buffer buflen=%d " - "needed min %d", buflen, Limit + AIT_LEN(val)); - return -1; - } else - Limit += AIT_LEN(val); - - memcpy(dat, val->val_data, AIT_LEN(val)); - /* Debug:: data offset in packet, not matter for anything! */ - v[i].val.net = dat - buf; - dat += AIT_LEN(val); - break; - case buffer: - case string: - if (AIT_LEN(val) > buflen - Limit) { - io_SetErr(EMSGSIZE, "Short buffer buflen=%d " - "needed min %d", buflen, Limit + AIT_LEN(val)); - return -1; - } else - Limit += AIT_LEN(val); - - memcpy(dat, val->val.buffer, AIT_LEN(val)); - /* Debug:: data offset in packet, not matter for anything! */ - v[i].val.net = dat - buf; - dat += AIT_LEN(val); - break; - default: - io_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", - AIT_TYPE(val), i); - return -1; - } - } - - return Limit; +/* + * io_vars2map() - Marshaling data from array with variables to memory map + * + * @buf = Buffer + * @buflen = Size of buffer + * @vars = Variable array + * return: -1 error, 0 nothing done or >0 size of marshaled data + */ +inline int +io_vars2map(u_char *buf, int buflen, array_t *vars) +{ + return vars2buffer(buf, buflen, 0, vars); } /* @@ -364,103 +317,10 @@ io_vars2map(u_char *buf, int buflen, array_t *vars) *DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy() * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy() */ -array_t * +inline array_t * io_map2vars(u_char *buf, int buflen, int vnum, int zcpy) { - array_t *vars; - int Limit = 0; - register int i; - ait_val_t *v, *val; - u_char *dat; - - assert(buf); - if (!buf || !buflen || !vnum) - return NULL; - - Limit = sizeof(ait_val_t) * vnum; - if (Limit > buflen) { - io_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", - buflen, Limit); - return NULL; - } else { - if (!(vars = io_arrayInit(vnum))) - return NULL; - - v = (ait_val_t*) buf; - dat = buf + Limit; - } - - /* de-marshaling */ - for (i = 0; i < io_arraySize(vars); i++) { - if (!zcpy) { - val = malloc(sizeof(ait_val_t)); - if (!val) { - LOGERR; - io_arrayFree(vars); - io_arrayDestroy(&vars); - return NULL; - } - } else - val = v + i; - io_arraySet(vars, i, val); - - val->val_type = v[i].val_type; - AIT_KEY(val) = AIT_KEY(&v[i]); - AIT_LEN(val) = AIT_LEN(&v[i]); - - switch (AIT_TYPE(val)) { - case blob: - case f32: - case f64: - case i8: - case i16: - case i32: - case i64: - case u8: - case u16: - case u32: - case u64: - val->val.net = v[i].val.net; - break; - case data: - /* WARNING:: remap data type to buffer */ - val->val_type = buffer; - case buffer: - case string: - if (AIT_LEN(val) > buflen - Limit) { - io_SetErr(EMSGSIZE, "short buffer buflen=%d " - "needed min %d", buflen, Limit + AIT_LEN(val)); - if (!zcpy) - io_arrayFree(vars); - io_arrayDestroy(&vars); - return NULL; - } else - Limit += AIT_LEN(val); - - if (!zcpy) { - val->val.buffer = malloc(AIT_LEN(val)); - if (!val->val.buffer) { - LOGERR; - io_arrayFree(vars); - io_arrayDestroy(&vars); - return NULL; - } else - memcpy(val->val.buffer, dat, AIT_LEN(val)); - } else - val->val.buffer = dat; - dat += AIT_LEN(val); - break; - default: - io_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", - AIT_TYPE(val), i); - if (!zcpy) - io_arrayFree(vars); - io_arrayDestroy(&vars); - return NULL; - } - } - - return vars; + return buffer2vars(buf, buflen, vnum, zcpy); } @@ -477,7 +337,7 @@ io_allocVars(int varnum) register int i; ait_val_t *v; - if (!varnum || !(arr = io_arrayInit(varnum))) + if (!(arr = io_arrayInit(varnum))) return NULL; for (i = 0; i < io_arraySize(arr); i++) { @@ -492,6 +352,42 @@ io_allocVars(int varnum) } /* + * io_getVars() - Get ait_val_t element from array and if not exists allocate it + * + * @vars = Variable array + * @n = index of variable into array + * return: NULL error or !=NULL ait_val_t element + */ +inline ait_val_t * +io_getVars(array_t ** __restrict vars, int n) +{ + register int i; + ait_val_t *v; + + if (!vars) + return NULL; + + if (!*vars) { + if (!(*vars = io_allocVars(n + 1))) + return NULL; + } else { + if (n >= (i = io_arraySize(*vars))) { + if (io_arrayGrow(*vars, n + 1, 0)) + return NULL; + for (; i < io_arraySize(*vars); i++) + if (!io_arrayGet(*vars, i)) { + if (!(v = io_allocVar())) + return NULL; + else + io_arraySet(*vars, n, v); + } + } + } + + return io_array(*vars, n, ait_val_t*); +} + +/* * io_clrVars() - Clear ait_val_t elements from array * * @vars = Variable array @@ -540,7 +436,7 @@ io_allocVar(void) { ait_val_t *v = NULL; - v = malloc(sizeof(ait_val_t)); + v = io_malloc(sizeof(ait_val_t)); if (!v) { LOGERR; return NULL; @@ -562,11 +458,97 @@ io_freeVar(ait_val_t ** __restrict val) { if (val && *val) { AIT_FREE_VAL(*val); - free(*val); + io_free(*val); *val = NULL; } } +/* + * io_makeVar() - Allocate memory and fill variable + * + * @type = type of variable + * @... = arg1 is value of variable + * @... = arg2 is length of variabla. Not required for numbers and strings! + * return: NULL error or new variable, after use free variable with io_freeVar() + */ +ait_val_t * +io_makeVar(ait_type_t type, ...) +{ + ait_val_t *v = NULL; + va_list lst; + void *p = NULL; + uint32_t len = 0; + uint64_t n = 0LL; + + v = io_allocVar(); + if (!v) + return NULL; + + va_start(lst, type); + switch (type) { + case empty: + v->val_type = (uint8_t) empty; + break; + case ptr: + p = va_arg(lst, void*); + len = va_arg(lst, uint32_t); + AIT_SET_PTR(v, p, len); + break; + case data: + p = va_arg(lst, void*); + len = va_arg(lst, uint32_t); + AIT_SET_DATA(v, p, len); + break; + case buffer: + p = va_arg(lst, void*); + len = va_arg(lst, uint32_t); + AIT_SET_BUF(v, p, len); + break; + case string: + p = va_arg(lst, char*); + AIT_SET_STR(v, (char*) p); + break; + case blob: + n = va_arg(lst, uint32_t); + len = va_arg(lst, uint32_t); + AIT_SET_BLOB(v, n, len); + break; + case f32: + AIT_SET_F32(v, (float) va_arg(lst, double)); + break; + case f64: + AIT_SET_F64(v, va_arg(lst, double)); + break; + case u8: + AIT_SET_U8(v, (uint8_t) va_arg(lst, int)); + break; + case u16: + AIT_SET_U16(v, (uint16_t) va_arg(lst, int)); + break; + case u32: + AIT_SET_U32(v, va_arg(lst, uint32_t)); + break; + case u64: + AIT_SET_U64(v, va_arg(lst, uint64_t)); + break; + case i8: + AIT_SET_I8(v, (int8_t) va_arg(lst, int)); + break; + case i16: + AIT_SET_I16(v, (int16_t) va_arg(lst, int)); + break; + case i32: + AIT_SET_I32(v, va_arg(lst, int32_t)); + break; + case i64: + AIT_SET_I64(v, va_arg(lst, int64_t)); + break; + } + va_end(lst); + + return v; +} + static int _cmp_arr_key_asc(const void *a, const void *b) { @@ -579,16 +561,28 @@ _cmp_arr_key_desc(const void *a, const void *b) return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a); } +static int +_cmp_arr_val_asc(const void *a, const void *b) +{ + return AIT_RAW(*(ait_val_t**) a) - AIT_RAW(*(ait_val_t**) b); +} + +static int +_cmp_arr_val_desc(const void *a, const void *b) +{ + return AIT_RAW(*(ait_val_t**) b) - AIT_RAW(*(ait_val_t**) a); +} + /* - * io_sortVars() - Sorting array with variables + * io_sortVarsByVal() - Sorting array with variables by value * * @vars = Variable array * @order = Sort order. If =0 ascend or !=0 descend - * @cmp = Compare function for sorting. If =NULL compare by key + * @cmp = Custom compare function for sorting. If =NULL compare by value * return: none */ inline void -io_sortVars(array_t * __restrict vars, int order, int (*cmp)(const void*, const void*)) +io_sortVarsByVal(array_t * __restrict vars, int order, int (*cmp)(const void*, const void*)) { if (!vars) return; @@ -596,6 +590,25 @@ io_sortVars(array_t * __restrict vars, int order, int if (cmp) qsort(vars->arr_data, vars->arr_num, sizeof(void*), cmp); else if (order) + qsort(vars->arr_data, vars->arr_num, sizeof(void*), _cmp_arr_val_desc); + else + qsort(vars->arr_data, vars->arr_num, sizeof(void*), _cmp_arr_val_asc); +} + +/* + * io_sortVarsByKey() - Sorting array with variables by key + * + * @vars = Variable array + * @order = Sort order. If =0 ascend or !=0 descend + * return: none + */ +inline void +io_sortVarsByKey(array_t * __restrict vars, int order) +{ + if (!vars) + return; + + if (order) qsort(vars->arr_data, vars->arr_num, sizeof(void*), _cmp_arr_key_desc); else qsort(vars->arr_data, vars->arr_num, sizeof(void*), _cmp_arr_key_asc);