1
0
mirror of https://github.com/falk-werner/webfuse synced 2024-10-27 20:34:10 +00:00

added implementation of json parser

This commit is contained in:
Falk Werner 2020-07-14 21:46:01 +02:00
parent 547cd0d7a6
commit 6c5ff67720
10 changed files with 919 additions and 0 deletions

View File

@ -0,0 +1,44 @@
#include "webfuse/impl/json/doc.h"
#include "webfuse/impl/json/node_intern.h"
#include "webfuse/impl/json/reader.h"
#include "webfuse/impl/json/parser.h"
#include <stdlib.h>
struct wf_json_doc
{
struct wf_json root;
};
struct wf_json_doc *
wf_impl_json_doc_loadb(
char * data,
size_t length)
{
struct wf_json_reader reader;
wf_impl_json_reader_init(&reader, data, length);
struct wf_json_doc * doc = malloc(sizeof(struct wf_json_doc));
if (!wf_impl_json_parse_value(&reader, &doc->root))
{
free(doc);
doc = NULL;
}
return doc;
}
void
wf_impl_json_doc_dispose(
struct wf_json_doc * doc)
{
wf_impl_json_cleanup(&doc->root);
free(doc);
}
struct wf_json const *
wf_impl_jsoc_doc_root(
struct wf_json_doc * doc)
{
return &doc->root;
}

View File

@ -0,0 +1,36 @@
#ifndef WF_IMPL_JSON_DOC_H
#define WF_IMPL_JSON_DOC_H
#ifndef __cplusplus
#include <stddef.h>
#else
#include <cstddef>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
struct wf_json_doc;
struct wf_json;
extern struct wf_json_doc *
wf_impl_json_doc_loadb(
char * data,
size_t length);
extern void
wf_impl_json_doc_dispose(
struct wf_json_doc * doc);
extern struct wf_json const *
wf_impl_jsoc_doc_root(
struct wf_json_doc * doc);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,147 @@
#include "webfuse/impl/json/node_intern.h"
#include <stdlib.h>
#include <string.h>
static struct wf_json const wf_json_undefined =
{
.type = WF_JSON_TYPE_UNDEFINED,
.value = { .b = false }
};
enum wf_json_type
wf_impl_json_type(
struct wf_json const * json)
{
return json->type;
}
bool
wf_impl_json_bool_get(
struct wf_json const * json)
{
return (WF_JSON_TYPE_BOOL == json->type) ? json->value.b : false;
}
int
wf_impl_json_int_get(
struct wf_json const * json)
{
return (WF_JSON_TYPE_INT == json->type) ? json->value.i : 0;
}
char const *
wf_impl_json_string_get(
struct wf_json const * json)
{
return (WF_JSON_TYPE_STRING == json->type) ? json->value.s : "";
}
struct wf_json const *
wf_impl_json_array_get(
struct wf_json const * json,
size_t pos)
{
struct wf_json const * result = &wf_json_undefined;
if ((WF_JSON_TYPE_ARRAY == json->type) && (pos < json->value.a.size))
{
result = &(json->value.a.items[pos]);
}
return result;
}
size_t
wf_impl_json_array_size(
struct wf_json const * json)
{
return (WF_JSON_TYPE_ARRAY == json->type) ? json->value.a.size : 0;
}
struct wf_json const *
wf_impl_json_object_get(
struct wf_json const * json,
char const * key)
{
if (WF_JSON_TYPE_OBJECT == json->type)
{
size_t const count = json->value.o.size;
for(size_t i = 0; i < count; i++)
{
struct wf_json_object_item * actual = &(json->value.o.items[i]);
if (0 == strcmp(key, actual->key))
{
return &(actual->json);
}
}
}
return &wf_json_undefined;
}
size_t
wf_impl_json_object_size(
struct wf_json const * json)
{
return (WF_JSON_TYPE_OBJECT == json->type) ? json->value.o.size : 0;
}
char const *
wf_impl_json_object_key(
struct wf_json const * json,
size_t pos)
{
char const * result = "";
if ((WF_JSON_TYPE_OBJECT == json->type) && (pos < json->value.o.size))
{
result = json->value.o.items[pos].key;
}
return result;
}
struct wf_json const *
wf_impl_json_object_value(
struct wf_json const * json,
size_t pos)
{
struct wf_json const * result = &wf_json_undefined;
if ((WF_JSON_TYPE_OBJECT == json->type) && (pos < json->value.o.size))
{
result = &(json->value.o.items[pos].json);
}
return result;
}
void
wf_impl_json_cleanup(
struct wf_json * json)
{
switch (json->type)
{
case WF_JSON_TYPE_ARRAY:
{
size_t const count = json->value.a.size;
for(size_t i = 0; i < count; i++)
{
struct wf_json * actual = &(json->value.a.items[i]);
wf_impl_json_cleanup(actual);
}
}
break;
case WF_JSON_TYPE_OBJECT:
{
size_t const count = json->value.o.size;
for(size_t i = 0; i < count; i++)
{
struct wf_json * actual = &(json->value.o.items[i].json);
wf_impl_json_cleanup(actual);
}
}
break;
default:
break;
}
}

