ujson
Complete and simple JSON reader and writer written in C
ujson_reader.h
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3  * Copyright (C) 2021-2024 Cyril Hrubis <metan@ucw.cz>
4  */
5 
17 #ifndef UJSON_READER_H
18 #define UJSON_READER_H
19 
20 #include <stdio.h>
21 #include <ujson_common.h>
22 
32 #define UJSON_READER_INIT(buf, buf_len, rflags) { \
33  .max_depth = UJSON_RECURSION_MAX, \
34  .err_print = UJSON_ERR_PRINT, \
35  .err_print_priv = UJSON_ERR_PRINT_PRIV, \
36  .json = buf, \
37  .len = buf_len, \
38  .flags = rflags \
39 }
40 
45 };
46 
50 struct ujson_reader {
52  const char *json;
54  size_t len;
56  size_t off;
58  size_t sub_off;
60  unsigned int depth;
62  unsigned int max_depth;
63 
66 
68  void (*err_print)(void *err_print_priv, const char *line);
69  void *err_print_priv;
70 
71  char err[UJSON_ERR_MAX];
72  char buf[];
73 };
74 
83 #define UJSON_VAL_INIT(sbuf, sbuf_size) { \
84  .buf = sbuf, \
85  .buf_size = sbuf_size, \
86 }
87 
91 struct ujson_val {
97  enum ujson_type type;
98 
100  char *buf;
101  size_t buf_size;
102 
109  size_t idx;
110 
112  union {
114  int val_bool;
116  long long val_int;
118  const char *val_str;
119  };
120 
127  double val_float;
128 
130  char id[UJSON_ID_MAX];
131 
132  char buf__[];
133 };
134 
141 ujson_val *ujson_val_alloc(size_t buf_size);
142 
149 
156 static inline int ujson_val_valid(struct ujson_val *res)
157 {
158  return !!res->type;
159 }
160 
171 void ujson_err(ujson_reader *self, const char *fmt, ...)
172  __attribute__((format(printf, 2, 3)));
173 
185 
196 void ujson_warn(ujson_reader *self, const char *fmt, ...)
197  __attribute__((format(printf, 2, 3)));
198 
205 static inline int ujson_reader_err(ujson_reader *self)
206 {
207  return !!self->err[0];
208 }
209 
217 
225 
234 int ujson_obj_first(ujson_reader *self, struct ujson_val *res);
235 
247 int ujson_obj_next(ujson_reader *self, struct ujson_val *res);
248 
262 #define UJSON_OBJ_FOREACH(self, res) \
263  for (ujson_obj_first(self, res); ujson_val_valid(res); ujson_obj_next(self, res))
264 
273 size_t ujson_lookup(const void *arr, size_t memb_size, size_t list_len,
274  const char *key);
275 
279 typedef struct ujson_obj_attr {
281  const char *key;
290  enum ujson_type type;
292 
294 typedef struct ujson_obj {
302  size_t attr_cnt;
304 
305 static inline size_t ujson_obj_lookup(const ujson_obj *obj, const char *key)
306 {
307  return ujson_lookup(obj->attrs, sizeof(*obj->attrs), obj->attr_cnt, key);
308 }
309 
311 #define UJSON_OBJ_ATTR(keyv, typev) \
312  {.key = keyv, .type = typev}
313 
315 #define UJSON_OBJ_ATTR_IDX(key_idx, keyv, typev) \
316  [key_idx] = {.key = keyv, .type = typev}
317 
329  const struct ujson_obj *obj, const struct ujson_obj *ign);
330 
336 extern const struct ujson_obj *ujson_empty_obj;
337 
353  const struct ujson_obj *obj, const struct ujson_obj *ign);
354 
381 #define UJSON_OBJ_FOREACH_FILTER(self, res, obj, ign) \
382  for (ujson_obj_first_filter(self, res, obj, ign); \
383  ujson_val_valid(res); \
384  ujson_obj_next_filter(self, res, obj, ign))
385 
394 
403 int ujson_arr_first(ujson_reader *self, struct ujson_val *res);
404 
416 int ujson_arr_next(ujson_reader *self, struct ujson_val *res);
417 
431 #define UJSON_ARR_FOREACH(self, res) \
432  for (ujson_arr_first(self, res); ujson_val_valid(res); ujson_arr_next(self, res))
433 
442 
446 typedef struct ujson_reader_state {
447  size_t off;
448  unsigned int depth;
450 
461 {
462  struct ujson_reader_state ret = {
463  .off = self->sub_off,
464  .depth = self->depth,
465  };
466 
467  return ret;
468 }
469 
480 {
481  if (ujson_reader_err(self))
482  return;
483 
484  self->off = state.off;
485  self->sub_off = state.off;
486  self->depth = state.depth;
487 }
488 
494 static inline void ujson_reader_reset(ujson_reader *self)
495 {
496  self->off = 0;
497  self->sub_off = 0;
498  self->depth = 0;
499  self->err[0] = 0;
500 }
501 
510 ujson_reader *ujson_reader_load(const char *path);
511 
518 
531 
538 static inline int ujson_reader_consumed(ujson_reader *self)
539 {
540  return self->off >= self->len;
541 }
542 
543 #endif /* UJSON_H */
A JSON object attribute description i.e. key and type.
Definition: ujson_reader.h:279
enum ujson_type type
A JSON object value type.
Definition: ujson_reader.h:290
const char * key
A JSON object key name.
Definition: ujson_reader.h:281
A JSON object description.
Definition: ujson_reader.h:294
const ujson_obj_attr * attrs
A list of attributes.
Definition: ujson_reader.h:300
size_t attr_cnt
A size of attrs array.
Definition: ujson_reader.h:302
A JSON reader state.
Definition: ujson_reader.h:446
A JSON parser internal state.
Definition: ujson_reader.h:50
unsigned int max_depth
Definition: ujson_reader.h:62
const char * json
Definition: ujson_reader.h:52
size_t sub_off
Definition: ujson_reader.h:58
enum ujson_reader_flags flags
Definition: ujson_reader.h:65
unsigned int depth
Definition: ujson_reader.h:60
void(* err_print)(void *err_print_priv, const char *line)
Definition: ujson_reader.h:68
A parsed JSON key value pair.
Definition: ujson_reader.h:91
double val_float
A floating point value.
Definition: ujson_reader.h:127
char * buf
Definition: ujson_reader.h:100
int val_bool
A boolean value.
Definition: ujson_reader.h:114
long long val_int
An integer value.
Definition: ujson_reader.h:116
size_t idx
An index to attribute list.
Definition: ujson_reader.h:109
const char * val_str
A string value.
Definition: ujson_reader.h:118
enum ujson_type type
A value type.
Definition: ujson_reader.h:97
Common JSON reader/writer definitions.
#define UJSON_ERR_MAX
Maximal error message length.
Definition: ujson_common.h:15
#define UJSON_ID_MAX
Maximal id string lenght including terminating null element.
Definition: ujson_common.h:17
ujson_type
A JSON data type.
Definition: ujson_common.h:27
void static int ujson_reader_err(ujson_reader *self)
Returns true if error was encountered.
Definition: ujson_reader.h:205
int ujson_arr_first(ujson_reader *self, struct ujson_val *res)
Starts parsing of a JSON array.
static void ujson_reader_reset(ujson_reader *self)
Resets the parser to a start.
Definition: ujson_reader.h:494
int ujson_obj_next_filter(ujson_reader *self, struct ujson_val *res, const struct ujson_obj *obj, const struct ujson_obj *ign)
Parses next value from a JSON object with attribute lists.
void ujson_err(ujson_reader *self, const char *fmt,...) __attribute__((format(printf
Fills the reader error.
static int ujson_val_valid(struct ujson_val *res)
Checks is result has valid type.
Definition: ujson_reader.h:156
enum ujson_type ujson_reader_start(ujson_reader *self)
Returns if first element in JSON is object or array.
int ujson_arr_next(ujson_reader *self, struct ujson_val *res)
Parses next value from a JSON array.
struct ujson_reader_state ujson_reader_state
A JSON reader state.
enum ujson_type ujson_next_type(ujson_reader *self)
Returns the type of next element in buffer.
ujson_reader * ujson_reader_load(const char *path)
Loads a file into an ujson_reader buffer.
void void ujson_err_print(ujson_reader *self)
Prints error stored in the buffer.
int ujson_obj_next(ujson_reader *self, struct ujson_val *res)
Parses next value from a JSON object.
static void ujson_reader_state_load(ujson_reader *self, ujson_reader_state state)
Returns the parser to a saved state.
Definition: ujson_reader.h:479
void ujson_reader_finish(ujson_reader *self)
Prints errors and warnings at the end of parsing.
int ujson_obj_first_filter(ujson_reader *self, struct ujson_val *res, const struct ujson_obj *obj, const struct ujson_obj *ign)
Starts parsing of a JSON object with attribute lists.
static int ujson_reader_consumed(ujson_reader *self)
Returns non-zero if whole buffer has been consumed.
Definition: ujson_reader.h:538
size_t ujson_lookup(const void *arr, size_t memb_size, size_t list_len, const char *key)
Utility function for log(n) lookup in a sorted array.
void ujson_warn(ujson_reader *self, const char *fmt,...) __attribute__((format(printf
Prints a warning.
int ujson_obj_first(ujson_reader *self, struct ujson_val *res)
Starts parsing of a JSON object.
int ujson_arr_skip(ujson_reader *self)
Skips parsing of a JSON array.
struct ujson_obj ujson_obj
A JSON object description.
struct ujson_obj_attr ujson_obj_attr
A JSON object attribute description i.e. key and type.
static ujson_reader_state ujson_reader_state_save(ujson_reader *self)
Returns a parser state at the start of current object/array.
Definition: ujson_reader.h:460
void ujson_val_free(ujson_val *self)
Frees a JSON value.
ujson_val * ujson_val_alloc(size_t buf_size)
Allocates a JSON value.
void ujson_reader_free(ujson_reader *self)
Frees an ujson_reader buffer.
ujson_reader_flags
Reader flags.
Definition: ujson_reader.h:42
@ UJSON_READER_STRICT
If set warnings are treated as errors.
Definition: ujson_reader.h:44
const struct ujson_obj * ujson_empty_obj
An empty object attribute list.
int ujson_obj_skip(ujson_reader *self)
Skips parsing of a JSON object.