This is Unofficial EPICS BASE Doxygen Site
yajl_parser.h File Reference
#include "yajl_parse.h"
#include "yajl_bytestack.h"
#include "yajl_buf.h"
#include "yajl_lex.h"
+ Include dependency graph for yajl_parser.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  yajl_handle_t
 

Enumerations

enum  yajl_state {
  yajl_state_start = 0, yajl_state_parse_complete, yajl_state_parse_error, yajl_state_lexical_error,
  yajl_state_map_start, yajl_state_map_sep, yajl_state_map_need_val, yajl_state_map_got_val,
  yajl_state_map_need_key, yajl_state_array_start, yajl_state_array_got_val, yajl_state_array_need_val,
  yajl_state_got_value
}
 

Functions

yajl_status yajl_do_parse (yajl_handle handle, const unsigned char *jsonText, size_t jsonTextLen)
 
yajl_status yajl_do_finish (yajl_handle handle)
 
unsigned char * yajl_render_error_string (yajl_handle hand, const unsigned char *jsonText, size_t jsonTextLen, int verbose)
 
long long yajl_parse_integer (const unsigned char *number, size_t length)
 

Enumeration Type Documentation

enum yajl_state
Enumerator
yajl_state_start 
yajl_state_parse_complete 
yajl_state_parse_error 
yajl_state_lexical_error 
yajl_state_map_start 
yajl_state_map_sep 
yajl_state_map_need_val 
yajl_state_map_got_val 
yajl_state_map_need_key 
yajl_state_array_start 
yajl_state_array_got_val 
yajl_state_array_need_val 
yajl_state_got_value 

Definition at line 26 of file yajl_parser.h.

Function Documentation

yajl_status yajl_do_finish ( yajl_handle  handle)

Definition at line 160 of file yajl_parser.c.

161 {
162  yajl_status stat;
163  stat = yajl_do_parse(hand,(const unsigned char *) " ",1);
164 
165  if (stat != yajl_status_ok) return stat;
166 
167  switch(yajl_bs_current(hand->stateStack))
168  {
171  return yajl_status_error;
174  return yajl_status_ok;
175  default:
176  if (!(hand->flags & yajl_allow_partial_values))
177  {
178  yajl_bs_set(hand->stateStack, yajl_state_parse_error);
179  hand->parseError = "premature EOF";
180  return yajl_status_error;
181  }
182  return yajl_status_ok;
183  }
184 }
#define yajl_bs_set(obs, byte)
#define yajl_bs_current(obs)
yajl_status yajl_do_parse(yajl_handle hand, const unsigned char *jsonText, size_t jsonTextLen)
Definition: yajl_parser.c:187
yajl_status
Definition: yajl_parse.h:32
yajl_status yajl_do_parse ( yajl_handle  handle,
const unsigned char *  jsonText,
size_t  jsonTextLen 
)

Definition at line 187 of file yajl_parser.c.

