The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
jsmn_helper.c
1 #include <lib/jsmn_helper.h>
2 #include <mm/dymelor.h>
3 
4 #include <string.h>
5 #include <stdio.h>
6 #include <limits.h>
7 
8 
9 int load_and_parse_json_file(const char *file_name, char **file_str_p, jsmntok_t **tokens_p) {
10  FILE *t_file;
11  long int file_len;
12  jsmn_parser parser;
13  int tokens_cnt;
14  char *buffer = NULL; // we initialize those pointers so we can safely free them even if uninstantiated
15  jsmntok_t *tokens = NULL;
16 
17  // by default we fail
18  int ret = -1;
19 
20  // sanity check
21  if(file_name == NULL || file_str_p == NULL || tokens_p == NULL)
22  return -1;
23 
24  // open file
25  t_file = fopen(file_name, "r");
26  if(t_file == NULL)
27  return -1;
28 
29  // compute file length
30  // set file position at EOF
31  if(fseek(t_file, 0L, SEEK_END))
32  goto end;
33  //get the actual length
34  file_len = ftell(t_file);
35  if(file_len < 0)
36  goto end;
37  // reset file position
38  if(fseek(t_file, 0L, SEEK_SET))
39  goto end;
40 
41  // allocate buffer
42  buffer = rsalloc(file_len + 1);
43  // Load the whole JSON file from disk
44  if(!fread(buffer, (size_t) file_len, 1, t_file))
45  goto end;
46 
47  // close file
48  fclose(t_file);
49 
50  // terminate buffer with null character
51  buffer[file_len] = '\0';
52 
53  // init parser
54  jsmn_init(&parser);
55  // compute tokens count
56  tokens_cnt = jsmn_parse(&parser, buffer, file_len, NULL, 0);
57  if(tokens_cnt <= 0)
58  goto end;
59  // allocate tokens buffer
60  tokens = rsalloc(sizeof(jsmntok_t) * (size_t) tokens_cnt);
61 
62  // re init parser
63  jsmn_init(&parser);
64  // Parse the loaded JSON file
65  if(jsmn_parse(&parser, buffer, file_len, tokens, tokens_cnt) != tokens_cnt)
66  goto end;
67 
68  // returns the important values
69  *file_str_p = buffer;
70  *tokens_p = tokens;
71  // set a correct return code
72  ret = 0;
73  end:
74 
75  // if we are failing free the buffers
76  if(ret) {
77  rsfree(buffer);
78  rsfree(tokens);
79  }
80 
81  return ret;
82 }
83 
84 void init_gnt_closure(struct _gnt_closure_t *closure) {
85  closure->a = 0;
86  closure->b = 0;
87 }
88 
89 c_jsmntok_t* get_next_token(c_jsmntok_t *base_t, c_jsmntok_t *t, struct _gnt_closure_t *closure) {
90 
91  // we expect t to be an object or an array
92  if((t->type != JSMN_OBJECT && t->type != JSMN_ARRAY) || t->size <= closure->a)
93  return NULL;
94 
95  closure->a++;
96  closure->b++;
97 
98  while ((t + closure->b)->parent != (t - base_t))
99  closure->b++;
100 
101  return t + closure->b;
102 }
103 
104 c_jsmntok_t* get_value_token_by_key(c_jsmntok_t *base_t, const char *base, c_jsmntok_t *t, const char *key) {
105 
106  c_jsmntok_t *t_aux;
107 
108  // we expect t to be an object
109  if(t->type != JSMN_OBJECT)
110  return NULL;
111 
112  struct _gnt_closure_t closure = GNT_CLOSURE_INITIALIZER;
113 
114  while ((t_aux = get_next_token(base_t, t, &closure)) != NULL) {
115  /*
116  * this stuff is not greatly documented in jsmn, anyway turns out that
117  * strings acting as object keys have child count set to 1.
118  * This is just another unnecessary check.
119  */
120  if(t_aux->type == JSMN_STRING && t_aux->size == 1) {
121  if(strcmp_token(base, t_aux, key) == 0)
122  // this is token representing the value associated with the key we found
123  return t_aux + 1;
124  }
125  }
126  return NULL;
127 }
128 
129 size_t children_count_token(c_jsmntok_t *base_t, c_jsmntok_t *t) {
130  struct _gnt_closure_t closure = GNT_CLOSURE_INITIALIZER;
131  size_t ret = 0;
132 
133  while (get_next_token(base_t, t, &closure))
134  ret++;
135 
136  return ret;
137 }
138 
139 c_jsmntok_t* get_at_token(c_jsmntok_t *base_t, c_jsmntok_t *t, size_t i) {
140  struct _gnt_closure_t closure = GNT_CLOSURE_INITIALIZER;
141 
142  while (i--)
143  if(!(get_next_token(base_t, t, &closure)))
144  return NULL;
145 
146  return get_next_token(base_t, t, &closure);
147 }
148 
149 int parse_double_token(const char *base, c_jsmntok_t *t, double *result) {
150  char buff[64];
151  size_t size;
152  double tmp;
153  char *check;
154 
155  if(t->type != JSMN_PRIMITIVE)
156  return -1;
157 
158  size = (size_t) (t->end - t->start);
159  size = size < (64 - 1) ? size : (64 - 1);
160 
161  memcpy(buff, &base[t->start], size);
162  buff[size] = '\0';
163 
164  tmp = strtod(buff, &check);
165  if(buff == check)
166  return -1;
167 
168  *result = tmp;
169  return 0;
170 }
171 
172 int parse_unsigned_token(const char *base, c_jsmntok_t *t, unsigned *result) {
173  double tmp;
174 
175  if(parse_double_token(base, t, &tmp) < 0 ||
176  tmp < 0.0 ||
177  tmp > UINT_MAX ||
178  tmp > (unsigned) tmp ||
179  tmp < (unsigned) tmp)
180  return -1;
181 
182  *result = (unsigned) tmp;
183  return 0;
184 }
185 
186 int strcmp_token(const char *base, c_jsmntok_t *t, const char* str) {
187  int t_len = t->end - t->start;
188  int res = strncmp(&base[t->start], str, t_len);
189  return res == 0 ? str[t_len] != '\0' : res;
190 }
191 
192 int parse_double_by_key(c_jsmntok_t *base_t, const char *base, c_jsmntok_t *t_obj, const char *key, double *result) {
193  // sanity checks
194  if(!(base_t && base && t_obj && key && result))
195  return -1;
196 
197  // parse requested double
198  c_jsmntok_t *t = get_value_token_by_key(base_t, base, t_obj, key);
199  if(t == NULL || parse_double_token(base, t, result) < 0) {
200  return -1;
201  }
202 
203  return 0;
204 }
205 
206 int parse_unsigned_by_key(c_jsmntok_t *base_t, const char *base, c_jsmntok_t *t_obj, const char *key, unsigned *result) {
207  // sanity checks
208  if(!(base_t && base && t_obj && key && result))
209  return -1;
210 
211  // parse requested unsigned
212  c_jsmntok_t *t = get_value_token_by_key(base_t, base, t_obj, key);
213  if(t == NULL || parse_unsigned_token(base, t, result) < 0) {
214  return -1;
215  }
216 
217  return 0;
218 }
219 
220 int parse_boolean_by_key(c_jsmntok_t *base_t, const char *base, c_jsmntok_t *t_obj, const char *key, bool *result) {
221  // sanity checks
222  if(!(base_t && base && t_obj && key && result))
223  return -1;
224 
225  // find relevant token
226  c_jsmntok_t *t = get_value_token_by_key(base_t, base, t_obj, key);
227  if(t == NULL || t->type != JSMN_PRIMITIVE) {
228  return -1;
229  }
230 
231  // parse the boolean value
232  if(!strcmp_token(base, t, "false")) {
233  *result = false;
234  } else if(!strcmp_token(base, t, "true")) {
235  *result = true;
236  } else {
237  return -1;
238  }
239 
240  return 0;
241 }
242 
243 int parse_double_array(c_jsmntok_t *base_t, const char *base, c_jsmntok_t *t_arr, unsigned expected_cnt, double *result) {
244  // sanity checks
245  if(!(base_t && base && t_arr && result))
246  return -1;
247 
248  // we make sure the elements count is the same
249  if(t_arr->type != JSMN_ARRAY || children_count_token(base_t, t_arr) != expected_cnt) {
250  return -1;
251  }
252 
253  struct _gnt_closure_t closure = GNT_CLOSURE_INITIALIZER;
254  unsigned i;
255  for (i = 0; i < expected_cnt; ++i) {
256  if(parse_double_token(base, get_next_token(base_t, t_arr, &closure), &result[i]) < 0)
257  return -1;
258  }
259 
260  return 0;
261 }
262 
263 unsigned parse_string_choice(c_jsmntok_t *base_t, const char *base, c_jsmntok_t *t_str, unsigned cnt, const char *choices[cnt]) {
264  // sanity checks
265  if(!(base_t && base && t_str && choices))
266  return UINT_MAX;
267 
268  // look for the topology type
269  if(t_str->type != JSMN_STRING) {
270  return UINT_MAX;
271  }
272 
273  unsigned i;
274  for (i = 0; i < cnt; ++i) {
275  if(!strcmp_token(base, t_str, choices[i]))
276  return i;
277  }
278  return cnt;
279 }
Definition: jsmn.h:43
Dynamic Memory Logger and Restorer (DyMeLoR)