Annotation of libelwix/src/vars.c, revision 1.9.56.1

1.1       misho       1: /*************************************************************************
                      2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
                      3: *  by Michael Pounov <misho@elwix.org>
                      4: *
                      5: * $Author: misho $
1.9.56.1! misho       6: * $Id: vars.c,v 1.9 2016/05/18 12:47:42 misho Exp $
1.1       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: 
1.9.56.1! misho      15: Copyright 2004 - 2022
1.1       misho      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: 
1.4       misho      49: static inline int
1.1       misho      50: vars2buffer(u_char * __restrict buf, int buflen, int be, array_t * __restrict vars)
                     51: {
                     52:        int Limit = 0;
                     53:        register int i;
                     54:        ait_val_t *v, *val;
                     55:        u_char *dat;
                     56: 
                     57:        assert(buf);
                     58:        assert(vars);
                     59:        if (!buf || !vars)
                     60:                return -1;
                     61:        if (!buflen || !array_Size(vars))
                     62:                return 0;
                     63:        be = !!be;
                     64: 
                     65:        Limit = sizeof(ait_val_t) * array_Size(vars);
                     66:        if (Limit > buflen) {
                     67:                elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
                     68:                                buflen, Limit);
                     69:                return -1;
                     70:        } else {
                     71:                memset(buf, 0, buflen);
                     72: 
                     73:                v = (ait_val_t*) buf;
                     74:                dat = buf + Limit;
                     75:        }
                     76: 
                     77:        /* marshaling */
                     78:        for (i = 0; i < array_Size(vars); i++) {
                     79:                val = array(vars, i, ait_val_t*);
                     80: 
                     81:                v[i].val_type = val->val_type;
                     82:                AIT_IN(&v[i]) = 1;
                     83:                AIT_BE(&v[i]) = be;
                     84:                AIT_LE(&v[i]) = !be;
                     85:                if (AIT_BE(&v[i])) {
                     86:                        AIT_KEY(&v[i]) = htobe16(AIT_KEY(val));
                     87:                        AIT_LEN(&v[i]) = htobe32(AIT_LEN(val));
                     88:                }
                     89:                if (AIT_LE(&v[i])) {
                     90:                        AIT_KEY(&v[i]) = htole16(AIT_KEY(val));
                     91:                        AIT_LEN(&v[i]) = htole32(AIT_LEN(val));
                     92:                }
                     93: 
                     94:                switch (AIT_TYPE(val)) {
                     95:                        case blob:
                     96:                        case f32:
                     97:                        case f64:
                     98:                        case i8:
                     99:                        case i16:
                    100:                        case i32:
                    101:                        case i64:
                    102:                        case u8:
                    103:                        case u16:
                    104:                        case u32:
                    105:                        case u64:
                    106:                                if (AIT_BE(&v[i]))
                    107:                                        v[i].val.net = htobe64(val->val.net);
                    108:                                if (AIT_LE(&v[i]))
                    109:                                        v[i].val.net = htole64(val->val.net);
                    110:                                break;
                    111:                        case data:
                    112:                                if (AIT_LEN(val) > buflen - Limit) {
                    113:                                        elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d "
                    114:                                                        "needed min %d", buflen, Limit + AIT_LEN(val));
                    115:                                        return -1;
                    116:                                } else
                    117:                                        Limit += AIT_LEN(val);
                    118: 
                    119:                                memcpy(dat, val->val_data, AIT_LEN(val));
                    120:                                /* Debug:: data offset in packet, not matter for anything! */
                    121:                                v[i].val.net = dat - buf;
                    122:                                dat += AIT_LEN(val);
                    123:                                break;
                    124:                        case buffer:
                    125:                        case string:
1.5       misho     126:                        case ptr:
1.1       misho     127:                                if (AIT_LEN(val) > buflen - Limit) {
                    128:                                        elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d "
                    129:                                                        "needed min %d", buflen, Limit + AIT_LEN(val));
                    130:                                        return -1;
                    131:                                } else
                    132:                                        Limit += AIT_LEN(val);
                    133: 
                    134:                                memcpy(dat, val->val.buffer, AIT_LEN(val));
                    135:                                /* Debug:: data offset in packet, not matter for anything! */
                    136:                                v[i].val.net = dat - buf;
                    137:                                dat += AIT_LEN(val);
                    138:                                break;
                    139:                        default:
                    140:                                elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
                    141:                                                AIT_TYPE(val), i);
                    142:                                return -1;
                    143:                }
                    144:        }
                    145: 
                    146:        return Limit;
                    147: }
                    148: 