189 {
190  yajl_tok tok;
191  const unsigned char * buf;
192  size_t bufLen;
193  size_t * offset = &(hand->bytesConsumed);
194 
195  *offset = 0;
196 
197  around_again:
198  switch (yajl_bs_current(hand->stateStack)) {
200  if (hand->flags & yajl_allow_multiple_values) {
201  yajl_bs_set(hand->stateStack, yajl_state_got_value);
202  goto around_again;
203  }
204  if (!(hand->flags & yajl_allow_trailing_garbage)) {
205  if (*offset != jsonTextLen) {
206  tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
207  offset, &buf, &bufLen);
208  if (tok != yajl_tok_eof) {
209  yajl_bs_set(hand->stateStack, yajl_state_parse_error);
210  hand->parseError = "trailing garbage";
211  }
212  goto around_again;
213  }
214  }
215  return yajl_status_ok;
218  return yajl_status_error;
219  case yajl_state_start:
223  case yajl_state_array_start: {
224  /* for arrays and maps, we advance the state for this
225  * depth, then push the state of the next depth.
226  * If an error occurs during the parsing of the nesting
227  * enitity, the state at this level will not matter.
228  * a state that needs pushing will be anything other
229  * than state_start */
230 
231  yajl_state stateToPush = yajl_state_start;
232 
233  tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
234  offset, &buf, &bufLen);
235 
236  switch (tok) {
237  case yajl_tok_eof:
238  return yajl_status_ok;
239  case yajl_tok_error:
240  yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
241  goto around_again;
242  case yajl_tok_string:
243  if (hand->callbacks && hand->callbacks->yajl_string) {
244  _CC_CHK(hand->callbacks->yajl_string(hand->ctx,
245  buf, bufLen));
246  }
247  break;
249  if (hand->callbacks && hand->callbacks->yajl_string) {
250  yajl_buf_clear(hand->decodeBuf);
251  yajl_string_decode(hand->decodeBuf, buf, bufLen);
252  _CC_CHK(hand->callbacks->yajl_string(
253  hand->ctx, yajl_buf_data(hand->decodeBuf),
254  yajl_buf_len(hand->decodeBuf)));
255  }
256  break;
257  case yajl_tok_bool:
258  if (hand->callbacks && hand->callbacks->yajl_boolean) {
259  _CC_CHK(hand->callbacks->yajl_boolean(hand->ctx,
260  *buf == 't'));
261  }
262  break;
263  case yajl_tok_null:
264  if (hand->callbacks && hand->callbacks->yajl_null) {
265  _CC_CHK(hand->callbacks->yajl_null(hand->ctx));
266  }
267  break;
268  case yajl_tok_left_brace:
269  if (hand->callbacks && hand->callbacks->yajl_start_map) {
270  _CC_CHK(hand->callbacks->yajl_start_map(hand->ctx));
271  }
272  stateToPush = yajl_state_map_start;
273  break;
275  if (hand->callbacks && hand->callbacks->yajl_start_array) {
276  _CC_CHK(hand->callbacks->yajl_start_array(hand->ctx));
277  }
278  stateToPush = yajl_state_array_start;
279  break;
280  case yajl_tok_integer:
281  if (hand->callbacks) {
282  if (hand->callbacks->yajl_number) {
283  _CC_CHK(hand->callbacks->yajl_number(
284  hand->ctx,(const char *) buf, bufLen));
285  } else if (hand->callbacks->yajl_integer) {
286  long long int i = 0;
287  i = yajl_parse_integer(buf, bufLen);
288  if ((i == LLONG_MIN || i == LLONG_MAX) &&
289  errno == ERANGE)
290  {
291  yajl_bs_set(hand->stateStack,
293  hand->parseError = "integer overflow" ;
294  /* try to restore error offset */
295  if (*offset >= bufLen) *offset -= bufLen;
296  else *offset = 0;
297  goto around_again;
298  }
299  _CC_CHK(hand->callbacks->yajl_integer(hand->ctx,
300  i));
301  }
302  }
303  break;
304  case yajl_tok_double:
305  if (hand->callbacks) {
306  if (hand->callbacks->yajl_number) {
307  _CC_CHK(hand->callbacks->yajl_number(
308  hand->ctx, (const char *) buf, bufLen));
309  } else if (hand->callbacks->yajl_double) {
310  double d = 0.0;
311  yajl_buf_clear(hand->decodeBuf);
312  yajl_buf_append(hand->decodeBuf, buf, bufLen);
313  buf = yajl_buf_data(hand->decodeBuf);
314  d = strtod((char *) buf, NULL);
315  if ((d == HUGE_VAL || d == -HUGE_VAL) &&
316  errno == ERANGE)
317  {
318  yajl_bs_set(hand->stateStack,
320  hand->parseError = "numeric (floating point) "
321  "overflow";
322  /* try to restore error offset */
323  if (*offset >= bufLen) *offset -= bufLen;
324  else *offset = 0;
325  goto around_again;
326  }
327  _CC_CHK(hand->callbacks->yajl_double(hand->ctx,
328  d));
329  }
330  }
331  break;
332  case yajl_tok_right_bracket: {
333  yajl_state s = yajl_bs_current(hand->stateStack);
334  if (s == yajl_state_array_start ||
336  {
337  if (hand->callbacks &&
338  hand->callbacks->yajl_end_array)
339  {
340  _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx));
341  }
342  yajl_bs_pop(hand->stateStack);
343  goto around_again;
344  }
345  /* intentional fall-through */
346  }
347  case yajl_tok_colon:
348  case yajl_tok_comma:
350  yajl_bs_set(hand->stateStack, yajl_state_parse_error);
351  hand->parseError =
352  "unallowed token at this point in JSON text";
353  goto around_again;
354  default:
355  yajl_bs_set(hand->stateStack, yajl_state_parse_error);
356  hand->parseError = "invalid token, internal error";
357  goto around_again;
358  }
359  /* got a value. transition depends on the state we're in. */
360  {
361  yajl_state s = yajl_bs_current(hand->stateStack);
362  if (s == yajl_state_start || s == yajl_state_got_value) {
363  yajl_bs_set(hand->stateStack, yajl_state_parse_complete);
364  } else if (s == yajl_state_map_need_val) {
365  yajl_bs_set(hand->stateStack, yajl_state_map_got_val);
366  } else {
367  yajl_bs_set(hand->stateStack, yajl_state_array_got_val);
368  }
369  }
370  if (stateToPush != yajl_state_start) {
371  yajl_bs_push(hand->stateStack, stateToPush);
372  }
373 
374  goto around_again;
375  }
378  /* only difference between these two states is that in
379  * start '}' is valid, whereas in need_key, we've parsed
380  * a comma, and a string key _must_ follow */
381  tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
382  offset, &buf, &bufLen);
383  switch (tok) {
384  case yajl_tok_eof:
385  return yajl_status_ok;
386  case yajl_tok_error:
387  yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
388  goto around_again;
390  if (hand->callbacks && hand->callbacks->yajl_map_key) {
391  yajl_buf_clear(hand->decodeBuf);
392  yajl_string_decode(hand->decodeBuf, buf, bufLen);
393  buf = yajl_buf_data(hand->decodeBuf);
394  bufLen = yajl_buf_len(hand->decodeBuf);
395  }
396  /* intentional fall-through */
397  case yajl_tok_string:
398  if (hand->callbacks && hand->callbacks->yajl_map_key) {
399  _CC_CHK(hand->callbacks->yajl_map_key(hand->ctx, buf,
400  bufLen));
401  }
402  yajl_bs_set(hand->stateStack, yajl_state_map_sep);
403  goto around_again;
404  case yajl_tok_right_brace: {
405  yajl_state s = yajl_bs_current(hand->stateStack);
406  if (s == yajl_state_map_start ||
408  if (hand->callbacks && hand->callbacks->yajl_end_map) {
409  _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
410  }
411  yajl_bs_pop(hand->stateStack);
412  goto around_again;
413  }
414  }
415  default:
416  yajl_bs_set(hand->stateStack, yajl_state_parse_error);
417  hand->parseError =
418  "invalid object key (must be a string)";
419  goto around_again;
420  }
421  }
422  case yajl_state_map_sep: {
423  tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
424  offset, &buf, &bufLen);
425  switch (tok) {
426  case yajl_tok_colon:
427  yajl_bs_set(hand->stateStack, yajl_state_map_need_val);
428  goto around_again;
429  case yajl_tok_eof:
430  return yajl_status_ok;
431  case yajl_tok_error:
432  yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
433  goto around_again;
434  default:
435  yajl_bs_set(hand->stateStack, yajl_state_parse_error);
436  hand->parseError = "object key and value must "
437  "be separated by a colon (':')";
438  goto around_again;
439  }
440  }
441  case yajl_state_map_got_val: {
442  tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
443  offset, &buf, &bufLen);
444  switch (tok) {
446  if (hand->callbacks && hand->callbacks->yajl_end_map) {
447  _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
448  }
449  yajl_bs_pop(hand->stateStack);
450  goto around_again;
451  case yajl_tok_comma:
452  yajl_bs_set(hand->stateStack, yajl_state_map_need_key);
453  goto around_again;
454  case yajl_tok_eof:
455  return yajl_status_ok;
456  case yajl_tok_error:
457  yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
458  goto around_again;
459  default:
460  yajl_bs_set(hand->stateStack, yajl_state_parse_error);
461  hand->parseError = "after key and value, inside map, "
462  "I expect ',' or '}'";
463  /* try to restore error offset */
464  if (*offset >= bufLen) *offset -= bufLen;
465  else *offset = 0;
466  goto around_again;
467  }
468  }
470  tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
471  offset, &buf, &bufLen);
472  switch (tok) {
474  if (hand->callbacks && hand->callbacks->yajl_end_array) {
475  _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx));
476  }
477  yajl_bs_pop(hand->stateStack);
478  goto around_again;
479  case yajl_tok_comma:
480  yajl_bs_set(hand->stateStack, yajl_state_array_need_val);
481  goto around_again;
482  case yajl_tok_eof:
483  return yajl_status_ok;
484  case yajl_tok_error:
485  yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
486  goto around_again;
487  default:
488  yajl_bs_set(hand->stateStack, yajl_state_parse_error);
489  hand->parseError =
490  "after array element, I expect ',' or ']'";
491  goto around_again;
492  }
493  }
494  }
495 
496  abort();
497  return yajl_status_error;
498 }
int i
Definition: scan.c:967
#define yajl_bs_push(obs, byte)
#define yajl_bs_set(obs, byte)
#define yajl_bs_current(obs)
yajl_state
Definition: yajl_parser.h:26
#define NULL
Definition: catime.c:38
size_t yajl_buf_len(yajl_buf buf)
Definition: yajl_buf.c:97
void yajl_buf_append(yajl_buf buf, const void *data, size_t len)
Definition: yajl_buf.c:75
#define LLONG_MIN
Definition: yajl_parser.c:34
yajl_tok yajl_lex_lex(yajl_lexer lexer, const unsigned char *jsonText, size_t jsonTextLen, size_t *offset, const unsigned char **outBuf, size_t *outLen)
Definition: yajl_lex.c:503
yajl_tok
Definition: yajl_lex.h:22
void yajl_buf_clear(yajl_buf buf)
Definition: yajl_buf.c:86
long long yajl_parse_integer(const unsigned char *number, size_t length)
Definition: yajl_parser.c:41
#define _CC_CHK(x)
Definition: yajl_parser.c:150
#define yajl_bs_pop(obs)
const unsigned char * yajl_buf_data(yajl_buf buf)
Definition: yajl_buf.c:92
#define LLONG_MAX
Definition: yajl_parser.c:33
void yajl_string_decode(yajl_buf buf, const unsigned char *str, size_t len)
Definition: yajl_encode.c:116
long long yajl_parse_integer ( const unsigned char *  number,
size_t  length 
)

