Annotation of libaitio/src/vars.c, revision 1.4

1.2       misho       1: /*************************************************************************
                      2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
                      3: *  by Michael Pounov <misho@elwix.org>
                      4: *
                      5: * $Author: misho $
1.4     ! misho       6: * $Id: vars.c,v 1.3.2.2 2011/12/14 12:22:05 misho Exp $
1.2       misho       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
                     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: /*
1.3       misho      50:  * io_vars2buffer() Marshaling data from array with variables to buffer
1.2       misho      51:  * @buf = Buffer
                     52:  * @buflen = Size of buffer
                     53:  * @vars = Variable array
                     54:  * return: -1 error, 0 nothing done or >0 size of marshaled data
                     55:  */
                     56: int
1.3       misho      57: io_vars2buffer(u_char *buf, int buflen, array_t *vars)
1.2       misho      58: {
                     59:        int Limit = 0;
                     60:        register int i;
                     61:        ait_val_t *v, *val;
                     62:        u_char *data;
                     63: 
                     64:        assert(buf);
                     65:        assert(vars);
                     66:        if (!buf || !vars)
                     67:                return -1;
                     68:        if (!buflen || !io_arraySize(vars))
                     69:                return 0;
                     70: 
                     71:        Limit = sizeof(ait_val_t) * io_arraySize(vars);
                     72:        if (Limit > buflen) {
                     73:                io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", 
                     74:                                buflen, Limit);
                     75:                return -1;
                     76:        } else {
                     77:                memset(buf, 0, buflen);
                     78: 
                     79:                v = (ait_val_t*) buf;
                     80:                data = buf + Limit;
                     81:        }
                     82: 
                     83:        /* marshaling */
                     84:        for (i = 0; i < io_arraySize(vars); i++) {
                     85:                val = io_array(vars, i, ait_val_t*);
                     86: 
                     87:                v[i].val_type = val->val_type;
                     88:                AIT_LEN(&v[i]) = htobe32(AIT_LEN(val));
                     89: 
                     90:                switch (AIT_TYPE(val)) {
                     91:                        case blob:
                     92:                        case f32:
                     93:                        case f64:
                     94:                        case i8:
                     95:                        case i16:
                     96:                        case i32:
                     97:                        case i64:
                     98:                        case u8:
                     99:                        case u16:
                    100:                        case u32:
                    101:                        case u64:
                    102:                                v[i].val.net = htobe64(val->val.net);
                    103:                                break;
                    104:                        case buffer:
                    105:                        case string:
                    106:                                if (AIT_LEN(val) > buflen - Limit) {
                    107:                                        io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d "
                    108:                                                        "needed min %d ...\n", buflen, Limit + AIT_LEN(val));
                    109:                                        return -1;
                    110:                                } else
                    111:                                        Limit += AIT_LEN(val);
                    112: 
                    113:                                memcpy(data, val->val.buffer, AIT_LEN(val));
                    114:                                /* Debug:: data offset in packet, not matter for anything! */
                    115:                                v[i].val.net = data - buf;
                    116:                                data += AIT_LEN(val);
                    117:                                break;
                    118:                        default:
                    119:                                io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", 
                    120:                                                AIT_TYPE(val), i);
                    121:                                return -1;
                    122:                }
                    123:        }
                    124: 
                    125:        return Limit;
                    126: }
                    127: 
                    128: /*
1.3       misho     129:  * io_buffer2vars() De-marshaling data from buffer to array with variables
1.2       misho     130:  * @buf = Buffer
                    131:  * @buflen = Size of buffer
                    132:  * @vnum = Number of variables into buffer
                    133:  * @zcpy = Zero-copy for variables, if !=0 don't use io_arrayFree() for free variables and 
                    134:                *DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy()
                    135:  * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy()
                    136:  */
                    137: array_t *
