Annotation of libelwix/src/vars.c, revision 1.4.20.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.4.20.1! misho       6: * $Id: vars.c,v 1.4 2013/05/30 09:07:34 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: 
                     15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
                     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:
                    126:                                if (AIT_LEN(val) > buflen - Limit) {
                    127:                                        elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d "
                    128:                                                        "needed min %d", buflen, Limit + AIT_LEN(val));
                    129:                                        return -1;
                    130:                                } else
                    131:                                        Limit += AIT_LEN(val);
                    132: 
                    133:                                memcpy(dat, val->val.buffer, AIT_LEN(val));
                    134:                                /* Debug:: data offset in packet, not matter for anything! */
                    135:                                v[i].val.net = dat - buf;
                    136:                                dat += AIT_LEN(val);
                    137:                                break;
                    138:                        default:
                    139:                                elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
                    140:                                                AIT_TYPE(val), i);
                    141:                                return -1;
                    142:                }
                    143:        }
                    144: 
                    145:        return Limit;
                    146: }
                    147: 
1.4       misho     148: static inline array_t *
1.1       misho     149: buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
                    150: {
                    151:        array_t *vars;
                    152:        int Limit = 0;
                    153:        register int i;
                    154:        ait_val_t *v, *val;
                    155:        u_char *dat;
                    156: 
                    157:        assert(buf);
                    158:        if (!buf || !buflen || !vnum)
                    159:                return NULL;
                    160: 
                    161:        Limit = sizeof(ait_val_t) * vnum;
                    162:        if (Limit > buflen) {
                    163:                elwix_SetErr(EMSGSIZE, "Short buffer buflen=%d needed min %d", 
                    164:                                buflen, Limit);
                    165:                return NULL;
                    166:        } else {
                    167:                if (!(vars = array_Init(vnum)))
                    168:                        return NULL;
                    169: 
                    170:                v = (ait_val_t*) buf;
                    171:                dat = buf + Limit;
                    172:        }
                    173: 
                    174:        /* de-marshaling */
                    175:        for (i = 0; i < array_Size(vars); i++) {
                    176:                if (!zcpy) {
                    177:                        val = e_malloc(sizeof(ait_val_t));
                    178:                        if (!val) {
                    179:                                if (!zcpy)
                    180:                                        array_Free(vars);
                    181:                                array_Destroy(&vars);
                    182:                                return NULL;
                    183:                        }
                    184:                        AIT_IN(val) = 0;
                    185:                } else {
                    186:                        val = v + i;
                    187:                        AIT_IN(val) = 1;
                    188:                }
                    189:                array_Set(vars, i, val);
                    190: 
                    191:                val->val_type = v[i].val_type;
                    192:                AIT_BE(val) = AIT_BE(&v[i]);
                    193:                AIT_LE(val) = AIT_LE(&v[i]);
                    194:                if (AIT_BE(val)) {
                    195:                        AIT_LEN(val) = be32toh(AIT_LEN(&v[i]));
                    196:                        AIT_KEY(val) = be16toh(AIT_KEY(&v[i]));
                    197:                }
                    198:                if (AIT_LE(val)) {
                    199:                        AIT_LEN(val) = le32toh(AIT_LEN(&v[i]));
                    200:                        AIT_KEY(val) = le16toh(AIT_KEY(&v[i]));
                    201:                }
                    202: 
                    203:                switch (AIT_TYPE(val)) {
                    204:                        case blob:
                    205:                        case f32:
                    206:                        case f64:
                    207:                        case i8:
                    208:                        case i16:
                    209:                        case i32:
                    210:                        case i64:
                    211:                        case u8:
                    212:                        case u16:
                    213:                        case u32:
                    214:                        case u64:
                    215:                                if (AIT_BE(val))
                    216:                                        val->val.net = be64toh(v[i].val.net);
                    217:                                if (AIT_LE(val))
                    218:                                        val->val.net = le64toh(v[i].val.net);
                    219:                                break;
                    220:                        case data:
                    221:                                /* WARNING:: remap data type to buffer */
                    222:                                val->val_type = buffer;
                    223:                        case buffer:
                    224:                        case string:
                    225:                                if (!zcpy) {
                    226:                                        val->val.buffer = e_malloc(AIT_LEN(val));
                    227:                                        if (!val->val.buffer) {
                    228:                                                array_Free(vars);
                    229:                                                array_Destroy(&vars);
                    230:                                                return NULL;
                    231:                                        } else
                    232:                                                memcpy(val->val.buffer, dat, AIT_LEN(val));
                    233:                                } else
                    234:                                        val->val.buffer = dat;
                    235:                                dat += AIT_LEN(val);
                    236:                                break;
                    237:                        default:
                    238:                                elwix_SetErr(EINVAL, "Unsupported variable type=%d at element #%d", 
                    239:                                                AIT_TYPE(val), i);
                    240:                                if (!zcpy)
                    241:                                        array_Free(vars);
                    242:                                array_Destroy(&vars);
                    243:                                return NULL;
                    244:                }
                    245:        }
                    246: 
                    247:        return vars;
                    248: }
                    249: 
                    250: 
                    251: /* buffer marshaling with swapping bytes to network order */
                    252: 
                    253: /*
                    254:  * ait_vars2buffer() - Marshaling data from array with variables to buffer
                    255:  *
                    256:  * @buf = Buffer
                    257:  * @buflen = Size of buffer
                    258:  * @vars = Variable array
                    259:  * return: -1 error, 0 nothing done or >0 size of marshaled data
                    260:  */
