version 1.2, 2011/10/31 13:53:51
|
version 1.13.2.5, 2012/09/17 14:01:34
|
Line 12 terms:
|
Line 12 terms:
|
All of the documentation and software included in the ELWIX and AITNET |
All of the documentation and software included in the ELWIX and AITNET |
Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> |
Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> |
|
|
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 | Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 |
by Michael Pounov <misho@elwix.org>. All rights reserved. |
by Michael Pounov <misho@elwix.org>. All rights reserved. |
|
|
Redistribution and use in source and binary forms, with or without |
Redistribution and use in source and binary forms, with or without |
Line 46 SUCH DAMAGE.
|
Line 46 SUCH DAMAGE.
|
#include "global.h" |
#include "global.h" |
|
|
|
|
/* | static int |
* io_vals2buffer() Marshaling data from array with variables to buffer | vars2buffer(u_char * __restrict buf, int buflen, int be, array_t * __restrict vars) |
* @buf = Buffer | |
* @buflen = Size of buffer | |
* @vars = Variable array | |
* return: -1 error, 0 nothing done or >0 size of marshaled data | |
*/ | |
int | |
io_vals2buffer(u_char *buf, int buflen, array_t *vars) | |
{ |
{ |
int Limit = 0; |
int Limit = 0; |
register int i; |
register int i; |
ait_val_t *v, *val; |
ait_val_t *v, *val; |
u_char *data; | u_char *dat; |
|
|
assert(buf); |
assert(buf); |
assert(vars); |
assert(vars); |
Line 67 io_vals2buffer(u_char *buf, int buflen, array_t *vars)
|
Line 60 io_vals2buffer(u_char *buf, int buflen, array_t *vars)
|
return -1; |
return -1; |
if (!buflen || !io_arraySize(vars)) |
if (!buflen || !io_arraySize(vars)) |
return 0; |
return 0; |
|
be = !!be; |
|
|
Limit = sizeof(ait_val_t) * io_arraySize(vars); |
Limit = sizeof(ait_val_t) * io_arraySize(vars); |
if (Limit > buflen) { |
if (Limit > buflen) { |
io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", | io_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", |
buflen, Limit); |
buflen, Limit); |
return -1; |
return -1; |
} else { |
} else { |
memset(buf, 0, buflen); |
memset(buf, 0, buflen); |
|
|
v = (ait_val_t*) buf; |
v = (ait_val_t*) buf; |
data = buf + Limit; | dat = buf + Limit; |
} |
} |
|
|
/* marshaling */ |
/* marshaling */ |
Line 85 io_vals2buffer(u_char *buf, int buflen, array_t *vars)
|
Line 79 io_vals2buffer(u_char *buf, int buflen, array_t *vars)
|
val = io_array(vars, i, ait_val_t*); |
val = io_array(vars, i, ait_val_t*); |
|
|
v[i].val_type = val->val_type; |
v[i].val_type = val->val_type; |
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)) { |
switch (AIT_TYPE(val)) { |
case blob: |
case blob: |
Line 99 io_vals2buffer(u_char *buf, int buflen, array_t *vars)
|
Line 103 io_vals2buffer(u_char *buf, int buflen, array_t *vars)
|
case u16: |
case u16: |
case u32: |
case u32: |
case u64: |
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; |
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 buffer: |
case string: |
case string: |
if (AIT_LEN(val) > buflen - Limit) { |
if (AIT_LEN(val) > buflen - Limit) { |
io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d " | io_SetErr(EMSGSIZE, "Short buffer buflen=%d " |
"needed min %d ...\n", buflen, Limit + AIT_LEN(val)); | "needed min %d", buflen, Limit + AIT_LEN(val)); |
return -1; |
return -1; |
} else |
} else |
Limit += AIT_LEN(val); |
Limit += AIT_LEN(val); |
|
|
memcpy(data, val->val.buffer, AIT_LEN(val)); | memcpy(dat, val->val.buffer, AIT_LEN(val)); |
/* Debug:: data offset in packet, not matter for anything! */ |
/* Debug:: data offset in packet, not matter for anything! */ |
v[i].val.net = data - buf; | v[i].val.net = dat - buf; |
data += AIT_LEN(val); | dat += AIT_LEN(val); |
break; |
break; |
default: |
default: |
io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", | io_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", |
AIT_TYPE(val), i); |
AIT_TYPE(val), i); |
return -1; |
return -1; |
} |
} |
Line 125 io_vals2buffer(u_char *buf, int buflen, array_t *vars)
|
Line 145 io_vals2buffer(u_char *buf, int buflen, array_t *vars)
|
return Limit; |
return Limit; |
} |
} |
|
|
/* | static array_t * |
* io_buffer2vals() De-marshaling data from buffer to array with variables | buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy) |
* @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_buffer2vals(u_char *buf, int buflen, int vnum, int zcpy) | |
{ |
{ |
array_t *vars; |
array_t *vars; |
int Limit = 0; |
int Limit = 0; |
register int i; |
register int i; |
ait_val_t *v, *val; |
ait_val_t *v, *val; |
u_char *data; | u_char *dat; |
|
|
assert(buf); |
assert(buf); |
if (!buf || !buflen || !vnum) |
if (!buf || !buflen || !vnum) |
Line 149 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
Line 160 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
|
|
Limit = sizeof(ait_val_t) * vnum; |
Limit = sizeof(ait_val_t) * vnum; |
if (Limit > buflen) { |
if (Limit > buflen) { |
io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", | io_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", |
buflen, Limit); |
buflen, Limit); |
return NULL; |
return NULL; |
} else { |
} else { |
Line 157 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
Line 168 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
return NULL; |
return NULL; |
|
|
v = (ait_val_t*) buf; |
v = (ait_val_t*) buf; |
data = buf + Limit; | dat = buf + Limit; |
} |
} |
|
|
/* de-marshaling */ |
/* de-marshaling */ |
for (i = 0; i < io_arraySize(vars); i++) { |
for (i = 0; i < io_arraySize(vars); i++) { |
if (!zcpy) { |
if (!zcpy) { |
val = malloc(sizeof(ait_val_t)); | val = io_malloc(sizeof(ait_val_t)); |
if (!val) { |
if (!val) { |
LOGERR; |
LOGERR; |
io_arrayFree(vars); |
io_arrayFree(vars); |
io_arrayDestroy(&vars); |
io_arrayDestroy(&vars); |
return NULL; |
return NULL; |
} |
} |
} else | AIT_IN(val) = 0; |
| } else { |
val = v + i; |
val = v + i; |
|
AIT_IN(val) = 1; |
|
} |
io_arraySet(vars, i, val); |
io_arraySet(vars, i, val); |
|
|
val->val_type = v[i].val_type; |
val->val_type = v[i].val_type; |
#if defined(__OpenBSD__) | AIT_BE(val) = AIT_BE(&v[i]); |
AIT_LEN(val) = betoh32(AIT_LEN(&v[i])); | AIT_LE(val) = AIT_LE(&v[i]); |
#else | if (AIT_BE(val)) { |
AIT_LEN(val) = be32toh(AIT_LEN(&v[i])); | AIT_LEN(val) = be32toh(AIT_LEN(&v[i])); |
#endif | 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)) { |
switch (AIT_TYPE(val)) { |
case blob: |
case blob: |
Line 193 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
Line 212 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
case u16: |
case u16: |
case u32: |
case u32: |
case u64: |
case u64: |
#if defined(__OpenBSD__) | if (AIT_BE(val)) |
val->val.net = betoh64(v[i].val.net); | val->val.net = be64toh(v[i].val.net); |
#else | if (AIT_LE(val)) |
val->val.net = be64toh(v[i].val.net); | val->val.net = le64toh(v[i].val.net); |
#endif | |
break; |
break; |
|
case data: |
|
/* WARNING:: remap data type to buffer */ |
|
val->val_type = buffer; |
case buffer: |
case buffer: |
case string: |
case string: |
if (AIT_LEN(val) > buflen - Limit) { |
if (AIT_LEN(val) > buflen - Limit) { |
io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d " | io_SetErr(EMSGSIZE, "Short buffer buflen=%d " |
"needed min %d ...\n", buflen, Limit + AIT_LEN(val)); | "needed min %d", buflen, Limit + AIT_LEN(val)); |
if (!zcpy) |
if (!zcpy) |
io_arrayFree(vars); |
io_arrayFree(vars); |
io_arrayDestroy(&vars); |
io_arrayDestroy(&vars); |
Line 212 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
Line 233 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
Limit += AIT_LEN(val); |
Limit += AIT_LEN(val); |
|
|
if (!zcpy) { |
if (!zcpy) { |
val->val.buffer = malloc(AIT_LEN(val)); | val->val.buffer = io_malloc(AIT_LEN(val)); |
if (!val->val.buffer) { |
if (!val->val.buffer) { |
LOGERR; |
LOGERR; |
io_arrayFree(vars); |
io_arrayFree(vars); |
io_arrayDestroy(&vars); |
io_arrayDestroy(&vars); |
return NULL; |
return NULL; |
} else |
} else |
memcpy(val->val.buffer, data, AIT_LEN(val)); | memcpy(val->val.buffer, dat, AIT_LEN(val)); |
} else |
} else |
val->val.buffer = data; | val->val.buffer = dat; |
data += AIT_LEN(val); | dat += AIT_LEN(val); |
break; |
break; |
default: |
default: |
io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", | io_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", |
AIT_TYPE(val), i); |
AIT_TYPE(val), i); |
if (!zcpy) |
if (!zcpy) |
io_arrayFree(vars); |
io_arrayFree(vars); |
Line 237 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
Line 258 io_buffer2vals(u_char *buf, int buflen, int vnum, int
|
return vars; |
return vars; |
} |
} |
|
|
|
|
|
/* buffer marshaling with swapping bytes to network order */ |
|
|
|
/* |
|
* 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 |
|
*/ |
|
inline int |
|
io_vars2buffer(u_char * __restrict buf, int buflen, array_t * __restrict vars) |
|
{ |
|
return vars2buffer(buf, buflen, 42, vars); |
|
} |
|
|
|
/* |
|
* 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); |
|
} |
|
|
/* buffer marshaling without swapping bytes to network order */ |
/* buffer marshaling without swapping bytes to network order */ |
|
|
/* |
/* |
* io_vals2map() Marshaling data from array with variables to memory map | * io_vars2map() - Marshaling data from array with variables to memory map |
| * |
* @buf = Buffer |
* @buf = Buffer |
* @buflen = Size of buffer |
* @buflen = Size of buffer |
* @vars = Variable array |
* @vars = Variable array |
* return: -1 error, 0 nothing done or >0 size of marshaled data |
* return: -1 error, 0 nothing done or >0 size of marshaled data |
*/ |
*/ |
int | inline int |
io_vals2map(u_char *buf, int buflen, array_t *vars) | io_vars2map(u_char *buf, int buflen, array_t *vars) |
{ |
{ |
int Limit = 0; | return vars2buffer(buf, buflen, 0, vars); |
register int i; | } |
ait_val_t *v, *val; | |
u_char *data; | |
|
|
assert(buf); | /* |
assert(vars); | * io_map2vars() - De-marshaling data from memory map to array with variables |
if (!buf || !vars) | * |
return -1; | * @buf = Buffer |
if (!buflen || !io_arraySize(vars)) | * @buflen = Size of buffer |
return 0; | * @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_map2vars(u_char *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, "Error:: too short buffer buflen=%d needed min %d ...\n", |
|
buflen, Limit); |
|
return -1; |
|
} else { |
|
memset(buf, 0, buflen); |
|
|
|
v = (ait_val_t*) buf; | /* |
data = buf + Limit; | * io_allocVars() - Allocate ait_val_t array |
| * |
| * @varnum = Number of variables |
| * return: =NULL error or !=NULL allocated array |
| */ |
| inline array_t * |
| io_allocVars(int varnum) |
| { |
| array_t *arr; |
| register int i; |
| ait_val_t *v; |
| |
| if (!(arr = io_arrayInit(varnum))) |
| return NULL; |
| |
| for (i = 0; i < io_arraySize(arr); i++) { |
| if (!(v = io_allocVar())) { |
| io_freeVars(&arr); |
| return NULL; |
| } else |
| io_arraySet(arr, i, v); |
} |
} |
|
|
/* marshaling */ | return arr; |
for (i = 0; i < io_arraySize(vars); i++) { | } |
val = io_array(vars, i, ait_val_t*); | |
|
|
v[i].val_type = val->val_type; | /* |
AIT_LEN(&v[i]) = AIT_LEN(val); | * 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; |
|
|
switch (AIT_TYPE(val)) { | if (!vars) |
case blob: | return NULL; |
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 buffer: | |
case string: | |
if (AIT_LEN(val) > buflen - Limit) { | |
io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d " | |
"needed min %d ...\n", buflen, Limit + AIT_LEN(val)); | |
return -1; | |
} else | |
Limit += AIT_LEN(val); | |
|
|
memcpy(data, val->val.buffer, AIT_LEN(val)); | if (!*vars) { |
/* Debug:: data offset in packet, not matter for anything! */ | if (!(*vars = io_allocVars(n + 1))) |
v[i].val.net = data - buf; | return NULL; |
data += AIT_LEN(val); | } else { |
break; | if (n >= (i = io_arraySize(*vars))) { |
default: | if (io_arrayGrow(*vars, n + 1, 0)) |
io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", | return NULL; |
AIT_TYPE(val), i); | for (; i < io_arraySize(*vars); i++) |
return -1; | if (!io_arrayGet(*vars, i)) { |
| if (!(v = io_allocVar())) |
| return NULL; |
| else |
| io_arraySet(*vars, n, v); |
| } |
} |
} |
} |
} |
|
|
return Limit; | return io_array(*vars, n, ait_val_t*); |
} |
} |
|
|
/* |
/* |
* io_map2vals() De-marshaling data from memory map to array with variables | * io_clrVars() - Clear ait_val_t elements from array |
* @buf = Buffer | * |
* @buflen = Size of buffer | * @vars = Variable array |
* @vnum = Number of variables into buffer | * return: -1 error or size of array |
* @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 * | inline int |
io_map2vals(u_char *buf, int buflen, int vnum, int zcpy) | io_clrVars(array_t * __restrict vars) |
{ |
{ |
array_t *vars; |
|
int Limit = 0; |
|
register int i; |
register int i; |
ait_val_t *v, *val; | ait_val_t *v; |
u_char *data; | |
|
|
assert(buf); | if (!vars) |
if (!buf || !buflen || !vnum) | return -1; |
| |
| for (i = 0; i < io_arraySize(vars); i++) |
| if ((v = io_array(vars, i, ait_val_t*))) |
| AIT_FREE_VAL(v); |
| |
| return io_arraySize(vars); |
| } |
| |
| /* |
| * io_freeVars() - Free ait_val_t array |
| * |
| * @vars = Variable array |
| * return: none |
| */ |
| inline void |
| io_freeVars(array_t ** __restrict vars) |
| { |
| if (!vars || !*vars) |
| return; |
| |
| io_clrVars(*vars); |
| io_arrayFree(*vars); |
| io_arrayDestroy(vars); |
| } |
| |
| /* |
| * io_allocVar() - Allocate memory for variable |
| * |
| * return: NULL error or new variable, after use free variable with io_freeVar() |
| */ |
| inline ait_val_t * |
| io_allocVar(void) |
| { |
| ait_val_t *v = NULL; |
| |
| v = io_malloc(sizeof(ait_val_t)); |
| if (!v) { |
| LOGERR; |
return NULL; |
return NULL; |
|
} else |
|
memset(v, 0, sizeof(ait_val_t)); |
|
v->val_type = empty; |
|
|
Limit = sizeof(ait_val_t) * vnum; | return v; |
if (Limit > buflen) { | } |
io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", | |
buflen, Limit); | /* |
| * io_freeVar() - Free allocated memory for variable |
| * |
| * @val = Variable |
| * return: none |
| */ |
| inline void |
| io_freeVar(ait_val_t ** __restrict val) |
| { |
| if (val && *val) { |
| AIT_FREE_VAL(*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; |
return NULL; |
} else { |
|
if (!(vars = io_arrayInit(vnum))) |
|
return NULL; |
|
|
|
v = (ait_val_t*) buf; | va_start(lst, type); |
data = buf + Limit; | 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); |
|
|
/* de-marshaling */ | return v; |
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; | static int |
AIT_LEN(val) = AIT_LEN(&v[i]); | _cmp_arr_key_asc(const void *a, const void *b) |
| { |
| return AIT_KEY(*(ait_val_t**) a) - AIT_KEY(*(ait_val_t**) b); |
| } |
|
|
switch (AIT_TYPE(val)) { | static int |
case blob: | _cmp_arr_key_desc(const void *a, const void *b) |
case f32: | { |
case f64: | return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a); |
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 buffer: | |
case string: | |
if (AIT_LEN(val) > buflen - Limit) { | |
io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d " | |
"needed min %d ...\n", buflen, Limit + AIT_LEN(val)); | |
if (!zcpy) | |
io_arrayFree(vars); | |
io_arrayDestroy(&vars); | |
return NULL; | |
} else | |
Limit += AIT_LEN(val); | |
|
|
if (!zcpy) { | static int |
val->val.buffer = malloc(AIT_LEN(val)); | _cmp_arr_val_asc(const void *a, const void *b) |
if (!val->val.buffer) { | { |
LOGERR; | return AIT_RAW(*(ait_val_t**) a) - AIT_RAW(*(ait_val_t**) b); |
io_arrayFree(vars); | } |
io_arrayDestroy(&vars); | |
return NULL; | static int |
} else | _cmp_arr_val_desc(const void *a, const void *b) |
memcpy(val->val.buffer, data, AIT_LEN(val)); | { |
} else | return AIT_RAW(*(ait_val_t**) b) - AIT_RAW(*(ait_val_t**) a); |
val->val.buffer = data; | } |
data += AIT_LEN(val); | |
| /* |
| * io_sortVarsByVal() - Sorting array with variables by value |
| * |
| * @vars = Variable array |
| * @order = Sort order. If =0 ascend or !=0 descend |
| * @cmp = Custom compare function for sorting. If =NULL compare by value |
| * return: none |
| */ |
| inline void |
| io_sortVarsByVal(array_t * __restrict vars, int order, int (*cmp)(const void*, const void*)) |
| { |
| if (!vars) |
| return; |
| |
| 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); |
| } |
| |
| /* |
| * io_findKeyVars() - Find variable by key from array |
| * |
| * @vars = Variables |
| * @key = Search key |
| * return: NULL error or not found, !=NULL valid element |
| */ |
| ait_val_t * |
| io_findKeyVars(array_t * __restrict vars, u_short key) |
| { |
| array_t *tmp; |
| ait_val_t **vv, *v = NULL; |
| register int i; |
| const u_char *p; |
| |
| if (!vars) |
| return NULL; |
| |
| if (io_arrayCopy(&tmp, vars) == -1) |
| return NULL; |
| else |
| qsort(tmp->arr_data, tmp->arr_num, sizeof(void*), _cmp_arr_key_asc); |
| |
| /* binary search */ |
| for (p = (const u_char*) tmp->arr_data, i = io_arraySize(tmp); i; i >>= 1) { |
| vv = (ait_val_t**) (p + (i >> 1) * sizeof(void*)); |
| if (!(key - AIT_KEY(*vv))) { /* found! */ |
| v = *vv; |
| break; |
| } |
| if ((key - AIT_KEY(*vv)) > 0) { /* move right key > current */ |
| p = (const u_char*) vv + sizeof(void*); |
| i--; |
| } /* else move left */ |
| } |
| |
| io_arrayDestroy(&tmp); |
| return v; |
| } |
| |
| /* |
| * io_hashVar() - Generate hash key for variable from string or value |
| * |
| * @v = variable |
| * @key = key string for hash, if =NULL hash will built from variable |
| * return: hash key |
| */ |
| u_short |
| io_hashVar(ait_val_t * __restrict v, const char * __restrict key) |
| { |
| void *p; |
| u_short cksum; |
| int l; |
| |
| if (!v) |
| return 0; |
| |
| if (key) { |
| p = (void*) key; |
| l = (strlen(key) + 1) / 2; |
| } else { |
| switch (AIT_TYPE(v)) { |
| case empty: |
| AIT_KEY(v) = 0; |
| return 0; |
| case string: |
| case buffer: |
| p = AIT_ADDR(v); |
| l = AIT_LEN(v) / 2; |
break; |
break; |
|
case data: |
|
p = v->val_data; |
|
l = AIT_LEN(v) / 2; |
|
break; |
default: |
default: |
io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", | p = &AIT_RAW(v); |
AIT_TYPE(val), i); | l = sizeof AIT_RAW(v) / 2; |
if (!zcpy) | break; |
io_arrayFree(vars); | |
io_arrayDestroy(&vars); | |
return NULL; | |
} |
} |
} |
} |
|
|
return vars; | cksum = crcFletcher16((u_short*) p, l); |
| |
| if (AIT_BE(v)) |
| AIT_KEY(v) = htobe16(cksum); |
| else if (AIT_LE(v)) |
| AIT_KEY(v) = htole16(cksum); |
| else |
| AIT_KEY(v) = cksum; |
| |
| return AIT_KEY(v); |
| } |
| |
| /* |
| * io_hashKeyVars() - Generate hash keys for variables |
| * |
| * @vars = Variables |
| * return -1 error or 0 ok |
| */ |
| inline int |
| io_hashKeyVars(array_t * __restrict vars) |
| { |
| register int i; |
| |
| if (!vars) |
| return -1; |
| |
| for (i = 0; i < io_arraySize(vars); i++) |
| io_hashVar(io_array(vars, i, ait_val_t*), NULL); |
| |
| return 0; |
| } |
| |
| /* |
| * io_findKeyHash() - Find variable by hash string from array |
| * |
| * @vars = Variables |
| * @key = Search string |
| * return: NULL error or not found, !=NULL valid element |
| */ |
| inline ait_val_t * |
| io_findKeyHash(array_t * __restrict vars, const char * __restrict key) |
| { |
| u_short k = 0; |
| |
| if (!vars || !key) |
| return NULL; |
| |
| k = crcFletcher16((u_short*) key, (strlen(key) + 1) / 2); |
| return io_findKeyVars(vars, k); |
| } |
| |
| /* |
| * io_sprintfVar() - Builtin string variable from formatted input |
| * |
| * @v = variable |
| * @fmt = format string |
| * @... = argument(s) |
| * return: -1 error or >0 copied bytes to variable |
| */ |
| int |
| io_sprintfVar(ait_val_t * __restrict v, const char *fmt, ...) |
| { |
| int ret = 0; |
| va_list lst; |
| char *str = NULL; |
| |
| if (!v || !fmt) |
| return -1; |
| |
| va_start(lst, fmt); |
| ret = vasprintf(&str, fmt, lst); |
| va_end(lst); |
| |
| if (str && ret > -1) { |
| AIT_FREE_VAL(v); |
| AIT_SET_STR(v, str); |
| } else |
| LOGERR; |
| |
| if (str) |
| free(str); |
| return ret; |
| } |
| |
| /* |
| * io_setlikeVar() - Set variable like ... |
| * |
| * @v = variable |
| * @t = type of data |
| * @l = length of data |
| * @... = data |
| * return: -1 error or 0 ok |
| */ |
| inline int |
| io_setlikeVar(ait_val_t * __restrict v, ait_type_t t, u_int l, ...) |
| { |
| va_list lst; |
| |
| if (!v) |
| return -1; |
| |
| AIT_FREE_VAL(v); |
| AIT_INIT_VAL2(v, t); |
| AIT_LEN(v) = l; |
| AIT_IN(v) = 1; |
| |
| va_start(lst, l); |
| switch (AIT_TYPE(v)) { |
| case ptr: |
| case buffer: |
| case string: |
| AIT_ADDR(v) = va_arg(lst, void*); |
| break; |
| default: |
| AIT_RAW(v) = va_arg(lst, uint64_t); |
| break; |
| } |
| va_end(lst); |
| |
| return 0; |
| } |
| |
| /* |
| * io_cmpVar() - Compare two variables |
| * |
| * @a = 1st variable |
| * @b = 2nd variable |
| * return: 0 is equal or !=0 is different |
| */ |
| inline int |
| io_cmpVar(ait_val_t * __restrict a, ait_val_t * __restrict b) |
| { |
| intptr_t ret; |
| |
| if (!(ret = (b - a))) |
| return ret; |
| if ((ret = AIT_TYPE(b) - AIT_TYPE(a))) |
| return ret; |
| if ((ret = AIT_LEN(b) - AIT_LEN(a))) |
| return ret; |
| |
| switch (AIT_TYPE(a)) { |
| case buffer: |
| ret = memcmp(AIT_GET_BUF(a), AIT_GET_BUF(b), AIT_LEN(a)); |
| break; |
| case string: |
| ret = strncmp(AIT_GET_STR(a), AIT_GET_STR(b), AIT_LEN(a)); |
| break; |
| case data: |
| ret = memcmp(AIT_GET_DATA(a), AIT_GET_DATA(b), AIT_LEN(a)); |
| break; |
| case ptr: |
| ret = AIT_ADDR(b) - AIT_ADDR(a); |
| break; |
| default: |
| ret = AIT_RAW(b) - AIT_RAW(a); |
| break; |
| } |
| |
| return (int) ret; |
} |
} |