--- libaitio/src/Attic/vars.c 2011/08/29 14:58:50 1.1 +++ libaitio/src/Attic/vars.c 2011/10/31 13:53:51 1.2 @@ -0,0 +1,423 @@ +/************************************************************************* +* (C) 2011 AITNET ltd - Sofia/Bulgaria - +* by Michael Pounov +* +* $Author: misho $ +* $Id: vars.c,v 1.2 2011/10/31 13:53:51 misho Exp $ +* +************************************************************************** +The ELWIX and AITNET software is distributed under the following +terms: + +All of the documentation and software included in the ELWIX and AITNET +Releases is copyrighted by ELWIX - Sofia/Bulgaria + +Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + by Michael Pounov . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by Michael Pounov +ELWIX - Embedded LightWeight unIX and its contributors. +4. Neither the name of AITNET nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ +#include "global.h" + + +/* + * io_vals2buffer() 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_vals2buffer(u_char *buf, int buflen, array_t *vars) +{ + int Limit = 0; + register int i; + ait_val_t *v, *val; + u_char *data; + + assert(buf); + assert(vars); + if (!buf || !vars) + return -1; + if (!buflen || !io_arraySize(vars)) + return 0; + + 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; + } + + /* 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_LEN(&v[i]) = htobe32(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 = htobe64(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)); + /* Debug:: data offset in packet, not matter for anything! */ + v[i].val.net = data - buf; + data += AIT_LEN(val); + break; + default: + io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", + AIT_TYPE(val), i); + return -1; + } + } + + return Limit; +} + +/* + * io_buffer2vals() 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_buffer2vals(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 *data; + + assert(buf); + if (!buf || !buflen || !vnum) + return NULL; + + Limit = sizeof(ait_val_t) * vnum; + if (Limit > buflen) { + io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", + buflen, Limit); + return NULL; + } else { + if (!(vars = io_arrayInit(vnum))) + return NULL; + + v = (ait_val_t*) buf; + data = 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; +#if defined(__OpenBSD__) + AIT_LEN(val) = betoh32(AIT_LEN(&v[i])); +#else + AIT_LEN(val) = be32toh(AIT_LEN(&v[i])); +#endif + + 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: +#if defined(__OpenBSD__) + val->val.net = betoh64(v[i].val.net); +#else + val->val.net = be64toh(v[i].val.net); +#endif + 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) { + 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, data, AIT_LEN(val)); + } else + val->val.buffer = data; + data += AIT_LEN(val); + break; + default: + io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", + AIT_TYPE(val), i); + if (!zcpy) + io_arrayFree(vars); + io_arrayDestroy(&vars); + return NULL; + } + } + + return vars; +} + +/* buffer marshaling without swapping bytes to network order */ + +/* + * io_vals2map() 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 + */ +int +io_vals2map(u_char *buf, int buflen, array_t *vars) +{ + int Limit = 0; + register int i; + ait_val_t *v, *val; + u_char *data; + + assert(buf); + assert(vars); + if (!buf || !vars) + return -1; + if (!buflen || !io_arraySize(vars)) + return 0; + + 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; + } + + /* 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_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 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)); + /* Debug:: data offset in packet, not matter for anything! */ + v[i].val.net = data - buf; + data += AIT_LEN(val); + break; + default: + io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", + AIT_TYPE(val), i); + return -1; + } + } + + return Limit; +} + +/* + * io_map2vals() De-marshaling data from memory map 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_map2vals(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 *data; + + assert(buf); + if (!buf || !buflen || !vnum) + return NULL; + + Limit = sizeof(ait_val_t) * vnum; + if (Limit > buflen) { + io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", + buflen, Limit); + return NULL; + } else { + if (!(vars = io_arrayInit(vnum))) + return NULL; + + v = (ait_val_t*) buf; + data = 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_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 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) { + 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, data, AIT_LEN(val)); + } else + val->val.buffer = data; + data += AIT_LEN(val); + break; + default: + io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", + AIT_TYPE(val), i); + if (!zcpy) + io_arrayFree(vars); + io_arrayDestroy(&vars); + return NULL; + } + } + + return vars; +}