Definition at line 41 of file yajl_parser.c.

42 {
43  long long ret = 0;
44  long sign = 1;
45  const unsigned char *pos = number;
46  if (*pos == '-') { pos++; sign = -1; }
47  if (*pos == '+') { pos++; }
48 
49  while (pos < number + length) {
50  if ( ret > MAX_VALUE_TO_MULTIPLY ) {
51  errno = ERANGE;
52  return sign == 1 ? LLONG_MAX : LLONG_MIN;
53  }
54  ret *= 10;
55  if (LLONG_MAX - ret < (*pos - '0')) {
56  errno = ERANGE;
57  return sign == 1 ? LLONG_MAX : LLONG_MIN;
58  }
59  ret += (*pos++ - '0');
60  }
61 
62  return sign * ret;
63 }
#define LLONG_MIN
Definition: yajl_parser.c:34
#define MAX_VALUE_TO_MULTIPLY
Definition: yajl_parser.c:37
#define LLONG_MAX
Definition: yajl_parser.c:33
unsigned char* yajl_render_error_string ( yajl_handle  hand,
const unsigned char *  jsonText,
size_t  jsonTextLen,
int  verbose 
)

Definition at line 66 of file yajl_parser.c.

68 {
69  size_t offset = hand->bytesConsumed;
70  unsigned char * str;
71  const char * errorType = NULL;
72  const char * errorText = NULL;
73  char text[72];
74  const char * arrow = " (right here) ------^\n";
75 
77  errorType = "parse";
78  errorText = hand->parseError;
80  errorType = "lexical";
82  } else {
83  errorType = "unknown";
84  }
85 
86  {
87  size_t memneeded = 0;
88  memneeded += strlen(errorType);
89  memneeded += strlen(" error");
90  if (errorText != NULL) {
91  memneeded += strlen(": ");
92  memneeded += strlen(errorText);
93  }
94  str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2);
95  if (!str) return NULL;
96  str[0] = 0;
97  strcat((char *) str, errorType);
98  strcat((char *) str, " error");
99  if (errorText != NULL) {
100  strcat((char *) str, ": ");
101  strcat((char *) str, errorText);
102  }
103  strcat((char *) str, "\n");
104  }
105 
106  /* now we append as many spaces as needed to make sure the error
107  * falls at char 41, if verbose was specified */
108  if (verbose) {
109  size_t start, end, i;
110  size_t spacesNeeded;
111 
112  spacesNeeded = (offset < 30 ? 40 - offset : 10);
113  start = (offset >= 30 ? offset - 30 : 0);
114  end = (offset + 30 > jsonTextLen ? jsonTextLen : offset + 30);
115 
116  for (i=0;i<spacesNeeded;i++) text[i] = ' ';
117 
118  for (;start < end;start++, i++) {
119  if (jsonText[start] != '\n' && jsonText[start] != '\r')
120  {
121  text[i] = jsonText[start];
122  }
123  else
124  {
125  text[i] = ' ';
126  }
127  }
128  assert(i <= 71);
129  text[i++] = '\n';
130  text[i] = 0;
131  {
132  char * newStr = (char *)
133  YA_MALLOC(&(hand->alloc), (unsigned int)(strlen((char *) str) +
134  strlen((char *) text) +
135  strlen(arrow) + 1));
136  if (newStr) {
137  newStr[0] = 0;
138  strcat((char *) newStr, (char *) str);
139  strcat((char *) newStr, text);
140  strcat((char *) newStr, arrow);
141  }
142  YA_FREE(&(hand->alloc), str);
143  str = (unsigned char *) newStr;
144  }
145  }
146  return str;
147 }
yajl_alloc_funcs alloc
Definition: yajl_parser.h:56
#define YA_MALLOC(afs, sz)
Definition: yajl_alloc.h:32
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
yajl_lex_error yajl_lex_get_error(yajl_lexer lexer)
Definition: yajl_lex.c:733
#define YA_FREE(afs, ptr)
Definition: yajl_alloc.h:33
const char * yajl_lex_error_to_string(yajl_lex_error error)
Definition: yajl_lex.c:695
int i
Definition: scan.c:967
#define yajl_bs_current(obs)
const char * parseError
Definition: yajl_parser.h:46
#define NULL
Definition: catime.c:38
#define str(v)
yajl_lexer lexer
Definition: yajl_parser.h:45
size_t bytesConsumed
Definition: yajl_parser.h:50
void verbose(void)
Definition: verbose.c:27
yajl_bytestack stateStack
Definition: yajl_parser.h:54