View File

@ -0,0 +1,77 @@
#ifndef WF_IMPL_JSON_NODE_H
#define WF_IMPL_JSON_NODE_H
#ifndef __cplusplus
#include <stdbool.h>
#include <stddef.h>
#else
#include <cstddef>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
enum wf_json_type
{
WF_JSON_TYPE_UNDEFINED,
WF_JSON_TYPE_NULL,
WF_JSON_TYPE_BOOL,
WF_JSON_TYPE_INT,
WF_JSON_TYPE_STRING,
WF_JSON_TYPE_ARRAY,
WF_JSON_TYPE_OBJECT
};
struct wf_json;
extern enum wf_json_type
wf_impl_json_type(
struct wf_json const * json);
extern bool
wf_impl_json_bool_get(
struct wf_json const * json);
extern int
wf_impl_json_int_get(
struct wf_json const * json);
extern char const *
wf_impl_json_string_get(
struct wf_json const * json);
extern struct wf_json const *
wf_impl_json_array_get(
struct wf_json const * json,
size_t pos);
extern size_t
wf_impl_json_array_size(
struct wf_json const * json);
extern struct wf_json const *
wf_impl_json_object_get(
struct wf_json const * json,
char const * key);
extern size_t
wf_impl_json_object_size(
struct wf_json const * json);
extern char const *
wf_impl_json_object_key(
struct wf_json const * json,
size_t pos);
extern struct wf_json const *
wf_impl_json_object_value(
struct wf_json const * json,
size_t pos);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,54 @@
#ifndef WF_IMPL_JSON_NODE_INTERN_H
#define WF_IMPL_JSON_NODE_INTERN_H
#include "webfuse/impl/json/node.h"
#ifdef __cplusplus
extern "C"
{
#endif
struct wf_json_array
{
struct wf_json * items;
size_t size;
};
struct wf_json_object_item;
struct wf_json_object
{
struct wf_json_object_item * items;
size_t size;
};
union wf_json_value
{
bool b;
int i;
char * s;
struct wf_json_array a;
struct wf_json_object o;
};
struct wf_json
{
enum wf_json_type type;
union wf_json_value value;
};
struct wf_json_object_item
{
struct wf_json json;
char * key;
};
extern void
wf_impl_json_cleanup(
struct wf_json * json);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,288 @@
#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;
}

View File