1.4       misho     261: int
1.1       misho     262: ait_vars2buffer(u_char * __restrict buf, int buflen, array_t * __restrict vars)
                    263: {
                    264:        return vars2buffer(buf, buflen, 42, vars);
                    265: }
                    266: 
                    267: /*
                    268:  * ait_buffer2vars() - De-marshaling data from buffer to array with variables
                    269:  *
                    270:  * @buf = Buffer
                    271:  * @buflen = Size of buffer
                    272:  * @vnum = Number of variables into buffer
                    273:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
                    274:                *DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
                    275:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
                    276:  */
1.4       misho     277: array_t *
1.1       misho     278: ait_buffer2vars(u_char * __restrict buf, int buflen, int vnum, int zcpy)
                    279: {
                    280:        return buffer2vars(buf, buflen, vnum, zcpy);
                    281: }
                    282: 
                    283: /* buffer marshaling without swapping bytes to network order */
                    284: 
                    285: /*
                    286:  * ait_vars2map() - Marshaling data from array with variables to memory map
                    287:  *
                    288:  * @buf = Buffer
                    289:  * @buflen = Size of buffer
                    290:  * @vars = Variable array
                    291:  * return: -1 error, 0 nothing done or >0 size of marshaled data
                    292:  */
1.4       misho     293: int
1.1       misho     294: ait_vars2map(u_char *buf, int buflen, array_t *vars)
                    295: {
                    296:        return vars2buffer(buf, buflen, 0, vars);
                    297: }
                    298: 
                    299: /*
                    300:  * ait_map2vars() - De-marshaling data from memory map to array with variables
                    301:  *
                    302:  * @buf = Buffer
                    303:  * @buflen = Size of buffer
                    304:  * @vnum = Number of variables into buffer
                    305:  * @zcpy = Zero-copy for variables, if !=0 don't use array_Free() for free variables and 
                    306:                *DON'T MODIFY OR DESTROY BUFFER*. =0 call array_Free() before array_Destroy()
                    307:  * return: =NULL error, !=NULL allocated variable array, after use must free with array_Destroy()
                    308:  */
1.4       misho     309: array_t *
1.1       misho     310: ait_map2vars(u_char *buf, int buflen, int vnum, int zcpy)
                    311: {
                    312:        return buffer2vars(buf, buflen, vnum, zcpy);
                    313: }
                    314: 
                    315: 
                    316: /* variables array */
                    317: 
                    318: /*
                    319:  * ait_allocVars() - Allocate ait_val_t array
                    320:  *
                    321:  * @varnum = Number of variables
                    322:  * return: =NULL error or !=NULL allocated array
                    323:  */