1.4       misho     149: static inline array_t *
1.1       misho     150: buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
                    151: {
                    152:        array_t *vars;
                    153:        int Limit = 0;
                    154:        register int i;
                    155:        ait_val_t *v, *val;
                    156:        u_char *dat;
                    157: 
                    158:        assert(buf);
                    159:        if (!buf || !buflen || !vnum)
                    160:                return NULL;
                    161: 
                    162:        Limit = sizeof(ait_val_t) * vnum;
                    163:        if (Limit > buflen) {
                    164:                elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
                    165:                                buflen, Limit);
                    166:                return NULL;
                    167:        } else {
                    168:                if (!(vars = array_Init(vnum)))
                    169:                        return NULL;
                    170: 
                    171:                v = (ait_val_t*) buf;
                    172:                dat = buf + Limit;
                    173:        }
                    174: 
                    175:        /* de-marshaling */
                    176:        for (i = 0; i < array_Size(vars); i++) {
                    177:                if (!zcpy) {
                    178:                        val = e_malloc(sizeof(ait_val_t));
                    179:                        if (!val) {
                    180:                                if (!zcpy)
                    181:                                        array_Free(vars);
                    182:                                array_Destroy(&vars);
                    183:                                return NULL;
                    184:                        }
                    185:                        AIT_IN(val) = 0;
                    186:                } else {
                    187:                        val = v + i;
                    188:                        AIT_IN(val) = 1;
                    189:                }
                    190:                array_Set(vars, i, val);
                    191: 
                    192:                val->val_type = v[i].val_type;
                    193:                AIT_BE(val) = AIT_BE(&v[i]);
                    194:                AIT_LE(val) = AIT_LE(&v[i]);
                    195:                if (AIT_BE(val)) {
                    196:                        AIT_LEN(val) = be32toh(AIT_LEN(&v[i]));
                    197:                        AIT_KEY(val) = be16toh(AIT_KEY(&v[i]));
                    198:                }
                    199:                if (AIT_LE(val)) {
                    200:                        AIT_LEN(val) = le32toh(AIT_LEN(&v[i]));
                    201:                        AIT_KEY(val) = le16toh(AIT_KEY(&v[i]));
                    202:                }
                    203: 
                    204:                switch (AIT_TYPE(val)) {
                    205:                        case blob:
                    206:                        case f32:
                    207:                        case f64:
                    208:                        case i8:
                    209:                        case i16:
                    210:                        case i32:
                    211:                        case i64:
                    212:                        case u8:
                    213:                        case u16:
                    214:                        case u32:
                    215:                        case u64:
                    216:                                if (AIT_BE(val))
                    217:                                        val->val.net = be64toh(v[i].val.net);
                    218:                                if (AIT_LE(val))
                    219:                                        val->val.net = le64toh(v[i].val.net);
                    220:                                break;
                    221:                        case data:
1.5       misho     222:                        case ptr:
                    223:                                /* WARNING:: remap data and ptr type to buffer! */
1.1       misho     224:                                val->val_type = buffer;
                    225:                        case buffer:
                    226:                        case string:
                    227:                                if (!zcpy) {
                    228:                                        val->val.buffer = e_malloc(AIT_LEN(val));
                    229:                                        if (!val->val.buffer) {
                    230:                                                array_Free(vars);
                    231:                                                array_Destroy(&vars);
                    232:                                                return NULL;
                    233:                                        } else
                    234:                                                memcpy(val->val.buffer, dat, AIT_LEN(val));
                    235:                                } else
                    236:                                        val->val.buffer = dat;
                    237:                                dat += AIT_LEN(val);
                    238:                                break;
                    239:                        default:
                    240:                                elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
                    241:                                                AIT_TYPE(val), i);
                    242:                                if (!zcpy)
                    243:                                        array_Free(vars);
                    244:                                array_Destroy(&vars);
                    245:                                return NULL;
                    246:                }
                    247:        }
                    248: 
                    249:        return vars;
                    250: }
                    251: 
