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

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

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