1.4       misho     324: array_t *
1.1       misho     325: ait_allocVars(int varnum)
                    326: {
                    327:        array_t *arr;
                    328:        register int i;
                    329:        ait_val_t *v;
                    330: 
                    331:        if (!(arr = array_Init(varnum)))
                    332:                return NULL;
                    333: 
                    334:        for (i = 0; i < array_Size(arr); i++) {
                    335:                if (!(v = ait_allocVar())) {
                    336:                        ait_freeVars(&arr);
                    337:                        return NULL;
                    338:                } else
                    339:                        array_Set(arr, i, v);
                    340:        }
                    341: 
                    342:        return arr;
                    343: }
                    344: 
                    345: /*
                    346:  * ait_getVars() - Get ait_val_t element from array and if not exists allocate it
                    347:  *
                    348:  * @vars = Variable array
                    349:  * @n = index of variable into array
                    350:  * return: NULL error or !=NULL ait_val_t element
                    351:  */
1.4       misho     352: ait_val_t *
1.1       misho     353: ait_getVars(array_t ** __restrict vars, int n)
                    354: {
                    355:        register int i;
                    356:        ait_val_t *v;
                    357: 
                    358:        if (!vars)
                    359:                return NULL;
                    360: 
                    361:        if (!*vars) {
                    362:                if (!(*vars = ait_allocVars(n + 1)))
                    363:                        return NULL;
                    364:        } else if (n >= (i = array_Size(*vars))) {
                    365:                if (array_Grow(*vars, n + 1, 0))
                    366:                        return NULL;
                    367:                for (; i < array_Size(*vars); i++)
                    368:                        if (!array_Get(*vars, i)) {
                    369:                                if (!(v = ait_allocVar()))
                    370:                                        return NULL;
                    371:                                else
                    372:                                        array_Set(*vars, i, v);
                    373:                        }
                    374:        }
                    375: 
                    376:        return array(*vars, n, ait_val_t*);
                    377: }
                    378: 
                    379: /*
                    380:  * ait_clrVars() - Clear ait_val_t elements from array
                    381:  *
                    382:  * @vars = Variable array
                    383:  * return: -1 error or size of array
                    384:  */
1.4       misho     385: int
1.1       misho     386: ait_clrVars(array_t * __restrict vars)
                    387: {
                    388:        register int i;
                    389:        ait_val_t *v;
                    390: 
                    391:        if (!vars)
                    392:                return -1;
                    393: 
                    394:        for (i = 0; i < array_Size(vars); i++)
                    395:                if ((v = array(vars, i, ait_val_t*)))
                    396:                        AIT_FREE_VAL(v);
                    397: 
                    398:        return array_Size(vars);
                    399: }
                    400: 
                    401: /*
                    402:  * ait_freeVars() - Free ait_val_t array
                    403:  *
                    404:  * @vars = Variable array
                    405:  * return: none
                    406:  */
1.4       misho     407: void
1.1       misho     408: ait_freeVars(array_t ** __restrict vars)
                    409: {
                    410:        if (!vars || !*vars)
                    411:                return;
                    412: 
                    413:        ait_clrVars(*vars);
                    414:        array_Free(*vars);
                    415:        array_Destroy(vars);
                    416: }
                    417: 
1.4.20.1! misho     418: /*
        !           419:  * ait_resideVars() - Calculate footprint of resided variables into array
        !           420:  *
        !           421:  * @vars = Variable array
        !           422:  * return: -1 error or !=-1 bytes for whole array
        !           423:  */
        !           424: ssize_t
        !           425: ait_resideVars(array_t * __restrict vars)
        !           426: {
        !           427:        ssize_t ret = 0;
        !           428:        register int i;
        !           429: 
        !           430:        if (!vars)
        !           431:                return -1;
        !           432: 
        !           433:        ret = array_Size(vars) * sizeof(ait_val_t);
        !           434:        for (i = 0; i < array_Size(vars); i++)
        !           435:                switch (AIT_TYPE(array(vars, i, ait_val_t*))) {
        !           436:                        case buffer:
        !           437:                        case string:
        !           438:                        case data:
        !           439:                        case ptr:
        !           440:                                ret += AIT_LEN(array(vars, i, ait_val_t*));
        !           441:                                break;
        !           442:                        default:
        !           443:                                break;
        !           444:                }
        !           445: 
        !           446:        return ret;
        !           447: }
        !           448: 
