Annotation of libelwix/src/json.c, revision 1.2

1.2     ! misho       1: /*************************************************************************
        !             2: * (C) 2017 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
        !             3: *  by Michael Pounov <misho@elwix.org>
        !             4: *
        !             5: * $Author: misho $
        !             6: * $Id: json.c,v 1.1.2.11 2017/11/30 13:45:38 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 - 2017
        !            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: /* JSON error strings */
        !            50: const char *jerrstr[] = {
        !            51:        "No error",
        !            52:        "Not enough tokens were provided",
        !            53:        "Invalid character",
        !            54:        "JSON string isn't full",
        !            55:        "Invalid parameter", 
        !            56:        NULL
        !            57: };
        !            58: 
        !            59: 
        !            60: /*
        !            61:  * json_init() - Initialize JSON handler
        !            62:  *
        !            63:  * @json = JSON handler, if there is NULL then dynamically will be allocated
        !            64:  * @jstrict = JSON strict mode, when we select strict mode every unquoted value is error
        !            65:  * return: =NULL error or !=NULL ready for use JSON handler and should be free with json_free()
        !            66:  */
        !            67: json_t *
        !            68: json_init(json_t * __restrict json, int jstrict)
        !            69: {
        !            70:        json_t *j = json;
        !            71: 
        !            72:        if (!j) {
        !            73:                j = e_malloc(sizeof(json_t));
        !            74:                if (!j) {
        !            75:                        LOGERR;
        !            76:                        return NULL;
        !            77:                }
        !            78:        }
        !            79: 
        !            80:        memset(j, 0, sizeof(json_t));
        !            81:        j->h_parent = -1;
        !            82:        j->h_strict = jstrict;
        !            83: 
        !            84:        /* handler is dynamically allocated! */
        !            85:        if (!json)
        !            86:                j->h_alloc = j;
        !            87: 
        !            88:        return j;
        !            89: }
        !            90: 
        !            91: /*
        !            92:  * json_free() - Free JSON handler
        !            93:  *
        !            94:  * @json = JSON handler
        !            95:  * return: none
        !            96:  */
        !            97: void
        !            98: json_free(json_t * __restrict json)
        !            99: {
        !           100:        if (json) {
        !           101:                if (json->h_alloc)
        !           102:                        e_free(json);
        !           103:                else
        !           104:                        memset(json, 0, sizeof(json_t));
        !           105:        }
        !           106: }
        !           107: 
        !           108: static jtok_t *
        !           109: json_gettoken(json_t * __restrict json, jtok_t * __restrict jtoks, u_int toksnum)
        !           110: {
        !           111:        jtok_t *tok;
        !           112: 
        !           113:        assert(json || !(!jtoks && toksnum));
        !           114: 
        !           115:        if (json->h_next >= toksnum) {
        !           116:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           117:                return NULL;
        !           118:        } else
        !           119:                tok = &jtoks[json->h_next];
        !           120:        tok->tok_idx = json->h_next++;
        !           121:        tok->tok_start = tok->tok_end = tok->tok_parent = -1;
        !           122:        tok->tok_size = 0;
        !           123: 
        !           124:        return tok;
        !           125: }
        !           126: 
        !           127: inline void
        !           128: json_filltoken(jtok_t * __restrict tok, jtype_t type, long start, long end, long parent)
        !           129: {
        !           130:        assert(tok);
        !           131: 
        !           132:        tok->tok_type = type;
        !           133:        tok->tok_start = start;
        !           134:        tok->tok_end = end;
        !           135:        tok->tok_parent = parent;
        !           136:        tok->tok_size = 0;
        !           137: }
        !           138: 
        !           139: static int
        !           140: json_parse_string(json_t * __restrict json, const char *jstr, size_t jlen, jtok_t * __restrict jtoks, u_int toksnum)
        !           141: {
        !           142:        jtok_t  *tok;
        !           143:        u_long pos;
        !           144:        char ch;
        !           145:        register int i;
        !           146: 
        !           147:        assert(json || jstr || !(!jtoks && toksnum));
        !           148: 
        !           149:        for (pos = json->h_pos++; json->h_pos < jlen && jstr[json->h_pos]; json->h_pos++) {
        !           150:                ch = jstr[json->h_pos];
        !           151: 
        !           152:                if (ch == '\"') {
        !           153:                        if (!jtoks)
        !           154:                                return 0;
        !           155:                        if (!(tok = json_gettoken(json, jtoks, toksnum))) {
        !           156:                                json->h_pos = pos;
        !           157:                                return -1;
        !           158:                        } else
        !           159:                                json_filltoken(tok, J_STRING, pos + 1, json->h_pos, json->h_parent);
        !           160:                        return 0;
        !           161:                }
        !           162: 
        !           163:                if (ch == '\\' && json->h_pos + 1 < jlen) {
        !           164:                        switch (jstr[++json->h_pos]) {
        !           165:                                case '\"':
        !           166:                                case '/':
        !           167:                                case '\\':
        !           168:                                case 'b':
        !           169:                                case 'f':
        !           170:                                case 'r':
        !           171:                                case 'n':
        !           172:                                case 't':
        !           173:                                        /* Allowed escaped symbols */
        !           174:                                        break;
        !           175:                                case 'u':
        !           176:                                        /* Allows escaped symbol \uXXXX */
        !           177:                                        json->h_pos++;
        !           178:                                        for (i = 0; i < 4 && json->h_pos < jlen && jstr[json->h_pos]; i++, json->h_pos++) {
        !           179:                                                /* If it isn't a hex character we have an error */
        !           180:                                                if (!((jstr[json->h_pos] >= 48 && jstr[json->h_pos] <= 57) || /* 0-9 */
        !           181:                                                                (jstr[json->h_pos] >= 65 && jstr[json->h_pos] <= 70) || /* A-F */
        !           182:                                                                (jstr[json->h_pos] >= 97 && jstr[json->h_pos] <= 102))) { /* a-f */
        !           183:                                                        json->h_pos = pos;
        !           184:                                                        elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
        !           185:                                                        return -1;
        !           186:                                                }
        !           187:                                        }
        !           188:                                        json->h_pos--;
        !           189:                                        break;
        !           190:                                default:
        !           191:                                        /* Unexpected symbol */
        !           192:                                        json->h_pos = pos;
        !           193:                                        elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
        !           194:                                        return -1;
        !           195:                        }
        !           196:                }
        !           197:        }
        !           198: 
        !           199:        json->h_pos = pos;
        !           200:        elwix_SetErr(J_ERR_PART, "%s", jerrstr[J_ERR_PART]);
        !           201:        return -1;
        !           202: }
        !           203: 
        !           204: static int
        !           205: json_parse_value(json_t * __restrict json, const char *jstr, size_t jlen, jtok_t * __restrict jtoks, u_int toksnum)
        !           206: {
        !           207:        jtok_t  *tok;
        !           208:        u_long pos;
        !           209: 
        !           210:        assert(json || jstr || !(!jtoks && toksnum));
        !           211: 
        !           212:        for (pos = json->h_pos; json->h_pos < jlen && jstr[json->h_pos]; json->h_pos++) {
        !           213:                switch (jstr[json->h_pos]) {
        !           214:                        case ':':
        !           215:                                if (json->h_strict)
        !           216:                                        goto found;
        !           217:                                break;
        !           218:                        case '\t':
        !           219:                        case '\r':
        !           220:                        case '\n':
        !           221:                        case ' ':
        !           222:                        case ',':
        !           223:                        case ']':
        !           224:                        case '}':
        !           225:                                goto found;
        !           226:                }
        !           227:                if (jstr[json->h_pos] < 32 || jstr[json->h_pos] > 127) {
        !           228:                        json->h_pos = pos;
        !           229:                        elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
        !           230:                        return -1;
        !           231:                }
        !           232:        }
        !           233: 
        !           234:        if (json->h_strict) {
        !           235:                json->h_pos = pos;
        !           236:                elwix_SetErr(J_ERR_PART, "%s", jerrstr[J_ERR_PART]);
        !           237:                return -1;
        !           238:        }
        !           239: found:
        !           240:        if (jtoks) {
        !           241:                if (!(tok = json_gettoken(json, jtoks, toksnum))) {
        !           242:                        json->h_pos = pos;
        !           243:                        return -1;
        !           244:                } else
        !           245:                        json_filltoken(tok, J_VALUE, pos, json->h_pos, json->h_parent);
        !           246:        }
        !           247: 
        !           248:        json->h_pos--;
        !           249:        return 0;
        !           250: }
        !           251: 
        !           252: /*
        !           253:  * json_parse() - Parse JSON string
        !           254:  *
        !           255:  * @json = JSON handler
        !           256:  * @jstr = JSON string
        !           257:  * @jlen = JSON string length
        !           258:  * @jtoks = Token array
        !           259:  * @toksnum = Token array size, return number of allocated tokens in array
        !           260:  * return: -1 error or number of found tokens 
        !           261:  */
        !           262: u_int
        !           263: json_parse(json_t * __restrict json, const char *jstr, size_t jlen, jtok_t * __restrict jtoks, u_int toksnum)
        !           264: {
        !           265:        register int i;
        !           266:        register u_int cx;
        !           267:        jtype_t type;
        !           268:        jtok_t *tok;
        !           269:        char ch;
        !           270: 
        !           271:        if (!json || !jstr || (!jtoks && toksnum)) {
        !           272:                elwix_SetErr(J_ERR_PARAM, "%s", jerrstr[J_ERR_PARAM]);
        !           273:                return (u_int) -1;
        !           274:        }
        !           275: 
        !           276:        for (cx = json->h_next; json->h_pos < jlen && jstr[json->h_pos]; json->h_pos++) {
        !           277:                switch ((ch = jstr[json->h_pos])) {
        !           278:                        case '{':
        !           279:                        case '[':
        !           280:                                cx++;   /* start new object/array token */
        !           281:                                if (!jtoks)
        !           282:                                        break;
        !           283: 
        !           284:                                tok = json_gettoken(json, jtoks, toksnum);
        !           285:                                if (!tok)
        !           286:                                        return (u_int) -1;
        !           287:                                if (json->h_parent != -1) {
        !           288:                                        jtoks[json->h_parent].tok_size++;
        !           289:                                        tok->tok_parent = json->h_parent;
        !           290:                                }
        !           291:                                tok->tok_type = (ch == '{' ? J_OBJECT : J_ARRAY);
        !           292:                                tok->tok_start = json->h_pos;
        !           293:                                json->h_parent = json->h_next - 1;
        !           294:                                break;
        !           295:                        case '}':
        !           296:                        case ']':
        !           297:                                if (!jtoks)
        !           298:                                        break;
        !           299: 
        !           300:                                if (json->h_next < 1) {
        !           301:                                        elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
        !           302:                                        return (u_int) -1;
        !           303:                                }
        !           304: 
        !           305:                                type = (ch == '}' ? J_OBJECT : J_ARRAY);
        !           306:                                tok = &jtoks[json->h_next - 1];
        !           307:                                while (42) {
        !           308:                                        if (tok->tok_start != -1 && tok->tok_end == -1) {
        !           309:                                                if (tok->tok_type != type) {
        !           310:                                                        elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
        !           311:                                                        return (u_int) -1;
        !           312:                                                }
        !           313:                                                tok->tok_end = json->h_pos + 1;
        !           314:                                                json->h_parent = tok->tok_parent;
        !           315:                                                break;
        !           316:                                        }
        !           317:                                        if (tok->tok_parent == -1) {
        !           318:                                                if (tok->tok_type != type || json->h_parent == -1) {
        !           319:                                                        elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
        !           320:                                                        return (u_int) -1;
        !           321:                                                }
        !           322:                                                break;
        !           323:                                        }
        !           324:                                        tok = &jtoks[tok->tok_parent];
        !           325:                                }
        !           326:                                break;
        !           327:                        case '\"':
        !           328:                                if (json_parse_string(json, jstr, jlen, jtoks, toksnum) == -1)
        !           329:                                        return (u_int) -1;
        !           330:                                cx++;   /* start new string token */
        !           331:                                if (jtoks && json->h_parent != -1)
        !           332:                                        jtoks[json->h_parent].tok_size++;
        !           333:                                break;
        !           334:                        case '\t':
        !           335:                        case '\r':
        !           336:                        case '\n':
        !           337:                        case ' ':
        !           338:                                /* whitespace, skip */
        !           339:                                break;
        !           340:                        case ':':
        !           341:                                json->h_parent = json->h_next - 1;
        !           342:                                break;
        !           343:                        case ',':
        !           344:                                if (jtoks && json->h_parent != -1 && 
        !           345:                                                jtoks[json->h_parent].tok_type != J_OBJECT && 
        !           346:                                                jtoks[json->h_parent].tok_type != J_ARRAY)
        !           347:                                        json->h_parent = jtoks[json->h_parent].tok_parent;
        !           348:                                break;
        !           349:                        case '-':
        !           350:                        case '0':
        !           351:                        case '1':
        !           352:                        case '2':
        !           353:                        case '3':
        !           354:                        case '4':
        !           355:                        case '5':
        !           356:                        case '6':
        !           357:                        case '7':
        !           358:                        case '8':
        !           359:                        case '9':
        !           360:                        case 't':
        !           361:                        case 'f':
        !           362:                        case 'n':
        !           363:                                if (json->h_strict) {
        !           364:                                        if (jtoks && json->h_parent != -1) {
        !           365:                                                /* they must not be keys of the object */
        !           366:                                                if (jtoks[json->h_parent].tok_type == J_OBJECT || 
        !           367:                                                                (jtoks[json->h_parent].tok_type == J_STRING && 
        !           368:                                                                 jtoks[json->h_parent].tok_size)) {
        !           369:                                                        elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
        !           370:                                                        return (u_int) -1;
        !           371:                                                }
        !           372:                                        }
        !           373: 
        !           374:                                        if (json_parse_value(json, jstr, jlen, jtoks, toksnum) == -1)
        !           375:                                                return (u_int) -1;
        !           376:                                        cx++;   /* start new value token */
        !           377:                                        if (jtoks && json->h_parent != -1)
        !           378:                                                jtoks[json->h_parent].tok_size++;
        !           379:                                        break;
        !           380:                                }
        !           381:                        default:
        !           382:                                if (json->h_strict) {
        !           383:                                        elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
        !           384:                                        return (u_int) -1;
        !           385:                                }
        !           386: 
        !           387:                                if (json_parse_value(json, jstr, jlen, jtoks, toksnum) == -1)
        !           388:                                        return (u_int) -1;
        !           389:                                cx++;   /* start new value token */
        !           390:                                if (jtoks && json->h_parent != -1)
        !           391:                                        jtoks[json->h_parent].tok_size++;
        !           392:                                break;
        !           393:                }
        !           394:        }
        !           395: 
        !           396:        if (jtoks) {
        !           397:                for (i = json->h_next - 1; i >= 0; i--) {
        !           398:                        /* unmatched opened object or array */
        !           399:                        if (jtoks[i].tok_start != -1 && jtoks[i].tok_end == -1) {
        !           400:                                elwix_SetErr(J_ERR_PART, "%s", jerrstr[J_ERR_PART]);
        !           401:                                return (u_int) -1;
        !           402:                        }
        !           403:                }
        !           404:        } else
        !           405:                cx++;   /* increment needed tokens number for termination empty token */
        !           406: 
        !           407:        return cx;
        !           408: }
        !           409: 
        !           410: /*
        !           411:  * json_token2val() - Return token to AIT variable
        !           412:  *
        !           413:  * @jstr = JSON string
        !           414:  * @tok = Token for convert
        !           415:  * @return =NULL error or !=NULL allocated variable, after use should be ait_freeVar()
        !           416:  */
        !           417: ait_val_t *
        !           418: json_token2val(const char *jstr, jtok_t * __restrict tok)
        !           419: {
        !           420:        ait_val_t *v = NULL;
        !           421: 
        !           422:        if (!jstr || !tok)
        !           423:                return NULL;
        !           424: 
        !           425:        v = ait_allocVar();
        !           426:        if (!v)
        !           427:                return NULL;
        !           428: 
        !           429:        AIT_SET_STRSIZ(v, json_toklen(tok));
        !           430:        strncpy(AIT_GET_STR(v), json_tokstr(jstr, tok), AIT_LEN(v) - 1);
        !           431: 
        !           432:        return v;
        !           433: }
        !           434: 
        !           435: /*
        !           436:  * json_token2str() - Return token to string
        !           437:  *
        !           438:  * @jstr = JSON string
        !           439:  * @tok = Token for convert
        !           440:  * @return =NULL error or !=NULL allocated str, after use should be e_free()
        !           441:  */
        !           442: char *
        !           443: json_token2str(const char *jstr, jtok_t * __restrict tok)
        !           444: {
        !           445:        char *str = NULL;
        !           446:        size_t len;
        !           447: 
        !           448:        if (!jstr || !tok)
        !           449:                return NULL;
        !           450: 
        !           451:        len = json_toklen(tok);
        !           452:        str = e_malloc(len + 1);
        !           453:        if (!str)
        !           454:                return NULL;
        !           455:        else {
        !           456:                strncpy(str, json_tokstr(jstr, tok), len);
        !           457:                str[len] = 0;
        !           458:        }
        !           459: 
        !           460:        return str;
        !           461: }
        !           462: 
        !           463: /*
        !           464:  * json_token2num() - Return token to numeric
        !           465:  *
        !           466:  * @jstr = JSON string
        !           467:  * @tok = Token for convert
        !           468:  * @return number
        !           469:  */
        !           470: long
        !           471: json_token2num(const char *jstr, jtok_t * __restrict tok)
        !           472: {
        !           473:        long ret = 0;
        !           474:        char *str;
        !           475: 
        !           476:        str = json_token2str(jstr, tok);
        !           477:        if (!str)
        !           478:                return 0;
        !           479: 
        !           480:        ret = strtol(str, NULL, 0);
        !           481:        e_free(str);
        !           482:        return ret;
        !           483: }
        !           484: 
        !           485: /*
        !           486:  * json_findbykey() - Find data by key
        !           487:  *
        !           488:  * @jstr = JSON string
        !           489:  * @key = Search key
        !           490:  * @toks = Parsed tokens
        !           491:  * @toksnum = Number of parsed tokens
        !           492:  * return: =NULL error or !=NULL data token found 
        !           493:  */
        !           494: jtok_t *
        !           495: json_findbykey(const char *jstr, const char *key, jtok_t * __restrict toks, int toksnum)
        !           496: {
        !           497:        jtok_t *tok = NULL;
        !           498:        register int i;
        !           499:        int klen;
        !           500: 
        !           501:        if (!jstr || !key || !toks)
        !           502:                return NULL;
        !           503:        else
        !           504:                klen = strlen(key);
        !           505: 
        !           506:        for (i = 1; i < toksnum; i++) {
        !           507:                if (toks[i].tok_type == J_STRING && 
        !           508:                                klen == toks[i].tok_end - toks[i].tok_start && 
        !           509:                                !strncmp(jstr + toks[i].tok_start, key, klen)) {
        !           510:                        tok = toks + i + 1;
        !           511:                        break;
        !           512:                }
        !           513:        }
        !           514: 
        !           515:        return tok;
        !           516: }
        !           517: 
        !           518: /*
        !           519:  * json_token2array() - Convert token to string array
        !           520:  *
        !           521:  * @jstr = JSON string
        !           522:  * @tok = Token for convert
        !           523:  * return: =NULL error or !=NULL allocated array with string variables, 
        !           524:  *             after use should be ait_freeVars()
        !           525:  */
        !           526: array_t *
        !           527: json_token2array(const char *jstr, jtok_t * __restrict tok)
        !           528: {
        !           529:        array_t *arr = NULL;
        !           530:        register int i;
        !           531:        int siz;
        !           532:        ait_val_t *v;
        !           533:        jtok_t *t;
        !           534: 
        !           535:        if (!jstr || !tok)
        !           536:                return NULL;
        !           537: 
        !           538:        siz = tok->tok_size;
        !           539:        if (!siz && json_toktype(tok) != J_ARRAY && json_toktype(tok) != J_OBJECT)
        !           540:                siz++;
        !           541: 
        !           542:        arr = ait_allocVars(siz);
        !           543:        if (!arr)
        !           544:                return NULL;
        !           545: 
        !           546:        if (tok->tok_type == J_STRING || tok->tok_type == J_VALUE) {
        !           547:                v = ait_getVars(&arr, 0);
        !           548:                AIT_SET_STRSIZ(v, json_toklen(tok) + 1);
        !           549:                json_tokstrcpy(AIT_GET_STR(v), jstr, tok);
        !           550:        } else if (tok->tok_type == J_ARRAY) {
        !           551:                for (i = 0; i < tok->tok_size; i++) {
        !           552:                        t = &tok[i + 1];
        !           553:                        v = ait_getVars(&arr, i);
        !           554:                        AIT_SET_STRSIZ(v, json_toklen(t) + 1);
        !           555:                        json_tokstrcpy(AIT_GET_STR(v), jstr, t);
        !           556:                }
        !           557:        } else if (tok->tok_type == J_OBJECT) {
        !           558:                for (i = 0; tok->tok_idx <= tok[i + 1].tok_parent; i++) {
        !           559:                        t = &tok[i + 1];
        !           560:                        v = ait_getVars(&arr, i);
        !           561:                        AIT_SET_STRSIZ(v, json_toklen(t) + 1);
        !           562:                        json_tokstrcpy(AIT_GET_STR(v), jstr, t);
        !           563:                }
        !           564:        } else {
        !           565:                elwix_SetErr(J_ERR_PARAM, "%s", jerrstr[J_ERR_PARAM]);
        !           566:                ait_freeVars(&arr);
        !           567:                return NULL;
        !           568:        }
        !           569: 
        !           570:        return arr;
        !           571: }
        !           572: 
        !           573: 
        !           574: 
        !           575: /*
        !           576:  * json_add_begin_object() - Adds begin of object {
        !           577:  *
        !           578:  * @jstr = JSON string
        !           579:  * @jlen = JSON string length
        !           580:  * @wspace = whitespace include
        !           581:  * return: -1 error or !=-1 actual JSON string length
        !           582:  */
        !           583: int
        !           584: json_add_begin_object(char * __restrict jstr, int jlen, int wspace)
        !           585: {
        !           586:        int len;
        !           587:        size_t eos;
        !           588: 
        !           589:        if (!jstr)
        !           590:                return -1;
        !           591:        else
        !           592:                eos = strlen(jstr);
        !           593: 
        !           594: 
        !           595:        if (wspace)
        !           596:                len = strlcat(jstr, "{ ", jlen);
        !           597:        else
        !           598:                len = strlcat(jstr, "{", jlen);
        !           599: 
        !           600:        if (len >= jlen) {
        !           601:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           602:                jstr[eos] = 0;
        !           603:                return -1;
        !           604:        }
        !           605: 
        !           606:        return len;
        !           607: }
        !           608: 
        !           609: /*
        !           610:  * json_add_end_object() - Adds end of object }
        !           611:  *
        !           612:  * @jstr = JSON string
        !           613:  * @jlen = JSON string length
        !           614:  * @wspace = whitespace include
        !           615:  * return: -1 error or !=-1 actual JSON string length
        !           616:  */
        !           617: int
        !           618: json_add_end_object(char * __restrict jstr, int jlen, int wspace)
        !           619: {
        !           620:        int len;
        !           621:        size_t eos;
        !           622: 
        !           623:        if (!jstr)
        !           624:                return -1;
        !           625:        else
        !           626:                eos = strlen(jstr);
        !           627: 
        !           628:        if (wspace)
        !           629:                len = strlcat(jstr, " }", jlen);
        !           630:        else
        !           631:                len = strlcat(jstr, "}", jlen);
        !           632: 
        !           633:        if (len >= jlen) {
        !           634:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           635:                jstr[eos] = 0;
        !           636:                return -1;
        !           637:        }
        !           638: 
        !           639:        return len;
        !           640: }
        !           641: 
        !           642: /*
        !           643:  * json_add_begin_array() - Adds begin of array [
        !           644:  *
        !           645:  * @jstr = JSON string
        !           646:  * @jlen = JSON string length
        !           647:  * @wspace = whitespace include
        !           648:  * return: -1 error or !=-1 actual JSON string length
        !           649:  */
        !           650: int
        !           651: json_add_begin_array(char * __restrict jstr, int jlen, int wspace)
        !           652: {
        !           653:        int len;
        !           654:        size_t eos;
        !           655: 
        !           656:        if (!jstr)
        !           657:                return -1;
        !           658:        else
        !           659:                eos = strlen(jstr);
        !           660: 
        !           661:        if (wspace)
        !           662:                len = strlcat(jstr, "[ ", jlen);
        !           663:        else
        !           664:                len = strlcat(jstr, "[", jlen);
        !           665: 
        !           666:        if (len >= jlen) {
        !           667:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           668:                jstr[eos] = 0;
        !           669:                return -1;
        !           670:        }
        !           671: 
        !           672:        return len;
        !           673: }
        !           674: 
        !           675: /*
        !           676:  * json_add_end_array() - Adds end of array ]
        !           677:  *
        !           678:  * @jstr = JSON string
        !           679:  * @jlen = JSON string length
        !           680:  * @wspace = whitespace include
        !           681:  * return: -1 error or !=-1 actual JSON string length
        !           682:  */
        !           683: int
        !           684: json_add_end_array(char * __restrict jstr, int jlen, int wspace)
        !           685: {
        !           686:        int len;
        !           687:        size_t eos;
        !           688: 
        !           689:        if (!jstr)
        !           690:                return -1;
        !           691:        else
        !           692:                eos = strlen(jstr);
        !           693: 
        !           694:        if (wspace)
        !           695:                len = strlcat(jstr, " ]", jlen);
        !           696:        else
        !           697:                len = strlcat(jstr, "]", jlen);
        !           698: 
        !           699:        if (len >= jlen) {
        !           700:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           701:                jstr[eos] = 0;
        !           702:                return -1;
        !           703:        }
        !           704: 
        !           705:        return len;
        !           706: }
        !           707: 
        !           708: /*
        !           709:  * json_add_char() - Adds character
        !           710:  *
        !           711:  * @jstr = JSON string
        !           712:  * @jlen = JSON string length
        !           713:  * @ch = Character
        !           714:  * return: -1 error or !=-1 actual JSON string length
        !           715:  */
        !           716: int
        !           717: json_add_char(char * __restrict jstr, int jlen, u_char ch)
        !           718: {
        !           719:        int len;
        !           720: 
        !           721:        if (!jstr)
        !           722:                return -1;
        !           723: 
        !           724:        len = strlen(jstr) + 1;
        !           725:        if (len >= jlen) {
        !           726:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           727:                return -1;
        !           728:        } else {
        !           729:                jstr[len++] = (char) ch;
        !           730:                jstr[len] = 0;
        !           731:        }
        !           732: 
        !           733:        return len;
        !           734: }
        !           735: 
        !           736: /*
        !           737:  * json_add_colon() - Adds key/value pair delimiter colon :
        !           738:  *
        !           739:  * @jstr = JSON string
        !           740:  * @jlen = JSON string length
        !           741:  * @wspace = whitespace include
        !           742:  * return: -1 error or !=-1 actual JSON string length
        !           743:  */
        !           744: int
        !           745: json_add_colon(char * __restrict jstr, int jlen, int wspace)
        !           746: {
        !           747:        int len;
        !           748:        size_t eos;
        !           749: 
        !           750:        if (!jstr)
        !           751:                return -1;
        !           752:        else
        !           753:                eos = strlen(jstr);
        !           754: 
        !           755:        if (wspace)
        !           756:                len = strlcat(jstr, ": ", jlen);
        !           757:        else
        !           758:                len = strlcat(jstr, ":", jlen);
        !           759: 
        !           760:        if (len >= jlen) {
        !           761:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           762:                jstr[eos] = 0;
        !           763:                return -1;
        !           764:        }
        !           765: 
        !           766:        return len;
        !           767: }
        !           768: 
        !           769: /*
        !           770:  * json_add_comma() - Adds value delimiter comma ,
        !           771:  *
        !           772:  * @jstr = JSON string
        !           773:  * @jlen = JSON string length
        !           774:  * @wspace = whitespace include
        !           775:  * return: -1 error or !=-1 actual JSON string length
        !           776:  */
        !           777: int
        !           778: json_add_comma(char * __restrict jstr, int jlen, int wspace)
        !           779: {
        !           780:        int len;
        !           781:        size_t eos;
        !           782: 
        !           783:        if (!jstr)
        !           784:                return -1;
        !           785:        else
        !           786:                eos = strlen(jstr);
        !           787: 
        !           788:        if (wspace)
        !           789:                len = strlcat(jstr, ", ", jlen);
        !           790:        else
        !           791:                len = strlcat(jstr, ",", jlen);
        !           792: 
        !           793:        if (len >= jlen) {
        !           794:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           795:                jstr[eos] = 0;
        !           796:                return -1;
        !           797:        }
        !           798: 
        !           799:        return len;
        !           800: }
        !           801: 
        !           802: /*
        !           803:  * json_add_string() - Adds string
        !           804:  *
        !           805:  * @jstr = JSON string
        !           806:  * @jlen = JSON string length
        !           807:  * @unquot = Unquoted string
        !           808:  * @str = String, it can't be NULL
        !           809:  * return: -1 error or !=-1 actual JSON string length
        !           810:  */
        !           811: int
        !           812: json_add_string(char * __restrict jstr, int jlen, int unquot, const char *str)
        !           813: {
        !           814:        int len;
        !           815:        size_t eos;
        !           816: 
        !           817:        if (!jstr || !str)
        !           818:                return -1;
        !           819:        else
        !           820:                eos = strlen(jstr);
        !           821: 
        !           822:        if (!unquot) {
        !           823:                len = strlcat(jstr, "\"", jlen);
        !           824:                if (len >= jlen) {
        !           825:                        elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           826:                        jstr[eos] = 0;
        !           827:                        return -1;
        !           828:                }
        !           829:        }
        !           830:        len = strlcat(jstr, str, jlen);
        !           831:        if (len >= jlen) {
        !           832:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           833:                jstr[eos] = 0;
        !           834:                return -1;
        !           835:        }
        !           836:        if (!unquot) {
        !           837:                len = strlcat(jstr, "\"", jlen);
        !           838:                if (len >= jlen) {
        !           839:                        elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           840:                        jstr[eos] = 0;
        !           841:                        return -1;
        !           842:                }
        !           843:        }
        !           844: 
        !           845:        return len;
        !           846: }
        !           847: 
        !           848: /*
        !           849:  * json_add_value() - Adds value
        !           850:  *
        !           851:  * @jstr = JSON string
        !           852:  * @jlen = JSON string length
        !           853:  * @unquot = Unquoted number
        !           854:  * @num = Number
        !           855:  * return: -1 error or !=-1 actual JSON string length
        !           856:  */
        !           857: int
        !           858: json_add_value(char * __restrict jstr, int jlen, int unquot, long num)
        !           859: {
        !           860:        int len;
        !           861:        char wrk[STRSIZ] = { [0 ... STRSIZ - 1] = 0 };
        !           862:        size_t eos;
        !           863: 
        !           864:        if (!jstr)
        !           865:                return -1;
        !           866:        else
        !           867:                eos = strlen(jstr);
        !           868: 
        !           869:        if (!unquot) {
        !           870:                len = strlcat(jstr, "\"", jlen);
        !           871:                if (len >= jlen) {
        !           872:                        elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           873:                        jstr[eos] = 0;
        !           874:                        return -1;
        !           875:                }
        !           876:        }
        !           877:        snprintf(wrk, sizeof wrk, "%ld", num);
        !           878:        len = strlcat(jstr, wrk, jlen);
        !           879:        if (len >= jlen) {
        !           880:                elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           881:                jstr[eos] = 0;
        !           882:                return -1;
        !           883:        }
        !           884:        if (!unquot) {
        !           885:                len = strlcat(jstr, "\"", jlen);
        !           886:                if (len >= jlen) {
        !           887:                        elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
        !           888:                        jstr[eos] = 0;
        !           889:                        return -1;
        !           890:                }
        !           891:        }
        !           892: 
        !           893:        return len;
        !           894: }
        !           895: 
        !           896: /*
        !           897:  * json_add_pair() - Adds key/value pair
        !           898:  *
        !           899:  * @jstr = JSON string
        !           900:  * @jlen = JSON string length
        !           901:  * @wspace = whitespace include
        !           902:  * @key = Key string
        !           903:  * @val = Value string
        !           904:  * return: -1 error or !=-1 actual JSON string length
        !           905:  */
        !           906: int
        !           907: json_add_pair(char * __restrict jstr, int jlen, int wspace, const char *key, const char *val)
        !           908: {
        !           909:        int len = -1;
        !           910:        size_t eos;
        !           911: 
        !           912:        if (!jstr || !key || !val)
        !           913:                return -1;
        !           914:        else
        !           915:                eos = strlen(jstr);
        !           916: 
        !           917:        if (json_add_string(jstr, jlen, 0, key) == -1) {
        !           918:                jstr[eos] = 0;
        !           919:                return -1;
        !           920:        }
        !           921:        if (json_add_colon(jstr, jlen, wspace) == -1) {
        !           922:                jstr[eos] = 0;
        !           923:                return -1;
        !           924:        }
        !           925:        if ((len = json_add_string(jstr, jlen, 0, val)) == -1) {
        !           926:                jstr[eos] = 0;
        !           927:                return -1;
        !           928:        }
        !           929: 
        !           930:        return len;
        !           931: }
        !           932: 
        !           933: /*
        !           934:  * json_add_array() - Adds array
        !           935:  *
        !           936:  * @jstr = JSON string
        !           937:  * @jlen = JSON string length
        !           938:  * @wspace = whitespace include
        !           939:  * @arr = Array with variables
        !           940:  * return: -1 error or !=-1 actual JSON string length
        !           941:  */
        !           942: int
        !           943: json_add_array(char * __restrict jstr, int jlen, int wspace, array_t * __restrict arr)
        !           944: {
        !           945:        int len = -1;
        !           946:        register int i;
        !           947:        ait_val_t *v;
        !           948:        size_t eos;
        !           949: 
        !           950:        if (!jstr || !arr)
        !           951:                return -1;
        !           952:        else
        !           953:                eos = strlen(jstr);
        !           954: 
        !           955:        if (json_add_begin_array(jstr, jlen, wspace) == -1) {
        !           956:                jstr[eos] = 0;
        !           957:                return -1;
        !           958:        }
        !           959:        for (i = 0; i < array_Size(arr); i++) {
        !           960:                v = array(arr, i, ait_val_t*);
        !           961:                if (v) {
        !           962:                        if (AIT_TYPE(v) == string) {
        !           963:                                if (json_add_string(jstr, jlen, 0, AIT_GET_STR(v)) == -1) {
        !           964:                                        jstr[eos] = 0;
        !           965:                                        return -1;
        !           966:                                }
        !           967:                        } else {
        !           968:                                if (json_add_value(jstr, jlen, 0, AIT_GET_LIKE(v, long)) == -1) {
        !           969:                                        jstr[eos] = 0;
        !           970:                                        return -1;
        !           971:                                }
        !           972:                        }
        !           973:                        if (i < array_Size(arr) - 1 && json_add_comma(jstr, jlen, wspace) == -1) {
        !           974:                                jstr[eos] = 0;
        !           975:                                return -1;
        !           976:                        }
        !           977:                }
        !           978:        }
        !           979:        if ((len = json_add_end_array(jstr, jlen, wspace)) == -1) {
        !           980:                jstr[eos] = 0;
        !           981:                return -1;
        !           982:        }
        !           983: 
        !           984:        return len;
        !           985: }

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