12 #include "strbuffer.h"
15 #define JSON_TOKEN_INVALID -1
16 #define JSON_TOKEN_EOF 0
17 #define JSON_TOKEN_STRING 256
18 #define JSON_TOKEN_INTEGER 257
19 #define JSON_TOKEN_REAL 258
20 #define JSON_TOKEN_TRUE 259
21 #define JSON_TOKEN_FALSE 260
22 #define JSON_TOKEN_NULL 261
37 /*** error reporting ***/
39 static void json_set_error(json_error_t *error, const json_lex *lex,
43 char text[JSON_ERROR_TEXT_LENGTH];
49 vsnprintf(text, JSON_ERROR_TEXT_LENGTH, msg, ap);
54 error->line = lex->line;
57 int n = (int)(lex->input - lex->start);
58 snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
59 "%s near '%.*s'", text, n, lex->start);
63 snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
64 "%s near end of file", text);
70 snprintf(error->text, JSON_ERROR_TEXT_LENGTH, "%s", text);
75 /*** lexical analyzer ***/
77 static void json_scan_string(json_lex *lex)
80 const char *p = lex->input + 1;
83 lex->token = JSON_TOKEN_INVALID;
87 /* unterminated string literal */
91 if(0 <= *p && *p <= 0x1F) {
92 /* control character */
99 for(int i = 0; i < 4; i++, p++) {
104 else if(*p == '"' || *p == '\\' || *p == '/' || *p == 'b' ||
105 *p == 'f' || *p == 'n' || *p == 'r' || *p == 't')
114 /* the actual value is at most of the same length as the source
116 lex->value.string = malloc(p - lex->start);
117 if(!lex->value.string) {
118 /* this is not very nice, since TOKEN_INVALID is returned */
123 t = lex->value.string;
130 /* TODO: \uXXXX not supported yet */
131 free(lex->value.string);
132 lex->value.string = NULL;
136 case '"': case '\\': case '/':
138 case 'b': *t = '\b'; break;
139 case 'f': *t = '\f'; break;
140 case 'n': *t = '\n'; break;
141 case 'r': *t = '\r'; break;
142 case 't': *t = '\t'; break;
157 lex->token = JSON_TOKEN_STRING;
163 static void json_scan_number(json_lex *lex)
165 const char *p = lex->input;
168 lex->token = JSON_TOKEN_INVALID;
178 else /* *p != '0' */ {
184 if(*p != '.' && *p != 'E' && *p != 'e') {
185 lex->token = JSON_TOKEN_INTEGER;
187 lex->value.integer = strtol(lex->start, &end, 10);
203 if(*p == 'E' || *p == 'e') {
205 if(*p == '+' || *p == '-')
216 lex->token = JSON_TOKEN_REAL;
218 lex->value.real = strtod(lex->start, &end);
225 static int json_lex_scan(json_lex *lex)
229 if(lex->token == JSON_TOKEN_STRING) {
230 free(lex->value.string);
231 lex->value.string = NULL;
235 while(c == ' ' || c == '\t' || c == '\n' || c == '\r')
244 lex->start = lex->input;
248 lex->token = JSON_TOKEN_EOF;
250 else if(c == '{' || c == '}' || c == '[' || c == ']' ||
251 c == ':' || c == ',')
258 json_scan_string(lex);
260 else if(isdigit(c) || c == '-')
261 json_scan_number(lex);
263 else if(isupper(c) || islower(c)) {
264 /* eat up the whole identifier for clearer error messages */
267 while(isupper(*lex->input) || islower(*lex->input))
269 len = lex->input - lex->start;
271 if(strncmp(lex->start, "true", len) == 0)
272 lex->token = JSON_TOKEN_TRUE;
273 else if(strncmp(lex->start, "false", len) == 0)
274 lex->token = JSON_TOKEN_FALSE;
275 else if(strncmp(lex->start, "null", len) == 0)
276 lex->token = JSON_TOKEN_NULL;
278 lex->token = JSON_TOKEN_INVALID;
282 lex->token = JSON_TOKEN_INVALID;
289 static int json_lex_init(json_lex *lex, const char *input)
292 lex->token = JSON_TOKEN_INVALID;
299 static void json_lex_close(json_lex *lex)
301 if(lex->token == JSON_TOKEN_STRING)
302 free(lex->value.string);
308 static json_t *json_parse(json_lex *lex, json_error_t *error);
310 static json_t *json_parse_object(json_lex *lex, json_error_t *error)
312 json_t *object = json_object();
317 if(lex->token == '}')
324 if(lex->token != JSON_TOKEN_STRING) {
325 json_set_error(error, lex, "string expected");
329 key = strdup(lex->value.string);
334 if(lex->token != ':') {
336 json_set_error(error, lex, "':' expected");
342 value = json_parse(lex, error);
348 if(json_object_set(object, key, value)) {
357 if(lex->token != ',')
363 if(lex->token != '}') {
364 json_set_error(error, lex, "'}' expected");
375 static json_t *json_parse_array(json_lex *lex, json_error_t *error)
377 json_t *array = json_array();
382 if(lex->token == ']')
386 json_t *elem = json_parse(lex, error);
390 if(json_array_append(array, elem)) {
396 if(lex->token != ',')
403 if(lex->token != ']') {
404 json_set_error(error, lex, "']' expected");
415 static json_t *json_parse(json_lex *lex, json_error_t *error)
420 case JSON_TOKEN_STRING: {
421 json = json_string(lex->value.string);
425 case JSON_TOKEN_INTEGER: {
426 json = json_integer(lex->value.integer);
430 case JSON_TOKEN_REAL: {
431 json = json_real(lex->value.real);
435 case JSON_TOKEN_TRUE:
439 case JSON_TOKEN_FALSE:
443 case JSON_TOKEN_NULL:
448 json = json_parse_object(lex, error);
452 json = json_parse_array(lex, error);
455 case JSON_TOKEN_INVALID:
456 json_set_error(error, lex, "invalid token");
460 json_set_error(error, lex, "unexpected token");
471 json_t *json_load(const char *path, json_error_t *error)
476 fp = fopen(path, "r");
479 json_set_error(error, NULL, "unable to open %s: %s",
480 path, strerror(errno));
484 result = json_loadf(fp, error);
490 json_t *json_loads(const char *string, json_error_t *error)
493 json_t *result = NULL;
495 if(json_lex_init(&lex, string))
498 if(lex.token != '[' && lex.token != '{') {
499 json_set_error(error, &lex, "'[' or '{' expected");
503 result = json_parse(&lex, error);
507 if(lex.token != JSON_TOKEN_EOF) {
508 json_set_error(error, &lex, "end of file expected");
514 json_lex_close(&lex);
518 #define BUFFER_SIZE 4096
520 json_t *json_loadf(FILE *input, json_error_t *error)
523 char buffer[BUFFER_SIZE];
525 json_t *result = NULL;
527 if(strbuffer_init(&strbuff))
532 length = fread(buffer, 1, BUFFER_SIZE, input);
537 json_set_error(error, NULL, "read error");
542 if(strbuffer_append_bytes(&strbuff, buffer, length))
546 result = json_loads(strbuffer_value(&strbuff), error);
549 strbuffer_close(&strbuff);
553 json_t *json_loadfd(int fd, json_error_t *error)
556 char buffer[BUFFER_SIZE];
558 json_t *result = NULL;
560 if(strbuffer_init(&strbuff))
565 length = read(fd, buffer, BUFFER_SIZE);
568 json_set_error(error, NULL, "read error: %s", strerror(errno));
574 if(strbuffer_append_bytes(&strbuff, buffer, length))
576 json_set_error(error, NULL, "error allocating memory");
581 result = json_loads(strbuffer_value(&strbuff), error);
584 strbuffer_close(&strbuff);