1.3       misho     138: io_buffer2vars(u_char *buf, int buflen, int vnum, int zcpy)
1.2       misho     139: {
                    140:        array_t *vars;
                    141:        int Limit = 0;
                    142:        register int i;
                    143:        ait_val_t *v, *val;
                    144:        u_char *data;
                    145: 
                    146:        assert(buf);
                    147:        if (!buf || !buflen || !vnum)
                    148:                return NULL;
                    149: 
                    150:        Limit = sizeof(ait_val_t) * vnum;
                    151:        if (Limit > buflen) {
                    152:                io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", 
                    153:                                buflen, Limit);
                    154:                return NULL;
                    155:        } else {
                    156:                if (!(vars = io_arrayInit(vnum)))
                    157:                        return NULL;
                    158: 
                    159:                v = (ait_val_t*) buf;
                    160:                data = buf + Limit;
                    161:        }
                    162: 
                    163:        /* de-marshaling */
                    164:        for (i = 0; i < io_arraySize(vars); i++) {
                    165:                if (!zcpy) {
                    166:                        val = malloc(sizeof(ait_val_t));
                    167:                        if (!val) {
                    168:                                LOGERR;
                    169:                                io_arrayFree(vars);
                    170:                                io_arrayDestroy(&vars);
                    171:                                return NULL;
                    172:                        }
                    173:                } else
                    174:                        val = v + i;
                    175:                io_arraySet(vars, i, val);
                    176: 
                    177:                val->val_type = v[i].val_type;
                    178: #if defined(__OpenBSD__)
                    179:                AIT_LEN(val) = betoh32(AIT_LEN(&v[i]));
                    180: #else
                    181:                AIT_LEN(val) = be32toh(AIT_LEN(&v[i]));
                    182: #endif
                    183: 
                    184:                switch (AIT_TYPE(val)) {
                    185:                        case blob:
                    186:                        case f32:
                    187:                        case f64:
                    188:                        case i8:
                    189:                        case i16:
                    190:                        case i32:
                    191:                        case i64:
                    192:                        case u8:
                    193:                        case u16:
                    194:                        case u32:
                    195:                        case u64:
                    196: #if defined(__OpenBSD__)
                    197:                                val->val.net = betoh64(v[i].val.net);
                    198: #else
                    199:                                val->val.net = be64toh(v[i].val.net);
                    200: #endif
                    201:                                break;
                    202:                        case buffer:
                    203:                        case string:
                    204:                                if (AIT_LEN(val) > buflen - Limit) {
                    205:                                        io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d "
                    206:                                                        "needed min %d ...\n", buflen, Limit + AIT_LEN(val));
                    207:                                        if (!zcpy)
                    208:                                                io_arrayFree(vars);
                    209:                                        io_arrayDestroy(&vars);
                    210:                                        return NULL;
                    211:                                } else
                    212:                                        Limit += AIT_LEN(val);
                    213: 
                    214:                                if (!zcpy) {
                    215:                                        val->val.buffer = malloc(AIT_LEN(val));
                    216:                                        if (!val->val.buffer) {
                    217:                                                LOGERR;
                    218:                                                io_arrayFree(vars);
                    219:                                                io_arrayDestroy(&vars);
                    220:                                                return NULL;
                    221:                                        } else
                    222:                                                memcpy(val->val.buffer, data, AIT_LEN(val));
                    223:                                } else
                    224:                                        val->val.buffer = data;
                    225:                                data += AIT_LEN(val);
                    226:                                break;
                    227:                        default:
                    228:                                io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", 
                    229:                                                AIT_TYPE(val), i);
                    230:                                if (!zcpy)
                    231:                                        io_arrayFree(vars);
                    232:                                io_arrayDestroy(&vars);
                    233:                                return NULL;
                    234:                }
                    235:        }
                    236: 
                    237:        return vars;
                    238: }
                    239: 
                    240: /* buffer marshaling without swapping bytes to network order */
                    241: 
                    242: /*
1.3       misho     243:  * io_vars2map() Marshaling data from array with variables to memory map
1.2       misho     244:  * @buf = Buffer
                    245:  * @buflen = Size of buffer
                    246:  * @vars = Variable array
                    247:  * return: -1 error, 0 nothing done or >0 size of marshaled data
                    248:  */
                    249: int