1.9.56.1! misho     252: /*
        !           253:  * ait_vars2tlv() - Marshaling data from array with variables to TLV buffer
        !           254:  *
        !           255:  * @buf = Buffer
        !           256:  * @buflen = Size of buffer
        !           257:  * @vars = Variable array
        !           258:  * return: -1 error, 0 nothing done or >0 size of marshaled data
        !           259:  */
        !           260: int
        !           261: ait_vars2tlv(u_char * __restrict buf, int buflen, array_t * __restrict vars)
        !           262: {
        !           263:        int Limit = 0;
        !           264:        register int i;
        !           265:        ait_val_t *val;
        !           266:        u_char *dat;
        !           267: 
        !           268:        assert(buf);
        !           269:        assert(vars);
        !           270:        if (!buf || !vars)
        !           271:                return -1;
        !           272:        if (!buflen || !array_Size(vars))
        !           273:                return 0;
        !           274: 
        !           275:        /* calculate amount of data into buffer */
        !           276:        for (i = 0, Limit = 0; i < array_Size(vars); i++, 
        !           277:                        Limit += 5 + AIT_LEN(array(vars, i, ait_val_t*)));
        !           278:        if (Limit > buflen) {
        !           279:                elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
        !           280:                                buflen, Limit);
        !           281:                return -1;
        !           282:        } else
        !           283:                memset(buf, 0, buflen);
        !           284: 
        !           285:        /* marshaling */
        !           286:        for (i = 0, dat = buf; i < array_Size(vars) && dat < (buf + Limit); i++) {
        !           287:                val = array(vars, i, ait_val_t*);
        !           288: 
        !           289:                *dat++ = AIT_TYPE(val); 
        !           290: 
        !           291:                *((uint32_t*) dat) = htonl(AIT_LEN(val));
        !           292:                dat += sizeof(uint32_t);
        !           293: 
        !           294:                switch (AIT_TYPE(val)) {
        !           295:                        case i8:
        !           296:                                *((int8_t*) dat) = AIT_GET_I8(val);
        !           297:                                break;
        !           298:                        case u8:
        !           299:                                *((uint8_t*) dat) = AIT_GET_U8(val);
        !           300:                                break;
        !           301:                        case i16:
        !           302:                                *((int16_t*) dat) = AIT_GET_I16(val);
        !           303:                                break;
        !           304:                        case u16:
        !           305:                                *((uint16_t*) dat) = AIT_GET_U16(val);
        !           306:                                break;
        !           307:                        case i32:
        !           308:                                *((int32_t*) dat) = AIT_GET_I32(val);
        !           309:                                break;
        !           310:                        case blob:
        !           311:                        case u32:
        !           312:                                *((uint32_t*) dat) = AIT_GET_U32(val);
        !           313:                                break;
        !           314:                        case i64:
        !           315:                                *((int64_t*) dat) = AIT_GET_I64(val);
        !           316:                                break;
        !           317:                        case u64:
        !           318:                                *((uint64_t*) dat) = AIT_GET_U64(val);
        !           319:                                break;
        !           320:                        case f32:
        !           321:                                *((float*) dat) = AIT_GET_F32(val);
        !           322:                                break;
        !           323:                        case f64:
        !           324:                                *((double*) dat) = AIT_GET_F64(val);
        !           325:                                break;
        !           326:                        case data:
        !           327:                                memcpy(dat, AIT_GET_DATA(val), AIT_LEN(val));
        !           328:                                break;
        !           329:                        case buffer:
        !           330:                                memcpy(dat, AIT_GET_BUF(val), AIT_LEN(val));
        !           331:                                break;
        !           332:                        case string:
        !           333:                                memcpy(dat, AIT_GET_STR(val), AIT_LEN(val));
        !           334:                                break;
        !           335:                        case ptr:
        !           336:                                memcpy(dat, AIT_GET_PTR(val), AIT_LEN(val));
        !           337:                                break;
        !           338:                        default:
        !           339:                                elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
        !           340:                                                AIT_TYPE(val), i);
        !           341:                                return -1;
        !           342:                }
        !           343:                dat += AIT_LEN(val);
        !           344:        }
        !           345: 
        !           346:        return Limit;
        !           347: }
        !           348: 
        !           349: /*
        !           350:  * ait_tlv2vars() - De-marshaling data from TLV buffer to array with variables
        !           351:  *
        !           352:  * @buf = Buffer
        !           353:  * @buflen = Size of buffer
        !           354:  * return: =NULL error, !=NULL allocated variable array, after use must free with ait_freeVars()
        !           355:  */
        !           356: array_t *
        !           357: ait_tlv2vars(u_char * __restrict buf, int buflen)
        !           358: {
        !           359:        array_t *vars;
        !           360:        register int i;
        !           361:        ait_val_t *val;
        !           362:        u_char *dat;
        !           363: 
        !           364:        assert(buf);
        !           365:        if (!buf || !buflen)
        !           366:                return NULL;
        !           367: 
        !           368:        if (!(vars = ait_allocVars(1)))
        !           369:                return NULL;
        !           370: 
        !           371:        /* de-marshaling */
        !           372:        for (i = 0, dat = buf; i < buflen; i++) {
        !           373:                val = ait_getVars(&vars, i);
        !           374:                if (!val) {
        !           375:                        ait_freeVars(&vars);
        !           376:                        return NULL;
        !           377:                }
        !           378: 
        !           379:                val->val_type = *dat++;
        !           380:                AIT_LEN(val) = ntohl(*((uint32_t*) dat));
        !           381:                dat += sizeof(uint32_t);
        !           382:                
        !           383:                switch (AIT_TYPE(val)) {
        !           384:                        case f32:
        !           385:                                AIT_SET_F32(val, *((float*) dat));
        !           386:                                break;
        !           387:                        case f64:
        !           388:                                AIT_SET_F64(val, *((double*) dat));
        !           389:                                break;
        !           390:                        case i8:
        !           391:                                AIT_SET_I8(val, *((int8_t*) dat));
        !           392:                                break;
        !           393:                        case i16:
        !           394:                                AIT_SET_I16(val, *((int16_t*) dat));
        !           395:                                break;
        !           396:                        case i32:
        !           397:                                AIT_SET_I32(val, *((int32_t*) dat));
        !           398:                                break;
        !           399:                        case i64:
        !           400:                                AIT_SET_I64(val, *((int64_t*) dat));
        !           401:                                break;
        !           402:                        case u8:
        !           403:                                AIT_SET_U8(val, *((uint8_t*) dat));
        !           404:                                break;
        !           405:                        case u16:
        !           406:                                AIT_SET_U16(val, *((uint16_t*) dat));
        !           407:                                break;
        !           408:                        case blob:
        !           409:                        case u32:
        !           410:                                AIT_SET_U32(val, *((uint32_t*) dat));
        !           411:                                break;
        !           412:                        case u64:
        !           413:                                AIT_SET_U64(val, *((uint64_t*) dat));
        !           414:                                break;
        !           415:                        case data:
        !           416:                                AIT_SET_DATA(val, dat, AIT_LEN(val));
        !           417:                                break;
        !           418:                        case ptr:
        !           419:                        case buffer:
        !           420:                                AIT_SET_BUF(val, dat, AIT_LEN(val));
        !           421:                                break;
        !           422:                        case string:
        !           423:                                AIT_SET_STR(val, (char*) dat);
        !           424:                                break;
        !           425:                        default:
        !           426:                                elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
        !           427:                                                AIT_TYPE(val), i);
        !           428:                                ait_freeVars(&vars);
        !           429:                                return NULL;
        !           430:                }
        !           431:                dat += AIT_LEN(val);
        !           432:        }
        !           433: 
        !           434:        return vars;
        !           435: }
