gwenhywfar 5.14.1
json_read.c
Go to the documentation of this file.
1/***************************************************************************
2 copyright : (C) 2023 by Martin Preuss
3 email : martin@libchipcard.de
4
5 ***************************************************************************
6 * *
7 * This library is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU Lesser General Public *
9 * License as published by the Free Software Foundation; either *
10 * version 2.1 of the License, or (at your option) any later version. *
11 * *
12 * This library is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15 * Lesser General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with this library; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 * *
22 ***************************************************************************/
23
24#ifdef HAVE_CONFIG_H
25# include <config.h>
26#endif
27
28#define DISABLE_DEBUGLOG
29
30
31#include "./json_p.h"
32#include "./json_read.h"
33
34#include <gwenhywfar/misc.h>
35#include <gwenhywfar/debug.h>
36#include <gwenhywfar/text.h>
37
38#include <ctype.h>
39
40
41
42static GWEN_JSON_ELEM *_readObject(const char *s, const char **next);
43static GWEN_JSON_ELEM *_readArray(const char *s, const char **next);
44static int _readKey(const char *s, GWEN_BUFFER *buf, const char **next);
45static GWEN_JSON_ELEM *_readValue(const char *s, const char **next);
46static int _readSimpleValueAndReturnType(const char *s, GWEN_BUFFER *buf, const char **next);
47static int _readTokenUntilChar(const char *s, GWEN_BUFFER *buf, int c, const char **next);
48static int _readQuotedToken(const char *s, GWEN_BUFFER *buf, const char **next);
49
50
51
52
54{
55 while(*s && isspace(*s))
56 s++;
57 if (*s=='{') {
58 GWEN_JSON_ELEM *jeObject;
59
60 s++;
61 jeObject=_readObject(s, &s);
62 if (jeObject==NULL) {
63 DBG_INFO(GWEN_LOGDOMAIN, "here");
64 return NULL;
65 }
66
67 return jeObject;
68 }
69
70 return NULL;
71}
72
73
74
75
76GWEN_JSON_ELEM *_readObject(const char *s, const char **next)
77{
78 GWEN_BUFFER *buf;
79 GWEN_JSON_ELEM *jeObject;
80
82 buf=GWEN_Buffer_new(0, 64, 0, 1);
83 while(*s) {
84 int rv;
85 GWEN_JSON_ELEM *jeKey;
86 GWEN_JSON_ELEM *jeValue;
87
88 while(*s && isspace(*s))
89 s++;
90 if (!*s || *s=='}')
91 break;
92
94 rv=_readKey(s, buf, &s);
95 if (rv<0) {
96 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
98 GWEN_JsonElement_free(jeObject);
99 return NULL;
100 }
102 GWEN_JsonElement_Tree2_AddChild(jeObject, jeKey);
103
104 while(*s && isspace(*s))
105 s++;
106
107 jeValue=_readValue(s, &s);
108 if (jeValue==NULL) {
109 DBG_INFO(GWEN_LOGDOMAIN, "here");
110 GWEN_Buffer_free(buf);
111 GWEN_JsonElement_free(jeObject);
112 return NULL;
113 }
114 GWEN_JsonElement_Tree2_AddChild(jeKey, jeValue);
115
116 while(*s && isspace(*s))
117 s++;
118
119 if (*s!=',')
120 break;
121 s++;
122 } /* while */
123 GWEN_Buffer_free(buf);
124
125 if (*s!='}') {
126 DBG_INFO(GWEN_LOGDOMAIN, "missing closing curly bracket");
127 GWEN_JsonElement_free(jeObject);
128 return NULL;
129 }
130 s++;
131 if (next)
132 *next=s;
133 return jeObject;
134}
135
136
137
138GWEN_JSON_ELEM *_readArray(const char *s, const char **next)
139{
140 GWEN_JSON_ELEM *jeArray;
141
143 while(*s) {
144 GWEN_JSON_ELEM *jeValue;
145
146 while(*s && isspace(*s))
147 s++;
148 if (!*s || *s==']')
149 break;
150
151 jeValue=_readValue(s, &s);
152 if (jeValue==NULL) {
153 DBG_INFO(GWEN_LOGDOMAIN, "here");
154 GWEN_JsonElement_free(jeArray);
155 return NULL;
156 }
157 GWEN_JsonElement_Tree2_AddChild(jeArray, jeValue);
158
159 while(*s && isspace(*s))
160 s++;
161
162 if (*s!=',')
163 break;
164 s++;
165 } /* while */
166
167 if (*s!=']') {
168 DBG_INFO(GWEN_LOGDOMAIN, "missing closing square bracket");
169 GWEN_JsonElement_free(jeArray);
170 return NULL;
171 }
172 s++;
173 if (next)
174 *next=s;
175 return jeArray;
176}
177
178
179
180int _readKey(const char *s, GWEN_BUFFER *buf, const char **next)
181{
182 int rv;
183
184 /* skip blanks */
185 while(*s && isspace(*s))
186 s++;
187 if (!(*s))
188 return GWEN_ERROR_NO_DATA;
189
190 if (*s!='"') {
191 DBG_INFO(GWEN_LOGDOMAIN, "missing opening quote");
192 return GWEN_ERROR_BAD_DATA;
193 }
194
195 /* read everything until closing quote */
196 s++;
197 rv=_readQuotedToken(s, buf, &s);
198 if (rv<1) {
199 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
200 return GWEN_ERROR_BAD_DATA;
201 }
202 if (*s!='"') {
203 DBG_INFO(GWEN_LOGDOMAIN, "missing closing quote");
204 return GWEN_ERROR_BAD_DATA;
205 }
206 s++;
207 while(*s && isspace(*s))
208 s++;
209 if (*s!=':') {
210 DBG_INFO(GWEN_LOGDOMAIN, "missing colon char");
211 return GWEN_ERROR_BAD_DATA;
212 }
213 s++;
214
215 if (next)
216 *next=s;
217 return 0;
218}
219
220
221
222GWEN_JSON_ELEM *_readValue(const char *s, const char **next)
223{
224 GWEN_JSON_ELEM *jeValue=NULL;
225
226 /* skip blanks */
227 while(*s && isspace(*s))
228 s++;
229 if (*s=='{') {
230 s++;
231 jeValue=_readObject(s, &s);
232 if (jeValue==NULL) {
233 DBG_INFO(GWEN_LOGDOMAIN, "error reading object");
234 return NULL;
235 }
236 }
237 else if (*s=='[') {
238 s++;
239 jeValue=_readArray(s, &s);
240 if (jeValue==NULL) {
241 DBG_INFO(GWEN_LOGDOMAIN, "error reading array");
242 return NULL;
243 }
244 }
245 else {
246 GWEN_BUFFER *buf;
247 int rv;
248
249 buf=GWEN_Buffer_new(0, 64, 0, 1);
250 rv=_readSimpleValueAndReturnType(s, buf, &s);
251 if (rv<0) {
252 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
253 GWEN_Buffer_free(buf);
254 return NULL;
255 }
257 GWEN_Buffer_free(buf);
258 }
259
260 if (next)
261 *next=s;
262
263 return jeValue;
264}
265
266
267
268
269int _readSimpleValueAndReturnType(const char *s, GWEN_BUFFER *buf, const char **next)
270{
271 int rv;
272 int elementType=GWEN_JSON_ELEMTYPE_UNKNOWN;
273
274 /* skip blanks */
275 while(*s && isspace(*s))
276 s++;
277 if (!(*s))
278 return GWEN_ERROR_NO_DATA;
279
280 if (*s=='"') {
281 /* string element, read everything until closing quote */
282 s++;
283 rv=_readQuotedToken(s, buf, &s);
284 if (rv<1) {
285 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
286 return GWEN_ERROR_BAD_DATA;
287 }
288 if (*s!='"') {
289 DBG_INFO(GWEN_LOGDOMAIN, "missing closing quote");
290 return GWEN_ERROR_BAD_DATA;
291 }
292 s++;
293 elementType=GWEN_JSON_ELEMTYPE_STRING;
294 }
295 else {
296 uint32_t pos;
297 const char *p;
298
299 pos=GWEN_Buffer_GetPos(buf);
300 rv=_readTokenUntilChar(s, buf, 0, &s);
301 if (rv<1) {
302 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
303 return GWEN_ERROR_BAD_DATA;
304 }
305 /* determine type */
306 p=GWEN_Buffer_GetStart(buf)+pos;
307 if (*p=='-' || *p=='.' || isdigit(*p)) {
308 elementType=GWEN_JSON_ELEMTYPE_NUM;
309 }
310 else if (strcasecmp(p, "TRUE")==0 || strcasecmp(p, "FALSE")==0) {
311 elementType=GWEN_JSON_ELEMTYPE_BOOL;
312 }
313 else if (strcasecmp(p, "NULL")==0) {
314 elementType=GWEN_JSON_ELEMTYPE_NULL;
315 }
316 }
317 if (next)
318 *next=s;
319 return elementType;
320}
321
322
323
324int _readTokenUntilChar(const char *s, GWEN_BUFFER *buf, int c, const char **next)
325{
326 int lastWasEscape=0;
327 int bytesAdded=0;
328
329 while(*s) {
330 if (lastWasEscape) {
331 GWEN_Buffer_AppendByte(buf, *s);
332 lastWasEscape=0;
333 bytesAdded++;
334 }
335 else {
336 if (*s=='\\')
337 lastWasEscape=1;
338 else {
339 if (*s==c || strchr(",:{}[]", *s)!=NULL)
340 break;
341 if (!iscntrl(*s)) {
342 GWEN_Buffer_AppendByte(buf, *s);
343 bytesAdded++;
344 }
345 }
346 }
347 s++;
348 }
349 if (next)
350 *next=s;
351
352 return bytesAdded;
353}
354
355
356
357int _readQuotedToken(const char *s, GWEN_BUFFER *buf, const char **next)
358{
359 int lastWasEscape=0;
360 int bytesAdded=0;
361
362 while(*s) {
363 if (lastWasEscape) {
364 GWEN_Buffer_AppendByte(buf, *s);
365 lastWasEscape=0;
366 bytesAdded++;
367 }
368 else {
369 if (*s=='\\')
370 lastWasEscape=1;
371 else {
372 if (*s=='"')
373 break;
374 GWEN_Buffer_AppendByte(buf, *s);
375 bytesAdded++;
376 }
377 }
378 s++;
379 }
380 if (next)
381 *next=s;
382
383 return bytesAdded;
384}
385
386
387
388
389
#define NULL
Definition binreloc.c:300
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition buffer.c:42
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition buffer.c:653
uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
Definition buffer.c:253
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition buffer.c:89
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition buffer.c:235
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition buffer.c:393
#define DBG_INFO(dbg_logger, format,...)
Definition debug.h:181
#define GWEN_ERROR_BAD_DATA
Definition error.h:121
#define GWEN_ERROR_NO_DATA
Definition error.h:94
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition buffer.h:38
GWEN_JSON_ELEM * GWEN_JsonElement_new(int t, const char *sData)
Definition json.c:50
void GWEN_JsonElement_free(GWEN_JSON_ELEM *je)
Definition json.c:63
@ GWEN_JSON_ELEMTYPE_OBJECT
Definition json.h:45
@ GWEN_JSON_ELEMTYPE_STRING
Definition json.h:43
@ GWEN_JSON_ELEMTYPE_BOOL
Definition json.h:41
@ GWEN_JSON_ELEMTYPE_NULL
Definition json.h:40
@ GWEN_JSON_ELEMTYPE_KEY
Definition json.h:39
@ GWEN_JSON_ELEMTYPE_ARRAY
Definition json.h:44
@ GWEN_JSON_ELEMTYPE_UNKNOWN
Definition json.h:38
@ GWEN_JSON_ELEMTYPE_NUM
Definition json.h:42
struct GWEN_JSON_ELEM GWEN_JSON_ELEM
Definition json.h:33
static int _readQuotedToken(const char *s, GWEN_BUFFER *buf, const char **next)
Definition json_read.c:357
static GWEN_JSON_ELEM * _readValue(const char *s, const char **next)
Definition json_read.c:222
static int _readSimpleValueAndReturnType(const char *s, GWEN_BUFFER *buf, const char **next)
Definition json_read.c:269
static int _readTokenUntilChar(const char *s, GWEN_BUFFER *buf, int c, const char **next)
Definition json_read.c:324
static int _readKey(const char *s, GWEN_BUFFER *buf, const char **next)
Definition json_read.c:180
static GWEN_JSON_ELEM * _readArray(const char *s, const char **next)
Definition json_read.c:138
static GWEN_JSON_ELEM * _readObject(const char *s, const char **next)
Definition json_read.c:76
GWEN_JSON_ELEM * GWEN_JsonElement_fromString(const char *s)
Definition json_read.c:53
#define GWEN_LOGDOMAIN
Definition logger.h:32