1.3       misho     250: io_vars2map(u_char *buf, int buflen, array_t *vars)
1.2       misho     251: {
                    252:        int Limit = 0;
                    253:        register int i;
                    254:        ait_val_t *v, *val;
                    255:        u_char *data;
                    256: 
                    257:        assert(buf);
                    258:        assert(vars);
                    259:        if (!buf || !vars)
                    260:                return -1;
                    261:        if (!buflen || !io_arraySize(vars))
                    262:                return 0;
                    263: 
                    264:        Limit = sizeof(ait_val_t) * io_arraySize(vars);
                    265:        if (Limit > buflen) {
                    266:                io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", 
                    267:                                buflen, Limit);
                    268:                return -1;
                    269:        } else {
                    270:                memset(buf, 0, buflen);
                    271: 
                    272:                v = (ait_val_t*) buf;
                    273:                data = buf + Limit;
                    274:        }
                    275: 
                    276:        /* marshaling */
                    277:        for (i = 0; i < io_arraySize(vars); i++) {
                    278:                val = io_array(vars, i, ait_val_t*);
                    279: 
                    280:                v[i].val_type = val->val_type;
                    281:                AIT_LEN(&v[i]) = AIT_LEN(val);
                    282: 
                    283:                switch (AIT_TYPE(val)) {
                    284:                        case blob:
                    285:                        case f32:
                    286:                        case f64:
                    287:                        case i8:
                    288:                        case i16:
                    289:                        case i32:
                    290:                        case i64:
                    291:                        case u8:
                    292:                        case u16:
                    293:                        case u32:
                    294:                        case u64:
                    295:                                v[i].val.net = val->val.net;
                    296:                                break;
                    297:                        case buffer:
                    298:                        case string:
                    299:                                if (AIT_LEN(val) > buflen - Limit) {
                    300:                                        io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d "
                    301:                                                        "needed min %d ...\n", buflen, Limit + AIT_LEN(val));
                    302:                                        return -1;
                    303:                                } else
                    304:                                        Limit += AIT_LEN(val);
                    305: 
                    306:                                memcpy(data, val->val.buffer, AIT_LEN(val));
                    307:                                /* Debug:: data offset in packet, not matter for anything! */
                    308:                                v[i].val.net = data - buf;
                    309:                                data += AIT_LEN(val);
                    310:                                break;
                    311:                        default:
                    312:                                io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", 
                    313:                                                AIT_TYPE(val), i);
                    314:                                return -1;
                    315:                }
                    316:        }
                    317: 
                    318:        return Limit;
                    319: }
                    320: 
                    321: /*
1.3       misho     322:  * io_map2vars() De-marshaling data from memory map to array with variables
1.2       misho     323:  * @buf = Buffer
                    324:  * @buflen = Size of buffer
                    325:  * @vnum = Number of variables into buffer
                    326:  * @zcpy = Zero-copy for variables, if !=0 don't use io_arrayFree() for free variables and 
                    327:                *DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy()
                    328:  * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy()
                    329:  */
                    330: array_t *
1.3       misho     331: io_map2vars(u_char *buf, int buflen, int vnum, int zcpy)
1.2       misho     332: {
                    333:        array_t *vars;
                    334:        int Limit = 0;
                    335:        register int i;
                    336:        ait_val_t *v, *val;
                    337:        u_char *data;
                    338: 
                    339:        assert(buf);
                    340:        if (!buf || !buflen || !vnum)
                    341:                return NULL;
                    342: 
                    343:        Limit = sizeof(ait_val_t) * vnum;
                    344:        if (Limit > buflen) {
                    345:                io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", 
                    346:                                buflen, Limit);
                    347:                return NULL;
                    348:        } else {
                    349:                if (!(vars = io_arrayInit(vnum)))
                    350:                        return NULL;
                    351: 
                    352:                v = (ait_val_t*) buf;
                    353:                data = buf + Limit;
                    354:        }
                    355: 
                    356:        /* de-marshaling */
                    357:        for (i = 0; i < io_arraySize(vars); i++) {
                    358:                if (!zcpy) {
                    359:                        val = malloc(sizeof(ait_val_t));
                    360:                        if (!val) {
                    361:                                LOGERR;
                    362:                                io_arrayFree(vars);
                    363:                                io_arrayDestroy(&vars);
                    364:                                return NULL;
                    365:                        }
                    366:                } else
                    367:                        val = v + i;
                    368:                io_arraySet(vars, i, val);
                    369: 
                    370:                val->val_type = v[i].val_type;
                    371:                AIT_LEN(val) = AIT_LEN(&v[i]);
                    372: 
                    373:                switch (AIT_TYPE(val)) {
                    374:                        case blob:
                    375:                        case f32:
                    376:                        case f64:
                    377:                        case i8:
                    378:                        case i16:
                    379:                        case i32:
                    380:                        case i64:
                    381:                        case u8:
                    382:                        case u16:
                    383:                        case u32:
                    384:                        case u64:
                    385:                                val->val.net = v[i].val.net;
                    386:                                break;
                    387:                        case buffer:
                    388:                        case string:
                    389:                                if (AIT_LEN(val) > buflen - Limit) {
                    390:                                        io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d "
                    391:                                                        "needed min %d ...\n", buflen, Limit + AIT_LEN(val));
                    392:                                        if (!zcpy)
                    393:                                                io_arrayFree(vars);
                    394:                                        io_arrayDestroy(&vars);
                    395:                                        return NULL;
                    396:                                } else
                    397:                                        Limit += AIT_LEN(val);
                    398: 
                    399:                                if (!zcpy) {
                    400:                                        val->val.buffer = malloc(AIT_LEN(val));
                    401:                                        if (!val->val.buffer) {
                    402:                                                LOGERR;
                    403:                                                io_arrayFree(vars);
                    404:                                                io_arrayDestroy(&vars);
                    405:                                                return NULL;
                    406:                                        } else
                    407:                                                memcpy(val->val.buffer, data, AIT_LEN(val));
                    408:                                } else
                    409:                                        val->val.buffer = data;
                    410:                                data += AIT_LEN(val);
                    411:                                break;
                    412:                        default:
                    413:                                io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", 
                    414:                                                AIT_TYPE(val), i);
                    415:                                if (!zcpy)
                    416:                                        io_arrayFree(vars);
                    417:                                io_arrayDestroy(&vars);
                    418:                                return NULL;
                    419:                }
                    420:        }
                    421: 
                    422:        return vars;
                    423: }