1.1       misho     436: 
                    437: /* buffer marshaling with swapping bytes to network order */
                    438: 
                    439: /*
                    440:  * ait_vars2buffer() - Marshaling data from array with variables to buffer
                    441:  *
                    442:  * @buf = Buffer
                    443:  * @buflen = Size of buffer
                    444:  * @vars = Variable array
                    445:  * return: -1 error, 0 nothing done or >0 size of marshaled data
                    446:  */
1.4       misho     447: int
1.1       misho     448: ait_vars2buffer(u_char * __restrict buf, int buflen, array_t * __restrict vars)
                    449: {
                    450:        return vars2buffer(buf, buflen, 42, vars);
                    451: }
                    452: 
                    453: /*
                    454:  * ait_buffer2vars() - De-marshaling data from buffer to array with variables
                    455:  *
                    456:  * @buf = Buffer
                    457:  * @buflen = Size of buffer
                    458:  * @vnum = Number of variables into buffer
                    459:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
                    460:                *DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
                    461:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
                    462:  */
1.4       misho     463: array_t *
1.1       misho     464: ait_buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
                    465: {
                    466:        return buffer2vars(buf, buflen, vnum, zcpy);
                    467: }
                    468: 
                    469: /* buffer marshaling without swapping bytes to network order */
                    470: 
                    471: /*
                    472:  * ait_vars2map() - Marshaling data from array with variables to memory map
                    473:  *
                    474:  * @buf = Buffer
                    475:  * @buflen = Size of buffer
                    476:  * @vars = Variable array
                    477:  * return: -1 error, 0 nothing done or >0 size of marshaled data
                    478:  */
1.4       misho     479: int
1.1       misho     480: ait_vars2map(u_char *buf, int buflen, array_t *vars)
                    481: {
                    482:        return vars2buffer(buf, buflen, 0, vars);
                    483: }
                    484: 
                    485: /*
                    486:  * ait_map2vars() - De-marshaling data from memory map to array with variables
                    487:  *
                    488:  * @buf = Buffer
                    489:  * @buflen = Size of buffer
                    490:  * @vnum = Number of variables into buffer
                    491:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
                    492:                *DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
                    493:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
                    494:  */
1.4       misho     495: array_t *
1.1       misho     496: ait_map2vars(u_char *buf, int buflen, int vnum, int zcpy)
                    497: {
                    498:        return buffer2vars(buf, buflen, vnum, zcpy);
                    499: }
                    500: 
1.9.56.1! misho     501: /*
        !           502:  * ait_array2vars() - Build array with variables from Null Terminated String Array
        !           503:  *
        !           504:  * @args = Null-terminated array with strings
        !           505:  * @dn = Convert numbers from strings to numbers into variables
        !           506:  * return: =NULL error, !=NULL allocated variable array, after use must free with ait_freeVars()
        !           507:  */
        !           508: array_t *
        !           509: ait_array2vars(const char **args, int dn)
        !           510: {
        !           511:        array_t *vars;
        !           512:        ait_val_t *val;
        !           513:        register int i;
        !           514:        long n;
        !           515:        float f;
        !           516:        double d;
        !           517:        char *str;
        !           518: 
        !           519:        if (!args)
        !           520:                return NULL;
        !           521: 
        !           522:        vars = ait_allocVars(0);
        !           523:        if (!vars)
        !           524:                return NULL;
        !           525: 
        !           526:        for (i = 0; *args; i++, args++) {
        !           527:                val = ait_getVars(&vars, i);
        !           528:                if (!val) {
        !           529:                        ait_freeVars(&vars);
        !           530:                        return NULL;
        !           531:                }
        !           532: 
        !           533:                if (dn) {
        !           534:                        n = strtol(*args, &str, 0);
        !           535:                        if (!str) {
        !           536:                                AIT_SET_I64(val, (int64_t) n);
        !           537:                                continue;
        !           538:                        }
        !           539:                        f = strtof(*args, &str);
        !           540:                        if (!str) {
        !           541:                                AIT_SET_F32(val, f);
        !           542:                                continue;
        !           543:                        }
        !           544:                        d = strtod(*args, &str);
        !           545:                        if (!str) {
        !           546:                                AIT_SET_F64(val, d);
        !           547:                                continue;
        !           548:                        }
        !           549:                        AIT_SET_STR(val, *args);
        !           550:                } else
        !           551:                        AIT_SET_STR(val, *args);
        !           552:        }
        !           553: 
        !           554:        return vars;
        !           555: }
1.1       misho     556: 
                    557: /* variables array */
                    558: 
                    559: /*
                    560:  * ait_allocVars() - Allocate ait_val_t array
                    561:  *
                    562:  * @varnum = Number of variables
                    563:  * return: =NULL error or !=NULL allocated array
                    564:  */
