4 * Simple JSON stream parser
6 * Copyright (c) 2018, SUSE LLC
8 * This program is licensed under the BSD license, read LICENSE.BSD
9 * for further information
16 #include "solv_jsonparser.h"
18 struct solv_jsonparser *
19 jsonparser_init(struct solv_jsonparser *jp, FILE *fp)
21 memset(jp, 0, sizeof(*jp));
24 jp->line = jp->nextline = 1;
26 queue_init(&jp->stateq);
30 struct solv_jsonparser *
31 jsonparser_free(struct solv_jsonparser *jp)
33 queue_free(&jp->stateq);
38 savec(struct solv_jsonparser *jp, char c)
40 if (jp->nspace == jp->aspace)
43 jp->space = solv_realloc(jp->space, jp->aspace);
45 jp->space[jp->nspace++] = c;
49 saveutf8(struct solv_jsonparser *jp, int c)
57 i = c < 0x800 ? 1 : c < 0x10000 ? 2 : 3;
58 savec(jp, (0x1f80 >> i) | (c >> (6 * i)));
60 savec(jp, 0x80 | ((c >> (6 * i)) & 0x3f));
64 nextc(struct solv_jsonparser *jp)
73 skipspace(struct solv_jsonparser *jp)
76 while (c == ' ' || c == '\t' || c == '\r' || c == '\n')
78 jp->line = jp->nextline;
79 return (jp->nextc = c);
83 parseliteral(struct solv_jsonparser *jp)
85 size_t nspace = jp->nspace;
91 if (c < 'a' || c > 'z')
97 if (!strcmp(jp->space + nspace, "true"))
99 if (!strcmp(jp->space + nspace, "false"))
101 if (!strcmp(jp->space + nspace, "null"))
107 parsenumber(struct solv_jsonparser *jp)
110 savec(jp, jp->nextc);
114 if ((c < '0' || c > '9') && c != '+' && c != '-' && c != '.' && c != 'e' && c != 'E')
124 parseutf8(struct solv_jsonparser *jp, int surrogate)
127 /* parse 4-digit hex */
128 for (i = 0; i < 4; i++)
131 if (c >= '0' && c <= '9')
133 else if (c >= 'a' && c <= 'f')
135 else if (c >= 'A' && c <= 'F')
141 if (!surrogate && r >= 0xd800 && r < 0xdc00)
143 /* utf16 surrogate pair encodes 0x10000 - 0x10ffff */
145 if (nextc(jp) != '\\' || nextc(jp) != 'u' || (r2 = parseutf8(jp, 1)) < 0xdc00 || r2 >= 0xe000)
147 r = 0x10000 + ((r & 0x3ff) << 10 | (r2 & 0x3ff));
153 parsestring(struct solv_jsonparser *jp)
158 if ((c = nextc(jp)) < 32)
164 switch (c = nextc(jp))
187 if ((c = parseutf8(jp, 0)) < 0)
203 parsevalue(struct solv_jsonparser *jp)
205 int c = skipspace(jp);
207 return parsestring(jp);
208 if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')
209 return parsenumber(jp);
210 if ((c >= 'a' && c <= 'z'))
211 return parseliteral(jp);
220 return JP_OBJECT_END;
225 jsonparser_parse(struct solv_jsonparser *jp)
230 jp->depth = jp->stateq.count;
231 jp->key = jp->value = 0;
232 jp->keylen = jp->valuelen = 0;
233 nspace = jp->nspace = 0;
235 if (jp->state == JP_END)
237 if (jp->state == JP_START)
239 type = parsevalue(jp);
242 if (type == JP_OBJECT_END || type == JP_ARRAY_END)
244 if (jp->state != type - 1)
246 jp->state = queue_pop(&jp->stateq);
248 else if (jp->state == JP_OBJECT)
251 if (type != JP_STRING)
253 if (skipspace(jp) != ':')
256 type = parsevalue(jp);
257 if (type == JP_OBJECT_END || type == JP_ARRAY_END)
260 jp->keylen = nspace - 1;
262 if (type == JP_STRING || type == JP_NUMBER || type == JP_BOOL || type == JP_NULL)
264 jp->value = jp->space + nspace;
265 jp->valuelen = jp->nspace - nspace - 1;
267 if (type == JP_ARRAY || type == JP_OBJECT)
269 queue_push(&jp->stateq, jp->state);
272 else if (jp->state == JP_OBJECT || jp->state == JP_ARRAY)
274 int c = skipspace(jp);
277 else if (c != (jp->state == JP_OBJECT ? '}' : ']'))
284 jsonparser_skip(struct solv_jsonparser *jp, int type)
286 if (type == JP_ARRAY || type == JP_OBJECT)
288 int depth = jp->depth + 1, endtype = type + 1;
289 while (type > 0 && (type != endtype || jp->depth != depth))
290 type = jsonparser_parse(jp);