@ -0,0 +1,25 @@
#ifndef WF_IMPL_JSON_PARSER_H
#define WF_IMPL_JSON_PARSER_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
struct wf_json_reader;
struct wf_json;
extern bool
wf_impl_json_parse_value(
struct wf_json_reader * reader,
struct wf_json * json);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,179 @@
#include "webfuse/impl/json/reader.h"
#include <string.h>
static char
wf_impl_json_unescape(
char c);
void
wf_impl_json_reader_init(
struct wf_json_reader * reader,
char * contents,
size_t length)
{
reader->contents = contents;
reader->length = length;
reader->pos = 0;
}
char
wf_impl_json_reader_skip_whitespace(
struct wf_json_reader * reader)
{
char c = wf_impl_json_reader_peek(reader);
if ((' ' == c) || ('\n' == c) || ('\t' == c) || ('\r' == c))
{
reader->pos++;
c = wf_impl_json_reader_peek(reader);
}
return c;
}
char
wf_impl_json_reader_peek(
struct wf_json_reader * reader)
{
char result = '\0';
if (reader->pos < reader->length)
{
result = reader->contents[reader->pos];
}
return result;
}
char
wf_impl_json_reader_get_char(
struct wf_json_reader * reader)
{
char result = '\0';
if (reader->pos < reader->length)
{
result = reader->contents[reader->pos++];
}
return result;
}
void
wf_impl_json_reader_unget_char(
struct wf_json_reader * reader)
{
if (0 < reader->pos)
{
reader->pos--;
}
}
bool
wf_impl_json_reader_read_const(
struct wf_json_reader * reader,
char const * value,
size_t length)
{
size_t remaining = reader->length - reader->pos;
bool const result = ((remaining >= length) && (0 == strncmp((&reader->contents[reader->pos]), value, length)));
if (result)
{
reader->pos += length;
}
return result;
}
bool
wf_impl_json_reader_read_int(
struct wf_json_reader * reader,
int * value)
{
char c = wf_impl_json_reader_get_char(reader);
bool const is_signed = ('-' == c);
if (is_signed)
{
c = wf_impl_json_reader_get_char(reader);
}
bool const result = (('0' <= c) && (c <= '9'));
if (result)
{
int v = c - '0';
c = wf_impl_json_reader_peek(reader);
while (('0' <= c) && (c <= '9'))
{
v *= 10;
v += c - '0';
reader->pos++;
c = wf_impl_json_reader_peek(reader);
}
*value = (is_signed) ? -v : v;
}
return result;
}
bool
wf_impl_json_reader_read_string(
struct wf_json_reader * reader,
char * * value)
{
wf_impl_json_reader_skip_whitespace(reader);
char c = wf_impl_json_reader_get_char(reader);
if ('\"' == c) { return value; }
size_t p = reader->pos;
*value = &(reader->contents[p]);
c = wf_impl_json_reader_get_char(reader);
while (('\"' != c) && ('\"' != c))
{
if ('\\' != c)
{
reader->contents[p++] = c;
}
else
{
char unescaped = wf_impl_json_unescape(wf_impl_json_reader_get_char(reader));
if ('\0' != c)
{
reader->contents[p++] = unescaped;
}
else
{
*value = NULL;
return false;
}
}
c = wf_impl_json_reader_get_char(reader);
}
bool const result = ('\"' == c);
if (result)
{
reader->contents[p] = '\0';
}
return result;
}
static char
wf_impl_json_unescape(
char c)
{
switch (c)
{
case '\"': return '\"';
case '\\': return '\\';
case '/': return '/';
case 'b': return '\b';
case 'f': return '\f';
case 'n': return '\n';
case 'r': return '\r';
case 't': return '\t';
default:
return '\0';
}
}

View File

@ -0,0 +1,65 @@
#ifndef WF_IMPL_JSON_READER_H
#define WF_IMPL_JSON_READER_H
#ifndef __cplusplus
#include <stddef.h>
#include <stdbool.h>
#else
#include <cstddef>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
struct wf_json_reader
{
char * contents;
size_t length;
size_t pos;
};
extern void
wf_impl_json_reader_init(
struct wf_json_reader * reader,
char * contents,
size_t length);
extern char
wf_impl_json_reader_skip_whitespace(
struct wf_json_reader * reader);
extern char
wf_impl_json_reader_peek(
struct wf_json_reader * reader);
extern char
wf_impl_json_reader_get_char(
struct wf_json_reader * reader);
extern void
wf_impl_json_reader_unget_char(
struct wf_json_reader * reader);
extern bool
wf_impl_json_reader_read_const(
struct wf_json_reader * reader,
char const * value,
size_t length);
extern bool
wf_impl_json_reader_read_int(
struct wf_json_reader * reader,
int * value);
extern bool
wf_impl_json_reader_read_string(
struct wf_json_reader * reader,
char * * value);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -29,6 +29,10 @@ webfuse_static = static_library('webfuse',
'lib/webfuse/impl/timer/timepoint.c',
'lib/webfuse/impl/timer/timer.c',
'lib/webfuse/impl/json/writer.c',
'lib/webfuse/impl/json/node.c',
'lib/webfuse/impl/json/doc.c',
'lib/webfuse/impl/json/reader.c',
'lib/webfuse/impl/json/parser.c',
'lib/webfuse/impl/jsonrpc/proxy.c',
'lib/webfuse/impl/jsonrpc/proxy_request_manager.c',
'lib/webfuse/impl/jsonrpc/proxy_variadic.c',