1.4       misho     565: array_t *
1.1       misho     566: ait_allocVars(int varnum)
                    567: {
                    568:        array_t *arr;
                    569:        register int i;
                    570:        ait_val_t *v;
                    571: 
                    572:        if (!(arr = array_Init(varnum)))
                    573:                return NULL;
                    574: 
                    575:        for (i = 0; i < array_Size(arr); i++) {
                    576:                if (!(v = ait_allocVar())) {
                    577:                        ait_freeVars(&arr);
                    578:                        return NULL;
                    579:                } else
                    580:                        array_Set(arr, i, v);
                    581:        }
                    582: 
                    583:        return arr;
                    584: }
                    585: 
                    586: /*
                    587:  * ait_getVars() - Get ait_val_t element from array and if not exists allocate it
                    588:  *
                    589:  * @vars = Variable array
                    590:  * @n = index of variable into array
                    591:  * return: NULL error or !=NULL ait_val_t element
                    592:  */
1.4       misho     593: ait_val_t *
1.1       misho     594: ait_getVars(array_t ** __restrict vars, int n)
                    595: {
                    596:        register int i;
                    597:        ait_val_t *v;
                    598: 
                    599:        if (!vars)
                    600:                return NULL;
                    601: 
                    602:        if (!*vars) {
                    603:                if (!(*vars = ait_allocVars(n + 1)))
                    604:                        return NULL;
                    605:        } else if (n >= (i = array_Size(*vars))) {
                    606:                if (array_Grow(*vars, n + 1, 0))
                    607:                        return NULL;
                    608:                for (; i < array_Size(*vars); i++)
                    609:                        if (!array_Get(*vars, i)) {
                    610:                                if (!(v = ait_allocVar()))
                    611:                                        return NULL;
                    612:                                else
                    613:                                        array_Set(*vars, i, v);
                    614:                        }
                    615:        }
                    616: 
                    617:        return array(*vars, n, ait_val_t*);
                    618: }
                    619: 
                    620: /*
                    621:  * ait_clrVars() - Clear ait_val_t elements from array
                    622:  *
                    623:  * @vars = Variable array
                    624:  * return: -1 error or size of array
                    625:  */
1.4       misho     626: int
1.1       misho     627: ait_clrVars(array_t * __restrict vars)
                    628: {
                    629:        register int i;
                    630:        ait_val_t *v;
                    631: 
                    632:        if (!vars)
                    633:                return -1;
                    634: 
                    635:        for (i = 0; i < array_Size(vars); i++)
                    636:                if ((v = array(vars, i, ait_val_t*)))
                    637:                        AIT_FREE_VAL(v);
                    638: 
                    639:        return array_Size(vars);
                    640: }
                    641: 
                    642: /*
                    643:  * ait_freeVars() - Free ait_val_t array
                    644:  *
                    645:  * @vars = Variable array
                    646:  * return: none
                    647:  */
1.4       misho     648: void
1.1       misho     649: ait_freeVars(array_t ** __restrict vars)
                    650: {
1.6       misho     651:        register int i;
                    652:        ait_val_t *v;
                    653: 
1.1       misho     654:        if (!vars || !*vars)
                    655:                return;
                    656: 
1.6       misho     657:        for (i = 0; i < array_Size(*vars); i++)
                    658:                if ((v = array(*vars, i, ait_val_t*))) {
                    659:                        /* free memory if isn't zero copy */
                    660:                        if (!AIT_IN(v)) {
                    661:                                AIT_FREE_VAL(v);
                    662:                                if ((*vars)->arr_data[i])
                    663:                                        e_free((*vars)->arr_data[i]);
                    664:                        } else
                    665:                                AIT_FREE_VAL(v);
                    666:                        (*vars)->arr_data[i] = NULL;
                    667:                }
                    668:        (*vars)->arr_last = -1;
                    669: 
1.1       misho     670:        array_Destroy(vars);
                    671: }
                    672: 
1.5       misho     673: /*
                    674:  * ait_resideVars() - Calculate footprint of resided variables into array
                    675:  *
                    676:  * @vars = Variable array
                    677:  * return: bytes for whole array
                    678:  */
                    679: size_t
                    680: ait_resideVars(array_t * __restrict vars)
                    681: {
                    682:        size_t ret = 0;
                    683:        register int i;
                    684: 
                    685:        if (vars) {
                    686:                ret = array_Size(vars) * sizeof(ait_val_t);
                    687:                for (i = 0; i < array_Size(vars); i++)
                    688:                        switch (AIT_TYPE(array(vars, i, ait_val_t*))) {
                    689:                                case buffer:
                    690:                                case string:
                    691:                                case data:
                    692:                                case ptr:
                    693:                                        ret += AIT_LEN(array(vars, i, ait_val_t*));
                    694:                                        break;
                    695:                                default:
                    696:                                        break;
                    697:                        }
                    698:        }
                    699: 
                    700:        return ret;
                    701: }
                    702: 
1.1       misho     703: 
                    704: /*
                    705:  * ait_allocVar() - Allocate memory for variable
                    706:  *
                    707:  * return: NULL error or new variable, after use free variable with ait_freeVar()
                    708:  */
1.4       misho     709: ait_val_t *
1.1       misho     710: ait_allocVar(void)
                    711: {
                    712:        ait_val_t *v = NULL;
                    713: 
                    714:        v = e_malloc(sizeof(ait_val_t));
                    715:        if (!v)
                    716:                return NULL;
                    717:        else
                    718:                memset(v, 0, sizeof(ait_val_t));
                    719:        v->val_type = empty;
                    720: 
                    721:        return v;
                    722: }
                    723: 
                    724: /*
                    725:  * ait_freeVar() - Free allocated memory for variable
                    726:  *
                    727:  * @val = Variable
                    728:  * return: none
                    729:  */