1.1       misho     449: 
                    450: /*
                    451:  * ait_allocVar() - Allocate memory for variable
                    452:  *
                    453:  * return: NULL error or new variable, after use free variable with ait_freeVar()
                    454:  */
1.4       misho     455: ait_val_t *
1.1       misho     456: ait_allocVar(void)
                    457: {
                    458:        ait_val_t *v = NULL;
                    459: 
                    460:        v = e_malloc(sizeof(ait_val_t));
                    461:        if (!v)
                    462:                return NULL;
                    463:        else
                    464:                memset(v, 0, sizeof(ait_val_t));
                    465:        v->val_type = empty;
                    466: 
                    467:        return v;
                    468: }
                    469: 
                    470: /*
                    471:  * ait_freeVar() - Free allocated memory for variable
                    472:  *
                    473:  * @val = Variable
                    474:  * return: none
                    475:  */
1.4       misho     476: void
1.1       misho     477: ait_freeVar(ait_val_t ** __restrict val)
                    478: {
                    479:        if (val && *val) {
                    480:                AIT_FREE_VAL(*val);
                    481:                e_free(*val);
                    482:                *val = NULL;
                    483:        }
                    484: }
                    485: 
                    486: /*
                    487:  * ait_makeVar() - Allocate memory and fill variable
                    488:  *
                    489:  * @type = type of variable
                    490:  * @... = arg1 is value of variable
                    491:  * @... = arg2 is length of variabla. Not required for numbers and strings!
                    492:  * return: NULL error or new variable, after use free variable with io_freeVar()
                    493:  */
                    494: ait_val_t *
                    495: ait_makeVar(ait_type_t type, ...)
                    496: {
                    497:        ait_val_t *v = NULL;
                    498:        va_list lst;
                    499:        void *p = NULL;
                    500:        uint32_t len = 0;
                    501:        uint64_t n = 0LL;
                    502: 
                    503:        v = ait_allocVar();
                    504:        if (!v)
                    505:                return NULL;
                    506: 
                    507:        va_start(lst, type);
                    508:        switch (type) {
                    509:                case empty:
                    510:                        v->val_type = (uint8_t) empty;
                    511:                        break;
                    512:                case ptr:
                    513:                        p = va_arg(lst, void*);
                    514:                        len = va_arg(lst, uint32_t);
                    515:                        AIT_SET_PTR(v, p, len);
                    516:                        break;
                    517:                case data:
                    518:                        p = va_arg(lst, void*);
                    519:                        len = va_arg(lst, uint32_t);
                    520:                        AIT_SET_DATA(v, p, len);
                    521:                        break;
                    522:                case buffer:
                    523:                        p = va_arg(lst, void*);
                    524:                        len = va_arg(lst, uint32_t);
                    525:                        AIT_SET_BUF(v, p, len);
                    526:                        break;
                    527:                case string:
                    528:                        p = va_arg(lst, char*);
                    529:                        AIT_SET_STR(v, (char*) p);
                    530:                        break;
                    531:                case blob:
                    532:                        n = va_arg(lst, uint32_t);
                    533:                        len = va_arg(lst, uint32_t);
                    534:                        AIT_SET_BLOB(v, n, len);
                    535:                        break;
                    536:                case f32:
                    537:                        AIT_SET_F32(v, (float) va_arg(lst, double));
                    538:                        break;
                    539:                case f64:
                    540:                        AIT_SET_F64(v, va_arg(lst, double));
                    541:                        break;
                    542:                case u8:
                    543:                        AIT_SET_U8(v, (uint8_t) va_arg(lst, int));
                    544:                        break;
                    545:                case u16:
                    546:                        AIT_SET_U16(v, (uint16_t) va_arg(lst, int));
                    547:                        break;
                    548:                case u32:
                    549:                        AIT_SET_U32(v, va_arg(lst, uint32_t));
                    550:                        break;
                    551:                case u64:
                    552:                        AIT_SET_U64(v, va_arg(lst, uint64_t));
                    553:                        break;
                    554:                case i8:
                    555:                        AIT_SET_I8(v, (int8_t) va_arg(lst, int));
                    556:                        break;
                    557:                case i16:
                    558:                        AIT_SET_I16(v, (int16_t) va_arg(lst, int));
                    559:                        break;
                    560:                case i32:
                    561:                        AIT_SET_I32(v, va_arg(lst, int32_t));
                    562:                        break;
                    563:                case i64:
                    564:                        AIT_SET_I64(v, va_arg(lst, int64_t));
                    565:                        break;
                    566:        }
                    567:        va_end(lst);
                    568: 
                    569:        return v;
                    570: }
                    571: 
                    572: static int
                    573: _cmp_arr_key_asc(const void *a, const void *b)
                    574: {
                    575:        return AIT_KEY(*(ait_val_t**) a) - AIT_KEY(*(ait_val_t**) b);
                    576: }
                    577: 
                    578: static int
                    579: _cmp_arr_key_desc(const void *a, const void *b)
                    580: {
                    581:        return AIT_KEY(*(ait_val_t**) b) - AIT_KEY(*(ait_val_t**) a);
                    582: }
                    583: 
                    584: static int
                    585: _cmp_arr_val_asc(const void *a, const void *b)
                    586: {
                    587:        return AIT_RAW(*(ait_val_t**) a) - AIT_RAW(*(ait_val_t**) b);
                    588: }
                    589: 
                    590: static int
                    591: _cmp_arr_val_desc(const void *a, const void *b)
                    592: {
                    593:        return AIT_RAW(*(ait_val_t**) b) - AIT_RAW(*(ait_val_t**) a);
                    594: }
                    595: 
                    596: /*
                    597:  * ait_sortVarsByVal() - Sorting array with variables by value
                    598:  *
                    599:  * @vars = Variable array
                    600:  * @order = Sort order. If =0 ascend or !=0 descend
                    601:  * @cmp = Custom compare function for sorting. If =NULL compare by value
                    602:  * return: none
                    603:  */