1.3       misho     424: 
                    425: 
                    426: /*
                    427:  * io_allocVars() Allocate ait_val_t array
                    428:  * @varnum = Number of variables
                    429:  * return: =NULL error or !=NULL allocated array
                    430:  */
                    431: inline array_t *
                    432: io_allocVars(int varnum)
                    433: {
                    434:        array_t *arr;
                    435:        register int i;
                    436:        ait_val_t *v;
                    437: 
                    438:        if (!varnum || !(arr = io_arrayInit(varnum)))
                    439:                return NULL;
                    440: 
                    441:        for (i = 0; i < io_arraySize(arr); i++) {
                    442:                v = malloc(sizeof(ait_val_t));
                    443:                if (!v) {
                    444:                        LOGERR;
                    445:                        io_freeVars(&arr);
                    446:                        return NULL;
                    447:                } else {
                    448:                        memset(v, 0, sizeof(ait_val_t));
                    449:                        io_arraySet(arr, i, v);
                    450:                }
                    451:        }
                    452: 
                    453:        return arr;
                    454: }
                    455: 
                    456: /*
                    457:  * io_clrVars() Clear ait_val_t elements from array
                    458:  * @vars = Variable array
                    459:  * return: -1 error or size of array
                    460:  */
                    461: inline int
                    462: io_clrVars(array_t * __restrict vars)
                    463: {
                    464:        register int i;
                    465: 
                    466:        if (!vars)
                    467:                return -1;
                    468: 
                    469:        for (i = 0; i < io_arraySize(vars); i++)
                    470:                if (io_arrayGet(vars, i))
                    471:                        AIT_FREE_VAL(io_array(vars, i, ait_val_t*));
                    472: 
                    473:        return io_arraySize(vars);
                    474: }
                    475: 
                    476: /*
                    477:  * io_freeVars() Free ait_val_t array
                    478:  * @vars = Variable array
                    479:  * return: none
                    480:  */
                    481: inline void
                    482: io_freeVars(array_t ** __restrict vars)
                    483: {
                    484:        if (!vars || !*vars)
                    485:                return;
                    486: 
                    487:        io_clrVars(*vars);
                    488:        io_arrayFree(*vars);
                    489:        io_arrayDestroy(vars);
                    490: }
1.4     ! misho     491: 
        !           492: /*
        !           493:  * io_allocVar() Allocate memory for variable
        !           494:  * return: NULL error or new variable, after use free variable with io_freeVar()
        !           495:  */
        !           496: inline ait_val_t *
        !           497: io_allocVar(void)
        !           498: {
        !           499:        ait_val_t *v = NULL;
        !           500: 
        !           501:        v = malloc(sizeof(ait_val_t));
        !           502:        if (!v) {
        !           503:                LOGERR;
        !           504:                return NULL;
        !           505:        } else
        !           506:                memset(v, 0, sizeof(ait_val_t));
        !           507:        v->val_type = empty;
        !           508: 
        !           509:        return v;
        !           510: }
        !           511: 
        !           512: /*
        !           513:  * io_freeVar() Free allocated memory for variable
        !           514:  * @val = Variable
        !           515:  * return: none
        !           516:  */
        !           517: inline void
        !           518: io_freeVar(ait_val_t * __restrict val)
        !           519: {
        !           520:        if (val) {
        !           521:                AIT_FREE_VAL(val);
        !           522:                free(val);
        !           523:                val = NULL;
        !           524:        }
        !           525: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>