1.4       misho     730: void
1.1       misho     731: ait_freeVar(ait_val_t ** __restrict val)
                    732: {
                    733:        if (val && *val) {
                    734:                AIT_FREE_VAL(*val);
                    735:                e_free(*val);
                    736:                *val = NULL;
                    737:        }
                    738: }
                    739: 
                    740: /*
                    741:  * ait_makeVar() - Allocate memory and fill variable
                    742:  *
                    743:  * @type = type of variable
                    744:  * @... = arg1 is value of variable
                    745:  * @... = arg2 is length of variabla. Not required for numbers and strings!
                    746:  * return: NULL error or new variable, after use free variable with io_freeVar()
                    747:  */
                    748: ait_val_t *
                    749: ait_makeVar(ait_type_t type, ...)
                    750: {
                    751:        ait_val_t *v = NULL;
                    752:        va_list lst;
                    753:        void *p = NULL;
                    754:        uint32_t len = 0;
                    755:        uint64_t n = 0LL;
                    756: 
                    757:        v = ait_allocVar();
                    758:        if (!v)
                    759:                return NULL;
                    760: 
                    761:        va_start(lst, type);
                    762:        switch (type) {
                    763:                case empty:
                    764:                        v->val_type = (uint8_t) empty;
                    765:                        break;
                    766:                case ptr:
                    767:                        p = va_arg(lst, void*);
                    768:                        len = va_arg(lst, uint32_t);
                    769:                        AIT_SET_PTR(v, p, len);
                    770:                        break;
                    771:                case data:
                    772:                        p = va_arg(lst, void*);
                    773:                        len = va_arg(lst, uint32_t);
                    774:                        AIT_SET_DATA(v, p, len);
                    775:                        break;
                    776:                case buffer:
                    777:                        p = va_arg(lst, void*);
                    778:                        len = va_arg(lst, uint32_t);
                    779:                        AIT_SET_BUF(v, p, len);
                    780:                        break;
                    781:                case string:
                    782:                        p = va_arg(lst, char*);
                    783:                        AIT_SET_STR(v, (char*) p);
                    784:                        break;
                    785:                case blob:
                    786:                        n = va_arg(lst, uint32_t);
                    787:                        len = va_arg(lst, uint32_t);
                    788:                        AIT_SET_BLOB(v, n, len);
                    789:                        break;
                    790:                case f32:
                    791:                        AIT_SET_F32(v, (float) va_arg(lst, double));
                    792:                        break;
                    793:                case f64:
                    794:                        AIT_SET_F64(v, va_arg(lst, double));
                    795:                        break;
                    796:                case u8:
                    797:                        AIT_SET_U8(v, (uint8_t) va_arg(lst, int));
                    798:                        break;
                    799:                case u16:
                    800:                        AIT_SET_U16(v, (uint16_t) va_arg(lst, int));
                    801:                        break;
                    802:                case u32:
                    803:                        AIT_SET_U32(v, va_arg(lst, uint32_t));
                    804:                        break;
                    805:                case u64:
                    806:                        AIT_SET_U64(v, va_arg(lst, uint64_t));
                    807:                        break;
                    808:                case i8:
                    809:                        AIT_SET_I8(v, (int8_t) va_arg(lst, int));
                    810:                        break;
                    811:                case i16:
                    812:                        AIT_SET_I16(v, (int16_t) va_arg(lst, int));
                    813:                        break;
                    814:                case i32:
                    815:                        AIT_SET_I32(v, va_arg(lst, int32_t));
                    816:                        break;
                    817:                case i64:
                    818:                        AIT_SET_I64(v, va_arg(lst, int64_t));
                    819:                        break;
                    820:        }
                    821:        va_end(lst);
                    822: 
                    823:        return v;
                    824: }
                    825: 
                    826: static int
                    827: _cmp_arr_key_asc(const void *a, const void *b)
                    828: {
                    829:        return AIT_KEY(*(ait_val_t**) a) - AIT_KEY(*(ait_val_t**) b);
                    830: }
                    831: 
                    832: static int
                    833: _cmp_arr_key_desc(const void *a, const void *b)
                    834: {
                    835:        return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a);
                    836: }
                    837: 
                    838: static int
                    839: _cmp_arr_val_asc(const void *a, const void *b)
                    840: {
                    841:        return AIT_RAW(*(ait_val_t**) a) - AIT_RAW(*(ait_val_t**) b);
                    842: }
                    843: 
                    844: static int
                    845: _cmp_arr_val_desc(const void *a, const void *b)
                    846: {
                    847:        return AIT_RAW(*(ait_val_t**) b) - AIT_RAW(*(ait_val_t**) a);
                    848: }
                    849: 
                    850: /*
                    851:  * ait_sortVarsByVal() - Sorting array with variables by value
                    852:  *
                    853:  * @vars = Variable array
                    854:  * @order = Sort order. If =0 ascend or !=0 descend
                    855:  * @cmp = Custom compare function for sorting. If =NULL compare by value
                    856:  * return: none
                    857:  */