1.4       misho     604: void
1.1       misho     605: ait_sortVarsByVal(array_t * __restrict vars, int order,  int (*cmp)(const void*, const void*))
                    606: {
                    607:        if (!vars)
                    608:                return;
                    609: 
                    610:        if (cmp)
1.2       misho     611:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), cmp);
1.1       misho     612:        else if (order)
1.2       misho     613:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_desc);
1.1       misho     614:        else
1.2       misho     615:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_val_asc);
1.1       misho     616: }
                    617: 
                    618: /*
                    619:  * ait_sortVarsByKey() - Sorting array with variables by key
                    620:  *
                    621:  * @vars = Variable array
                    622:  * @order = Sort order. If =0 ascend or !=0 descend
                    623:  * return: none
                    624:  */
1.4       misho     625: void
1.1       misho     626: ait_sortVarsByKey(array_t * __restrict vars, int order)
                    627: {
                    628:        if (!vars)
                    629:                return;
                    630: 
                    631:        if (order)
1.2       misho     632:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_desc);
1.1       misho     633:        else
1.2       misho     634:                qsort(vars->arr_data, vars->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
1.1       misho     635: }
                    636: 
                    637: /*
                    638:  * ait_findKeyVars() - Find variable by key from array
                    639:  *
                    640:  * @vars = Variables
                    641:  * @key = Search key
                    642:  * return: NULL error or not found, !=NULL valid element
                    643:  */
                    644: ait_val_t *
                    645: ait_findKeyVars(array_t * __restrict vars, u_short key)
                    646: {
                    647:        array_t *tmp;
                    648:        ait_val_t **vv, *v = NULL;
                    649:        register int i;
                    650:        const u_char *p;
                    651: 
                    652:        if (!vars)
                    653:                return NULL;
                    654: 
                    655:        if (array_Copy(&tmp, vars) == -1)
                    656:                return NULL;
                    657:        else
1.2       misho     658:                qsort(tmp->arr_data, tmp->arr_num, sizeof(uintptr_t), _cmp_arr_key_asc);
1.1       misho     659: 
                    660:        /* binary search */
                    661:        for (p = (const u_char*) tmp->arr_data, i = array_Size(tmp); i; i >>= 1) {
1.2       misho     662:                vv = (ait_val_t**) (p + (i >> 1) * sizeof(uintptr_t));
1.1       misho     663:                if (!(key - AIT_KEY(*vv))) {    /* found! */
                    664:                        v = *vv;
                    665:                        break;
                    666:                }
                    667:                if ((key - AIT_KEY(*vv)) > 0) { /* move right key > current */
1.2       misho     668:                        p = (const u_char*) vv + sizeof(uintptr_t);
1.1       misho     669:                        i--;
                    670:                }                               /* else move left */
                    671:        }
                    672: 
                    673:        array_Destroy(&tmp);
                    674:        return v;
                    675: }
                    676: 
                    677: /*
                    678:  * ait_hashVar() - Generate hash key for variable from string or value
                    679:  *
                    680:  * @v = variable
                    681:  * @key = key string for hash, if =NULL hash will built from variable
                    682:  * return: hash key
                    683:  */
                    684: u_short
                    685: ait_hashVar(ait_val_t * __restrict v, const char * __restrict key)
                    686: {
                    687:        void *p;
                    688:        u_short cksum;
                    689:        int l;
                    690: 
                    691:        if (!v)
                    692:                return 0;
                    693: 
                    694:        if (key) {
                    695:                p = (void*) key;
                    696:                l = (strlen(key) + 1) / 2;
                    697:        } else {
                    698:                switch (AIT_TYPE(v)) {
                    699:                        case empty:
                    700:                                AIT_KEY(v) = 0;
                    701:                                return 0;
                    702:                        case string:
                    703:                        case buffer:
                    704:                                p = AIT_ADDR(v);
                    705:                                l = AIT_LEN(v) / 2;
                    706:                                break;
                    707:                        case data:
                    708:                                p = v->val_data;
                    709:                                l = AIT_LEN(v) / 2;
                    710:                                break;
                    711:                        default:
                    712:                                p = &AIT_RAW(v);
                    713:                                l = sizeof AIT_RAW(v) / 2;
                    714:                                break;
                    715:                }
                    716:        }
                    717: 
                    718:        cksum = crcFletcher16((u_short*) p, l);
                    719: 
                    720:        if (AIT_BE(v))
                    721:                AIT_KEY(v) = htobe16(cksum);
                    722:        else if (AIT_LE(v))
                    723:                AIT_KEY(v) = htole16(cksum);
                    724:        else
                    725:                AIT_KEY(v) = cksum;
                    726: 
                    727:        return AIT_KEY(v);
                    728: }
                    729: 
                    730: /*
                    731:  * ait_hashKeyVars() - Generate hash keys for variables
                    732:  *
                    733:  * @vars = Variables
                    734:  * return -1 error or 0 ok
                    735:  */
