Annotation of libelwix/src/json.c, revision 1.1.2.2
1.1.2.1 misho 1: /*************************************************************************
2: * (C) 2017 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.1.2.2 ! misho 6: * $Id: json.c,v 1.1.2.1 2017/11/24 09:53:53 misho Exp $
1.1.2.1 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
15: Copyright 2004 - 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:
1.1.2.2 ! misho 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: /*
! 109: * json_parse() - Parse JSON string
! 110: *
! 111: * @json = JSON handler
! 112: * @jstr = JSON string
! 113: * @jlen = JSON string length
! 114: * @jtoks = Token array
! 115: * @toksnum = Token array size, return number of allocated tokens in array
! 116: * return: -1 error or number of found tokens
! 117: */
! 118: u_int
! 119: json_parse(json_t * __restrict json, const char *jstr, size_t jlen, jtok_t * __restrict jtoks, u_int toksnum)
! 120: {
! 121: register int i;
! 122: register u_int cx;
! 123: jtype_t type;
! 124: jtok_t *tok;
! 125: char ch;
! 126:
! 127: if (!json || !jstr || (!jtoks && toksnum)) {
! 128: elwix_SetErr(J_ERR_PARAM, "%s", jerrstr[J_ERR_PARAM]);
! 129: return (u_int) -1;
! 130: }
! 131:
! 132: for (cx = json->h_next; json->h_pos < jlen && jstr[json->h_pos]; json->h_pos++) {
! 133: switch ((ch = jstr[json->h_pos])) {
! 134: case '{':
! 135: case '[':
! 136: cx++; /* start new token */
! 137: if (!jtoks)
! 138: break;
! 139:
! 140: tok = json_gettoken(json, jtoks, toksnum);
! 141: if (!tok) {
! 142: elwix_SetErr(J_ERR_NOMEM, "%s", jerrstr[J_ERR_NOMEM]);
! 143: return (u_int) -1;
! 144: }
! 145: if (json->h_parent != -1) {
! 146: jtoks[json->h_parent].tok_size++;
! 147: tok->tok_parent = json->h_parent;
! 148: }
! 149: tok->tok_type = (ch == '{' ? J_OBJECT : J_ARRAY);
! 150: tok->tok_start = json->h_pos;
! 151: json->h_parent = json->h_next - 1;
! 152: break;
! 153: case '}':
! 154: case ']':
! 155: if (!jtoks)
! 156: break;
! 157:
! 158: if (json->h_next < 1) {
! 159: elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
! 160: return (u_int) -1;
! 161: }
! 162:
! 163: type = (ch == '}' ? J_OBJECT : J_ARRAY);
! 164: tok = &jtoks[json->h_next - 1];
! 165: while (42) {
! 166: if (tok->tok_start != -1 && tok->tok_end == -1) {
! 167: if (tok->tok_type != type) {
! 168: elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
! 169: return (u_int) -1;
! 170: }
! 171: tok->tok_end = json->h_pos + 1;
! 172: json->h_parent = tok->tok_parent;
! 173: break;
! 174: }
! 175: if (tok->tok_parent == -1) {
! 176: if (tok->tok_type != type || json->h_parent == -1) {
! 177: elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
! 178: return (u_int) -1;
! 179: }
! 180: break;
! 181: }
! 182: tok = &jtoks[tok->tok_parent];
! 183: }
! 184: break;
! 185: case '\"':
! 186: if (json_parse_string(json, jstr, jlen, jtoks, toksnum) == -1) {
! 187: elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
! 188: return (u_int) -1;
! 189: }
! 190: cx++;
! 191: if (jtoks && json->h_parent != -1)
! 192: jtoks[json->h_parent].tok_size++;
! 193: break;
! 194: case '\t':
! 195: case '\r':
! 196: case '\n':
! 197: case ' ':
! 198: /* whitespace, skip */
! 199: break;
! 200: case ':':
! 201: json->h_parent = json->h_next - 1;
! 202: break;
! 203: case ',':
! 204: if (jtoks && json->h_parent != -1 &&
! 205: jtoks[json->h_parent].tok_type != J_OBJECT &&
! 206: jtoks[json->h_parent].tok_type != J_ARRAY)
! 207: json->h_parent = jtoks[json->h_parent].tok_parent;
! 208: break;
! 209: case '-':
! 210: case '0':
! 211: case '1':
! 212: case '2':
! 213: case '3':
! 214: case '4':
! 215: case '5':
! 216: case '6':
! 217: case '7':
! 218: case '8':
! 219: case '9':
! 220: case 't':
! 221: case 'f':
! 222: case 'n':
! 223: if (!json->h_strict)
! 224: break;
! 225:
! 226: if (jtoks && json->h_parent != -1) {
! 227: /* they must not be keys of the object */
! 228: if (jtoks[json->h_parent].tok_type == J_OBJECT ||
! 229: (jtoks[json->h_parent].tok_type == J_STRING &&
! 230: jtoks[json->h_parent].tok_size)) {
! 231: elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
! 232: return (u_int) -1;
! 233: }
! 234: }
! 235:
! 236: if (json_parse_value(json, jstr, jlen, jtoks, toksnum) == -1)
! 237: return (u_int) -1;
! 238: cx++;
! 239: if (jtoks && json->h_parent != -1)
! 240: jtoks[json->h_parent].tok_size++;
! 241: break;
! 242: default:
! 243: if (json->h_strict) {
! 244: elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]);
! 245: return (u_int) -1;
! 246: }
! 247:
! 248: if (json_parse_value(json, jstr, jlen, jtoks, toksnum) == -1)
! 249: return (u_int) -1;
! 250: cx++;
! 251: if (jtoks && json->h_parent != -1)
! 252: jtoks[json->h_parent].tok_size++;
! 253: break;
! 254: }
! 255: }
! 256:
! 257: if (jtoks) {
! 258: for (i = json->h_next - 1; i >= 0; i--) {
! 259: /* unmatched opened object or array */
! 260: if (jtoks[i].tok_start != -1 && jtoks[i].tok_end == -1) {
! 261: elwix_SetErr(J_ERR_PART, "%s", jerrstr[J_ERR_PART]);
! 262: return (u_int) -1;
! 263: }
! 264: }
! 265: }
! 266:
! 267: return cx;
! 268: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>