--- libelwix/src/vars.c 2022/01/24 16:01:49 1.9.56.2 +++ libelwix/src/vars.c 2022/10/24 00:10:22 1.13 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: vars.c,v 1.9.56.2 2022/01/24 16:01:49 misho Exp $ +* $Id: vars.c,v 1.13 2022/10/24 00:10:22 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -250,9 +250,102 @@ buffer2vars(u_char * __restrict buf, int buflen, int v } /* + * ait_var2tlv() - Marshaling data from variable to TLV buffer + * + * @buf = Buffer, If =NULL then we return only needed buffer size + * @buflen = Size of buffer + * @var = Variable + * return: -1 error, 0 nothing done or >0 size of marshaled data + */ +int +ait_var2tlv(u_char * __restrict buf, int buflen, ait_val_t * __restrict v) +{ + int Limit = 0; + u_char *dat; + + assert(v); + if (!v) + return -1; + if (AIT_TYPE(v) == empty) + return 0; + + /* calculate amount of data into buffer */ + Limit = 5 + AIT_LEN(v); + /* check only needed buffer size */ + if (!buf) + return Limit; + else + dat = buf; + + if (Limit > buflen) { + elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", + buflen, Limit); + return -1; + } else + memset(buf, 0, buflen); + + /* marshaling */ + *dat++ = AIT_TYPE(v); + + *((uint32_t*) dat) = htonl(AIT_LEN(v)); + dat += sizeof(uint32_t); + + switch (AIT_TYPE(v)) { + case i8: + *((int8_t*) dat) = AIT_GET_I8(v); + break; + case u8: + *((uint8_t*) dat) = AIT_GET_U8(v); + break; + case i16: + *((int16_t*) dat) = AIT_GET_I16(v); + break; + case u16: + *((uint16_t*) dat) = AIT_GET_U16(v); + break; + case i32: + *((int32_t*) dat) = AIT_GET_I32(v); + break; + case blob: + case u32: + *((uint32_t*) dat) = AIT_GET_U32(v); + break; + case i64: + *((int64_t*) dat) = AIT_GET_I64(v); + break; + case u64: + *((uint64_t*) dat) = AIT_GET_U64(v); + break; + case f32: + *((float*) dat) = AIT_GET_F32(v); + break; + case f64: + *((double*) dat) = AIT_GET_F64(v); + break; + case data: + memcpy(dat, AIT_GET_DATA(v), AIT_LEN(v)); + break; + case buffer: + memcpy(dat, AIT_GET_BUF(v), AIT_LEN(v)); + break; + case string: + memcpy(dat, AIT_GET_STR(v), AIT_LEN(v)); + break; + case ptr: + memcpy(dat, AIT_GET_PTR(v), AIT_LEN(v)); + break; + default: + elwix_SetErr(EINVAL, "Unsupported variable type=%d", AIT_TYPE(v)); + return -1; + } + + return Limit; +} + +/* * ait_vars2tlv() - Marshaling data from array with variables to TLV buffer * - * @buf = Buffer + * @buf = Buffer, If =NULL then we return only needed buffer size * @buflen = Size of buffer * @vars = Variable array * return: -1 error, 0 nothing done or >0 size of marshaled data @@ -265,16 +358,19 @@ ait_vars2tlv(u_char * __restrict buf, int buflen, arra ait_val_t *val; u_char *dat; - assert(buf); assert(vars); - if (!buf || !vars) + if (!vars) return -1; - if (!buflen || !array_Size(vars)) + if (!array_Size(vars)) return 0; /* calculate amount of data into buffer */ - for (i = 0, Limit = 0; i < array_Size(vars); i++, - Limit += 5 + AIT_LEN(array(vars, i, ait_val_t*))); + for (i = 0, Limit = 0; i < array_Size(vars); + Limit += 5 + AIT_LEN(array(vars, i, ait_val_t*)), i++); + /* check only needed buffer size */ + if (!buf) + return Limit; + if (Limit > buflen) { elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", buflen, Limit); @@ -347,6 +443,91 @@ ait_vars2tlv(u_char * __restrict buf, int buflen, arra } /* + * ait_tlv2var() - De-marshaling data from TLV buffer to variable + * + * @buf = Buffer + * @buflen = Size of buffer + * @next_tlv = Next TLV position, if it is !=NULL + * return: =NULL error, !=NULL allocated variable array, after use must free with ait_freeVar() + */ +ait_val_t * +ait_tlv2var(u_char * __restrict buf, int buflen, off_t *next_tlv) +{ + ait_val_t *val; + u_char *dat; + + assert(buf); + if (!buf || !buflen) + return NULL; + + if (!(val = ait_allocVar())) + return NULL; + else + dat = buf; + + /* de-marshaling */ + if (*dat != empty) { + val->val_type = *dat++; + AIT_LEN(val) = ntohl(*((uint32_t*) dat)); + dat += sizeof(uint32_t); + + switch (AIT_TYPE(val)) { + case f32: + AIT_SET_F32(val, *((float*) dat)); + break; + case f64: + AIT_SET_F64(val, *((double*) dat)); + break; + case i8: + AIT_SET_I8(val, *((int8_t*) dat)); + break; + case i16: + AIT_SET_I16(val, *((int16_t*) dat)); + break; + case i32: + AIT_SET_I32(val, *((int32_t*) dat)); + break; + case i64: + AIT_SET_I64(val, *((int64_t*) dat)); + break; + case u8: + AIT_SET_U8(val, *((uint8_t*) dat)); + break; + case u16: + AIT_SET_U16(val, *((uint16_t*) dat)); + break; + case blob: + case u32: + AIT_SET_U32(val, *((uint32_t*) dat)); + break; + case u64: + AIT_SET_U64(val, *((uint64_t*) dat)); + break; + case data: + AIT_SET_DATA(val, dat, AIT_LEN(val)); + break; + case ptr: + case buffer: + AIT_SET_BUF(val, dat, AIT_LEN(val)); + break; + case string: + AIT_SET_STR(val, (char*) dat); + break; + default: + elwix_SetErr(EINVAL, "Unsupported variable type=%d", AIT_TYPE(val)); + ait_freeVar(&val); + return NULL; + } + dat += AIT_LEN(val); + } + + if (next_tlv) + *next_tlv = dat - buf; + + return val; +} + +/* * ait_tlv2vars() - De-marshaling data from TLV buffer to array with variables * * @buf = Buffer @@ -369,7 +550,7 @@ ait_tlv2vars(u_char * __restrict buf, int buflen) return NULL; /* de-marshaling */ - for (i = 0, dat = buf; i < buflen; i++) { + for (i = 0, dat = buf; *dat != empty && dat < (buf + buflen); i++) { val = ait_getVars(&vars, i); if (!val) { ait_freeVars(&vars); @@ -512,7 +693,6 @@ ait_array2vars(const char **args, int dn) ait_val_t *val; register int i; long n; - float f; double d; char *str; @@ -536,11 +716,6 @@ ait_array2vars(const char **args, int dn) AIT_SET_I64(val, (int64_t) n); continue; } - f = strtof(*args, &str); - if (!str || !*str) { - AIT_SET_F32(val, f); - continue; - } d = strtod(*args, &str); if (!str || !*str) { AIT_SET_F64(val, d); @@ -1033,7 +1208,7 @@ ait_sprintfVar(ait_val_t * __restrict v, const char *f { int ret = 0; va_list lst; - char str[STRSIZ] = { [0 ... STRSIZ - 1] = 0 }; + char str[65536] = { [0 ... 65535] = 0 }; if (!v || !fmt) return -1;