1.4       misho     736: int
1.1       misho     737: ait_hashKeyVars(array_t * __restrict vars)
                    738: {
                    739:        register int i;
                    740: 
                    741:        if (!vars)
                    742:                return -1;
                    743: 
                    744:        for (i = 0; i < array_Size(vars); i++)
                    745:                ait_hashVar(array(vars, i, ait_val_t*), NULL);
                    746: 
                    747:        return 0;
                    748: }
                    749: 
                    750: /*
                    751:  * ait_findKeyHash() - Find variable by hash string from array
                    752:  *
                    753:  * @vars = Variables
                    754:  * @key = Search string
                    755:  * return: NULL error or not found, !=NULL valid element
                    756:  */
1.4       misho     757: ait_val_t *
1.1       misho     758: ait_findKeyHash(array_t * __restrict vars, const char * __restrict key)
                    759: {
                    760:        u_short k = 0;
                    761: 
                    762:        if (!vars || !key)
                    763:                return NULL;
                    764: 
                    765:        k = crcFletcher16((u_short*) key, (strlen(key) + 1) / 2);
                    766:        return ait_findKeyVars(vars, k);
                    767: }
                    768: 
                    769: /*
                    770:  * ait_sprintfVar() - Builtin string variable from formatted input
                    771:  *
                    772:  * @v = variable
                    773:  * @fmt = format string
                    774:  * @... = argument(s)
                    775:  * return: -1 error or >0 copied bytes to variable
                    776:  */
                    777: int
