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 
42 static GWEN_JSON_ELEM *_readObject(const char *s, const char **next);
43 static GWEN_JSON_ELEM *_readArray(const char *s, const char **next);
44 static int _readKey(const char *s, GWEN_BUFFER *buf, const char **next);
45 static GWEN_JSON_ELEM *_readValue(const char *s, const char **next);
46 static int _readSimpleValueAndReturnType(const char *s, GWEN_BUFFER *buf, const char **next);
47 static int _readTokenUntilChar(const char *s, GWEN_BUFFER *buf, int c, const char **next);
48 static 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 
76 GWEN_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 
93  GWEN_Buffer_Reset(buf);
94  rv=_readKey(s, buf, &s);
95  if (rv<0) {
96  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
97  GWEN_Buffer_free(buf);
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 
138 GWEN_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 
180 int _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 
222 GWEN_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  }
256  jeValue=GWEN_JsonElement_new(rv, GWEN_Buffer_GetStart(buf));
257  GWEN_Buffer_free(buf);
258  }
259 
260  if (next)
261  *next=s;
262 
263  return jeValue;
264 }
265 
266 
267 
268 
269 int _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 
324 int _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 
357 int _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 
struct GWEN_JSON_ELEM GWEN_JSON_ELEM
Definition: json.h:33
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
static int _readQuotedToken(const char *s, GWEN_BUFFER *buf, const char **next)
Definition: json_read.c:357
#define NULL
Definition: binreloc.c:300
GWEN_JSON_ELEM * GWEN_JsonElement_new(int t, const char *sData)
Definition: json.c:50
#define GWEN_LOGDOMAIN
Definition: logger.h:32
uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
Definition: buffer.c:253
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
static int _readKey(const char *s, GWEN_BUFFER *buf, const char **next)
Definition: json_read.c:180
#define GWEN_ERROR_BAD_DATA
Definition: error.h:121
static int _readSimpleValueAndReturnType(const char *s, GWEN_BUFFER *buf, const char **next)
Definition: json_read.c:269
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:393
static GWEN_JSON_ELEM * _readArray(const char *s, const char **next)
Definition: json_read.c:138
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
void GWEN_JsonElement_free(GWEN_JSON_ELEM *je)
Definition: json.c:63
static GWEN_JSON_ELEM * _readValue(const char *s, const char **next)
Definition: json_read.c:222
#define DBG_INFO(dbg_logger, format,...)
Definition: debug.h:181
#define GWEN_ERROR_NO_DATA
Definition: error.h:94
GWEN_JSON_ELEM * GWEN_JsonElement_fromString(const char *s)
Definition: json_read.c:53
static GWEN_JSON_ELEM * _readObject(const char *s, const char **next)
Definition: json_read.c:76
static int _readTokenUntilChar(const char *s, GWEN_BUFFER *buf, int c, const char **next)
Definition: json_read.c:324