1
0
mirror of https://github.com/falk-werner/webfuse synced 2024-10-27 20:34:10 +00:00
falk-werner_webfuse/lib/webfuse/impl/json/parser.c
2020-07-15 18:55:09 +02:00

288 lines
6.5 KiB
C

#include "webfuse/impl/json/parser.h"
#include "webfuse/impl/json/reader.h"
#include "webfuse/impl/json/node_intern.h"
#include <stdlib.h>
#define WF_JSON_PARSER_INITIAL_CAPACITY 4
static bool
wf_impl_json_parse_null(
struct wf_json_reader * reader,
struct wf_json * json);
static bool
wf_impl_json_parse_true(
struct wf_json_reader * reader,
struct wf_json * json);
static bool
wf_impl_json_parse_false(
struct wf_json_reader * reader,
struct wf_json * json);
static bool
wf_impl_json_parse_int(
struct wf_json_reader * reader,
struct wf_json * json);
static bool
wf_impl_json_parse_string(
struct wf_json_reader * reader,
struct wf_json * json);
static bool
wf_impl_json_parse_array(
struct wf_json_reader * reader,
struct wf_json * json);
static bool
wf_impl_json_parse_object(
struct wf_json_reader * reader,
struct wf_json * json);
// --
bool
wf_impl_json_parse_value(
struct wf_json_reader * reader,
struct wf_json * json)
{
bool result = false;
char const c = wf_impl_json_reader_skip_whitespace(reader);
switch (c)
{
case 'n':
result = wf_impl_json_parse_null(reader, json);
break;
case 't':
result = wf_impl_json_parse_true(reader, json);
break;
case 'f':
result = wf_impl_json_parse_false(reader, json);
break;
case '\"':
result = wf_impl_json_parse_string(reader, json);
break;
case '[':
result = wf_impl_json_parse_array(reader, json);
break;
case '{':
result = wf_impl_json_parse_object(reader, json);
break;
case '-': // fall-through
case '0': // fall-through
case '1': // fall-through
case '2': // fall-through
case '3': // fall-through
case '4': // fall-through
case '5': // fall-through
case '6': // fall-through
case '7': // fall-through
case '8': // fall-through
case '9':
result = wf_impl_json_parse_int(reader, json);
break;
default:
result = false;
break;
}
return result;
}
// --
static bool
wf_impl_json_parse_null(
struct wf_json_reader * reader,
struct wf_json * json)
{
bool const result = wf_impl_json_reader_read_const(reader, "null", 4);
if (result)
{
json->type = WF_JSON_TYPE_NULL;
}
return result;
}
static bool
wf_impl_json_parse_true(
struct wf_json_reader * reader,
struct wf_json * json)
{
bool const result = wf_impl_json_reader_read_const(reader, "true", 4);
if (result)
{
json->type = WF_JSON_TYPE_BOOL;
json->value.b = true;
}
return result;
}
static bool
wf_impl_json_parse_false(
struct wf_json_reader * reader,
struct wf_json * json)
{
bool const result = wf_impl_json_reader_read_const(reader, "false", 5);
if (result)
{
json->type = WF_JSON_TYPE_BOOL;
json->value.b = false;
}
return result;
}
static bool
wf_impl_json_parse_int(
struct wf_json_reader * reader,
struct wf_json * json)
{
int value;
bool const result = wf_impl_json_reader_read_int(reader, &value);
if (result)
{
json->type = WF_JSON_TYPE_INT;
json->value.i = value;
}
return result;
}
static bool
wf_impl_json_parse_string(
struct wf_json_reader * reader,
struct wf_json * json)
{
char * value;
bool const result = wf_impl_json_reader_read_string(reader, &value);
if (result)
{
json->type = WF_JSON_TYPE_STRING;
json->value.s = value;
}
return result;
}
static bool
wf_impl_json_parse_array(
struct wf_json_reader * reader,
struct wf_json * json)
{
wf_impl_json_reader_skip_whitespace(reader);
char c = wf_impl_json_reader_get_char(reader);
if ('[' != c) { return false; }
size_t capacity = WF_JSON_PARSER_INITIAL_CAPACITY;
json->type = WF_JSON_TYPE_ARRAY;
json->value.a.items = malloc(sizeof(struct wf_json) * capacity);
json->value.a.size = 0;
c = wf_impl_json_reader_skip_whitespace(reader);
if (']' == c)
{
wf_impl_json_reader_get_char(reader);
return true;
}
bool result;
do
{
if (json->value.a.size >= capacity)
{
capacity *= 2;
json->value.a.items = realloc(json->value.a.items, sizeof(struct wf_json) * capacity);
}
result = wf_impl_json_parse_value(reader, &(json->value.a.items[json->value.a.size]));
if (result)
{
json->value.a.size++;
wf_impl_json_reader_skip_whitespace(reader);
c = wf_impl_json_reader_get_char(reader);
}
} while ((result) && (',' == c));
if ((result) && (']' != c))
{
result = false;
}
if (!result)
{
wf_impl_json_cleanup(json);
}
return result;
}
static bool
wf_impl_json_parse_object(
struct wf_json_reader * reader,
struct wf_json * json)
{
wf_impl_json_reader_skip_whitespace(reader);
char c = wf_impl_json_reader_get_char(reader);
if ('{' != c) { return false; }
size_t capacity = WF_JSON_PARSER_INITIAL_CAPACITY;
json->type = WF_JSON_TYPE_OBJECT;
json->value.o.items = malloc(sizeof(struct wf_json_object_item) * capacity);
json->value.o.size = 0;
c = wf_impl_json_reader_skip_whitespace(reader);
if ('}' == c)
{
wf_impl_json_reader_get_char(reader);
return true;
}
bool result;
do
{
if (json->value.o.size >= capacity)
{
capacity *= 2;
json->value.o.items = realloc(json->value.o.items, sizeof(struct wf_json_object_item) * capacity);
}
struct wf_json_object_item * item = &(json->value.o.items[json->value.o.size]);
result = wf_impl_json_reader_read_string(reader, &(item->key));
if (result)
{
wf_impl_json_reader_skip_whitespace(reader);
result = (':' == wf_impl_json_reader_get_char(reader));
}
if (result)
{
result = wf_impl_json_parse_value(reader, &(item->json));
}
if (result)
{
json->value.o.size++;
wf_impl_json_reader_skip_whitespace(reader);
c = wf_impl_json_reader_get_char(reader);
}
} while ((reader) && (',' == c));
if ((reader) && ('}' != c))
{
result = false;
}
if (!result)
{
wf_impl_json_cleanup(json);
}
return result;
}