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

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