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

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.12    ! misho       6: * $Id: vars.c,v 1.11.4.4 2012/07/31 16:04:52 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: }

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