1.2       misho     778: ait_sprintfVar(ait_val_t * __restrict v, const char *fmt, ...)
1.1       misho     779: {
                    780:        int ret = 0;
                    781:        va_list lst;
                    782:        char *str = NULL;
                    783: 
                    784:        if (!v || !fmt)
                    785:                return -1;
                    786: 
                    787:        va_start(lst, fmt);
                    788:        ret = vasprintf(&str, fmt, lst);
                    789:        va_end(lst);
                    790: 
                    791:        if (str && ret > -1) {
                    792:                AIT_FREE_VAL(v);
                    793:                AIT_SET_STR(v, str);
                    794:        } else
                    795:                LOGERR;
                    796: 
                    797:        if (str)
                    798:                free(str);
                    799:        return ret;
                    800: }
                    801: 
                    802: /*
                    803:  * ait_setlikeVar() - Set variable like ...
                    804:  *
                    805:  * @v = variable
                    806:  * @t = type of data
                    807:  * @l = length of data
                    808:  * @... = data
                    809:  * return: -1 error or 0 ok
                    810:  */
1.4       misho     811: int
1.1       misho     812: ait_setlikeVar(ait_val_t * __restrict v, ait_type_t t, u_int l, ...)
                    813: {
                    814:        va_list lst;
                    815: 
                    816:        if (!v)
                    817:                return -1;
                    818: 
                    819:        AIT_FREE_VAL(v);
                    820:        AIT_INIT_VAL2(v, t);
                    821:        AIT_LEN(v) = l;
                    822:        AIT_IN(v) = 1;
                    823: 
                    824:        va_start(lst, l);
                    825:        switch (AIT_TYPE(v)) {
                    826:                case ptr:
                    827:                case buffer:
                    828:                case string:
                    829:                        AIT_ADDR(v) = va_arg(lst, void*);
                    830:                        break;
                    831:                default:
                    832:                        AIT_RAW(v) = va_arg(lst, uint64_t);
                    833:                        break;
                    834:        }
                    835:        va_end(lst);
                    836: 
                    837:        return 0;
                    838: }
                    839: 
                    840: /*
                    841:  * ait_getlikeVar() - Get variable like ...
                    842:  *
                    843:  * @v = variable
                    844:  * return: return raw data
                    845:  */
1.4       misho     846: uint64_t
1.1       misho     847: ait_getlikeVar(ait_val_t * __restrict v)
                    848: {
                    849:        if (!v)
                    850:                return (uintptr_t) -1;
                    851: 
                    852:        return AIT_RAW(v);
                    853: }
                    854: 
                    855: /*
                    856:  * ait_cmpVar() - Compare two variables
                    857:  *
                    858:  * @a = 1st variable
                    859:  * @b = 2nd variable
                    860:  * return: 0 is equal or !=0 is different
                    861:  */
1.4       misho     862: int
1.1       misho     863: ait_cmpVar(ait_val_t * __restrict a, ait_val_t * __restrict b)
                    864: {
                    865:        intptr_t ret;
                    866: 
                    867:        if (!(ret = (a - b)))
                    868:                return ret;
                    869:        if ((ret = AIT_TYPE(a) - AIT_TYPE(b)))
                    870:                return ret;
                    871:        if ((ret = AIT_LEN(a) - AIT_LEN(b)))
                    872:                return ret;
                    873: 
                    874:        switch (AIT_TYPE(a)) {
                    875:                case buffer:
                    876:                        ret = memcmp(AIT_GET_BUF(a), AIT_GET_BUF(b), AIT_LEN(a));
                    877:                        break;
                    878:                case string:
                    879:                        ret = strncmp(AIT_GET_STR(a), AIT_GET_STR(b), AIT_LEN(a));
                    880:                        break;
                    881:                case data:
                    882:                        ret = memcmp(AIT_GET_DATA(a), AIT_GET_DATA(b), AIT_LEN(a));
                    883:                        break;
                    884:                case ptr:
                    885:                        ret = AIT_ADDR(a) - AIT_ADDR(b);
                    886:                        break;
                    887:                default:
                    888:                        ret = AIT_RAW(a) - AIT_RAW(b);
                    889:                        break;
                    890:        }
                    891: 
                    892:        return (int) ret;
                    893: }

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