1.4       misho     858: void
1.1       misho     859: ait_sortVarsByVal(array_t * __restrict vars, int order,  int (*cmp)(const void*, const void*))
                    860: {
                    861:        if (!vars)
                    862:                return;
                    863: 
                    864:        if (cmp)
1.2       misho     865:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), cmp);
1.1       misho     866:        else if (order)
1.2       misho     867:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_desc);
1.1       misho     868:        else
1.2       misho     869:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_asc);
1.1       misho     870: }
                    871: 
                    872: /*
                    873:  * ait_sortVarsByKey() - Sorting array with variables by key
                    874:  *
                    875:  * @vars = Variable array
                    876:  * @order = Sort order. If =0 ascend or !=0 descend
                    877:  * return: none
                    878:  */
1.4       misho     879: void
1.1       misho     880: ait_sortVarsByKey(array_t * __restrict vars, int order)
                    881: {
                    882:        if (!vars)
                    883:                return;
                    884: 
                    885:        if (order)
1.2       misho     886:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_desc);
1.1       misho     887:        else
1.2       misho     888:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
1.1       misho     889: }
                    890: 
                    891: /*
                    892:  * ait_findKeyVars() - Find variable by key from array
                    893:  *
                    894:  * @vars = Variables
                    895:  * @key = Search key
                    896:  * return: NULL error or not found, !=NULL valid element
                    897:  */
                    898: ait_val_t *
                    899: ait_findKeyVars(array_t * __restrict vars, u_short key)
                    900: {
                    901:        array_t *tmp;
                    902:        ait_val_t **vv, *v = NULL;
                    903:        register int i;
                    904:        const u_char *p;
                    905: 
                    906:        if (!vars)
                    907:                return NULL;
                    908: 
                    909:        if (array_Copy(&tmp, vars) == -1)
                    910:                return NULL;
                    911:        else
1.2       misho     912:                qsort(tmp->arr_data, tmp->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
1.1       misho     913: 
                    914:        /* binary search */
                    915:        for (p = (const u_char*) tmp->arr_data, i = array_Size(tmp); i; i >>= 1) {
1.2       misho     916:                vv = (ait_val_t**) (p + (i >> 1) * sizeof(uintptr_t));
1.1       misho     917:                if (!(key - AIT_KEY(*vv))) {    /* found! */
                    918:                        v = *vv;
                    919:                        break;
                    920:                }
                    921:                if ((key - AIT_KEY(*vv)) > 0) { /* move right key > current */
1.2       misho     922:                        p = (const u_char*) vv + sizeof(uintptr_t);
1.1       misho     923:                        i--;
                    924:                }                               /* else move left */
                    925:        }
                    926: 
                    927:        array_Destroy(&tmp);
                    928:        return v;
                    929: }
                    930: 
                    931: /*
                    932:  * ait_hashVar() - Generate hash key for variable from string or value
                    933:  *
                    934:  * @v = variable
                    935:  * @key = key string for hash, if =NULL hash will built from variable
                    936:  * return: hash key
                    937:  */
                    938: u_short
                    939: ait_hashVar(ait_val_t * __restrict v, const char * __restrict key)
                    940: {
                    941:        void *p;
                    942:        u_short cksum;
                    943:        int l;
                    944: 
                    945:        if (!v)
                    946:                return 0;
                    947: 
                    948:        if (key) {
                    949:                p = (void*) key;
                    950:                l = (strlen(key) + 1) / 2;
                    951:        } else {
                    952:                switch (AIT_TYPE(v)) {
                    953:                        case empty:
                    954:                                AIT_KEY(v) = 0;
                    955:                                return 0;
                    956:                        case string:
                    957:                        case buffer:
                    958:                                p = AIT_ADDR(v);
                    959:                                l = AIT_LEN(v) / 2;
                    960:                                break;
                    961:                        case data:
                    962:                                p = v->val_data;
                    963:                                l = AIT_LEN(v) / 2;
                    964:                                break;
                    965:                        default:
                    966:                                p = &AIT_RAW(v);
                    967:                                l = sizeof AIT_RAW(v) / 2;
                    968:                                break;
                    969:                }
                    970:        }
                    971: 
                    972:        cksum = crcFletcher16((u_short*) p, l);
                    973: 
                    974:        if (AIT_BE(v))
                    975:                AIT_KEY(v) = htobe16(cksum);
                    976:        else if (AIT_LE(v))
                    977:                AIT_KEY(v) = htole16(cksum);
                    978:        else
                    979:                AIT_KEY(v) = cksum;
                    980: 
                    981:        return AIT_KEY(v);
                    982: }
                    983: 
                    984: /*
                    985:  * ait_hashKeyVars() - Generate hash keys for variables
                    986:  *
                    987:  * @vars = Variables
                    988:  * return -1 error or 0 ok
                    989:  */
1.4       misho     990: int
1.1       misho     991: ait_hashKeyVars(array_t * __restrict vars)
                    992: {
                    993:        register int i;
                    994: 
                    995:        if (!vars)
                    996:                return -1;
                    997: 
                    998:        for (i = 0; i < array_Size(vars); i++)
                    999:                ait_hashVar(array(vars, i, ait_val_t*), NULL);
                   1000: 
                   1001:        return 0;
                   1002: }
                   1003: 
                   1004: /*
                   1005:  * ait_findKeyHash() - Find variable by hash string from array
                   1006:  *
                   1007:  * @vars = Variables
                   1008:  * @key = Search string
                   1009:  * return: NULL error or not found, !=NULL valid element
                   1010:  */
1.4       misho    1011: ait_val_t *
1.1       misho    1012: ait_findKeyHash(array_t * __restrict vars, const char * __restrict key)
                   1013: {
                   1014:        u_short k = 0;
                   1015: 
                   1016:        if (!vars || !key)
                   1017:                return NULL;
                   1018: 
                   1019:        k = crcFletcher16((u_short*) key, (strlen(key) + 1) / 2);
                   1020:        return ait_findKeyVars(vars, k);
                   1021: }
                   1022: 
                   1023: /*
                   1024:  * ait_sprintfVar() - Builtin string variable from formatted input
                   1025:  *
                   1026:  * @v = variable
                   1027:  * @fmt = format string
                   1028:  * @... = argument(s)
                   1029:  * return: -1 error or >0 copied bytes to variable
                   1030:  */
                   1031: int
1.2       misho    1032: ait_sprintfVar(ait_val_t * __restrict v, const char *fmt, ...)
1.1       misho    1033: {
                   1034:        int ret = 0;
                   1035:        va_list lst;
1.9       misho    1036:        char str[STRSIZ] = { [0 ... STRSIZ - 1] = 0 };
1.1       misho    1037: 
                   1038:        if (!v || !fmt)
                   1039:                return -1;
                   1040: 
                   1041:        va_start(lst, fmt);
1.9       misho    1042:        ret = vsnprintf(str, sizeof str - 1, fmt, lst);
1.1       misho    1043:        va_end(lst);
                   1044: 
1.9       misho    1045:        if (ret > -1) {
1.1       misho    1046:                AIT_FREE_VAL(v);
                   1047:                AIT_SET_STR(v, str);
                   1048:        } else
                   1049:                LOGERR;
                   1050: 
                   1051:        return ret;
                   1052: }
                   1053: 
                   1054: /*
                   1055:  * ait_setlikeVar() - Set variable like ...
                   1056:  *
                   1057:  * @v = variable
                   1058:  * @t = type of data
                   1059:  * @l = length of data
                   1060:  * @... = data
                   1061:  * return: -1 error or 0 ok
                   1062:  */
1.4       misho    1063: int
1.1       misho    1064: ait_setlikeVar(ait_val_t * __restrict v, ait_type_t t, u_int l, ...)
                   1065: {
                   1066:        va_list lst;
                   1067: 
                   1068:        if (!v)
                   1069:                return -1;
                   1070: 
                   1071:        AIT_FREE_VAL(v);
                   1072:        AIT_INIT_VAL2(v, t);
                   1073:        AIT_LEN(v) = l;
                   1074:        AIT_IN(v) = 1;
                   1075: 
                   1076:        va_start(lst, l);
                   1077:        switch (AIT_TYPE(v)) {
                   1078:                case ptr:
                   1079:                case buffer:
                   1080:                case string:
                   1081:                        AIT_ADDR(v) = va_arg(lst, void*);
                   1082:                        break;
                   1083:                default:
                   1084:                        AIT_RAW(v) = va_arg(lst, uint64_t);
                   1085:                        break;
                   1086:        }
                   1087:        va_end(lst);
                   1088: 
                   1089:        return 0;
                   1090: }
                   1091: 
                   1092: /*
                   1093:  * ait_getlikeVar() - Get variable like ...
                   1094:  *
                   1095:  * @v = variable
                   1096:  * return: return raw data
                   1097:  */
1.4       misho    1098: uint64_t
1.1       misho    1099: ait_getlikeVar(ait_val_t * __restrict v)
                   1100: {
                   1101:        if (!v)
                   1102:                return (uintptr_t) -1;
                   1103: 
                   1104:        return AIT_RAW(v);
                   1105: }
                   1106: 
                   1107: /*
                   1108:  * ait_cmpVar() - Compare two variables
                   1109:  *
                   1110:  * @a = 1st variable
                   1111:  * @b = 2nd variable
                   1112:  * return: 0 is equal or !=0 is different
                   1113:  */
1.4       misho    1114: int
1.1       misho    1115: ait_cmpVar(ait_val_t * __restrict a, ait_val_t * __restrict b)
                   1116: {
                   1117:        intptr_t ret;
                   1118: 
                   1119:        if (!(ret = (a - b)))
                   1120:                return ret;
                   1121:        if ((ret = AIT_TYPE(a) - AIT_TYPE(b)))
                   1122:                return ret;
                   1123:        if ((ret = AIT_LEN(a) - AIT_LEN(b)))
                   1124:                return ret;
                   1125: 
                   1126:        switch (AIT_TYPE(a)) {
                   1127:                case buffer:
                   1128:                        ret = memcmp(AIT_GET_BUF(a), AIT_GET_BUF(b), AIT_LEN(a));
                   1129:                        break;
                   1130:                case string:
                   1131:                        ret = strncmp(AIT_GET_STR(a), AIT_GET_STR(b), AIT_LEN(a));
                   1132:                        break;
                   1133:                case data:
                   1134:                        ret = memcmp(AIT_GET_DATA(a), AIT_GET_DATA(b), AIT_LEN(a));
                   1135:                        break;
                   1136:                case ptr:
                   1137:                        ret = AIT_ADDR(a) - AIT_ADDR(b);
                   1138:                        break;
                   1139:                default:
                   1140:                        ret = AIT_RAW(a) - AIT_RAW(b);
                   1141:                        break;
                   1142:        }
                   1143: 
                   1144:        return (int) ret;
                   1145: }

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