1
0
mirror of https://github.com/falk-werner/webfuse-provider synced 2026-03-02 04:09:18 +00:00

added implementation of json_writer

This commit is contained in:
Falk Werner
2020-07-09 22:12:13 +02:00
parent c6c9edcd81
commit c9f086f6cf
8 changed files with 523 additions and 56 deletions

View File

@@ -1,17 +1,25 @@
#include "webfuse_provider/impl/json/writer.h"
#include "webfuse_provider/impl/util/base64.h"
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <limits.h>
#define WFP_JSON_WRITER_MAX_LEVEL 8
#define WFP_JSON_WRITER_MAX_LEVEL 7
#define WFP_INT_BUFFER_SIZE 64
enum wfp_json_writer_state
{
WFP_JSON_WRITER_STATE_INIT
WFP_JSON_WRITER_STATE_INIT,
WFP_JSON_WRITER_STATE_ARRAY_FIRST,
WFP_JSON_WRITER_STATE_ARRAY_NEXT,
WFP_JSON_WRITER_STATE_OBJECT_FIRST,
WFP_JSON_WRITER_STATE_OBJECT_NEXT
};
struct wfp_json_writer
{
enum wfp_json_writer_state state[WFP_JSON_WRITER_MAX_LEVEL];
enum wfp_json_writer_state state[WFP_JSON_WRITER_MAX_LEVEL + 1];
size_t level;
size_t capacity;
size_t pre;
@@ -20,6 +28,34 @@ struct wfp_json_writer
char * raw_data;
};
static char
wfp_impl_json_writer_get_esc(
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:
// error
return '/';
}
}
static void
wfp_impl_json_writer_write_raw_char(
struct wfp_json_writer * writer,
char value)
{
writer->data[writer->offset++] = value;
}
static void
wfp_impl_json_writer_reserve(
struct wfp_json_writer * writer,
@@ -40,13 +76,47 @@ wfp_impl_json_writer_reserve(
}
}
void
wfp_impl_json_writer_write_raw_char(
struct wfp_json_writer * writer,
char value)
static void
wfp_impl_json_writer_begin_value(
struct wfp_json_writer * writer)
{
writer->data[writer->offset] = value;
writer->offset++;
wfp_impl_json_writer_reserve(writer, 1);
if (writer->state[writer->level] == WFP_JSON_WRITER_STATE_ARRAY_NEXT)
{
wfp_impl_json_writer_write_raw_char(writer, ',');
}
}
static void
wfp_impl_json_writer_end_value(
struct wfp_json_writer * writer)
{
if (WFP_JSON_WRITER_STATE_ARRAY_FIRST == writer->state[writer->level])
{
writer->state[writer->level] = WFP_JSON_WRITER_STATE_ARRAY_NEXT;
}
}
static void
wfp_impl_json_writer_push(
struct wfp_json_writer * writer,
enum wfp_json_writer_state state)
{
if (writer->level < WFP_JSON_WRITER_MAX_LEVEL)
{
writer->level++;
writer->state[writer->level] = state;
}
}
static void
wfp_impl_json_writer_pop(
struct wfp_json_writer * writer)
{
if (writer->level > 0)
{
writer->level--;
}
}
void
@@ -84,9 +154,20 @@ wfp_impl_json_writer_dispose(
free(writer);
}
void
wfp_impl_json_writer_reset(
struct wfp_json_writer * writer)
{
writer->level = 0;
writer->state[writer->level] = WFP_JSON_WRITER_STATE_INIT;
writer->offset = 0;
}
char *
wfp_impl_json_writer_take_data(
struct wfp_json_writer * writer)
struct wfp_json_writer * writer,
size_t * size)
{
wfp_impl_json_writer_reserve(writer, 1);
writer->data[writer->offset] = '\0';
@@ -94,6 +175,11 @@ wfp_impl_json_writer_take_data(
char * result = writer->raw_data;
writer->raw_data = NULL;
if (NULL != size)
{
*size = writer->offset;
}
return result;
}
@@ -102,7 +188,41 @@ wfp_impl_json_writer_write_int(
struct wfp_json_writer * writer,
int value)
{
wfp_impl_json_writer_begin_value(writer);
wfp_impl_json_writer_reserve(writer, WFP_INT_BUFFER_SIZE);
bool const is_signed = (0 > value);
char buffer[WFP_INT_BUFFER_SIZE];
size_t offset = WFP_INT_BUFFER_SIZE;
buffer[--offset] = '\0';
if (is_signed)
{
if (INT_MIN == value)
{
char const actual = (char) abs(value % 10);
buffer[--offset] = (char) ('0' + actual);
value /= 10;
}
value = -value;
}
do
{
char const actual = (char) (value % 10);
buffer[--offset] = ('0' + actual);
value /= 10;
}
while (0 != value);
if (is_signed)
{
buffer[--offset] = '-';
}
size_t const length = (WFP_INT_BUFFER_SIZE - offset - 1);
wfp_impl_json_writer_write_raw(writer, &(buffer[offset]), length);
wfp_impl_json_writer_end_value(writer);
}
void
@@ -110,6 +230,41 @@ wfp_impl_json_writer_write_string(
struct wfp_json_writer * writer,
char const * value)
{
wfp_impl_json_writer_begin_value(writer);
size_t length = strlen(value);
wfp_impl_json_writer_reserve(writer, length + 2);
wfp_impl_json_writer_write_raw_char(writer, '\"');
for(size_t i = 0; i < length; i++)
{
char c = value[i];
if ((' ' <= c) && (c != '\\') && (c != '\"'))
{
wfp_impl_json_writer_write_raw_char(writer, c);
}
else
{
char esc = wfp_impl_json_writer_get_esc(c);
wfp_impl_json_writer_reserve(writer, (length - i) + 2);
wfp_impl_json_writer_write_raw_char(writer, '\\');
wfp_impl_json_writer_write_raw_char(writer, esc);
}
}
wfp_impl_json_writer_write_raw_char(writer, '\"');
wfp_impl_json_writer_end_value(writer);
}
void
wfp_impl_json_writer_write_string_nocheck(
struct wfp_json_writer * writer,
char const * value)
{
wfp_impl_json_writer_begin_value(writer);
size_t length = strlen(value);
wfp_impl_json_writer_reserve(writer, length + 2);
@@ -117,6 +272,7 @@ wfp_impl_json_writer_write_string(
wfp_impl_json_writer_write_raw(writer, value, length);
wfp_impl_json_writer_write_raw_char(writer, '\"');
wfp_impl_json_writer_end_value(writer);
}
void
@@ -125,14 +281,27 @@ wfp_impl_json_writer_write_bytes(
char const * data,
size_t length)
{
wfp_impl_json_writer_begin_value(writer);
size_t encoded_length = wfp_impl_base64_encoded_size(length);
wfp_impl_json_writer_reserve(writer, encoded_length + 2);
wfp_impl_json_writer_write_raw_char(writer, '\"');
wfp_impl_base64_encode((uint8_t const*) data, length, &(writer->data[writer->offset]), encoded_length);
writer->offset += encoded_length;
wfp_impl_json_writer_write_raw_char(writer, '\"');
wfp_impl_json_writer_end_value(writer);
}
void
wfp_impl_json_writer_object_begin(
struct wfp_json_writer * writer)
{
wfp_impl_json_writer_begin_value(writer);
wfp_impl_json_writer_reserve(writer, 1);
wfp_impl_json_writer_push(writer, WFP_JSON_WRITER_STATE_OBJECT_FIRST);
wfp_impl_json_writer_write_raw_char(writer, '{');
}
@@ -142,6 +311,9 @@ wfp_impl_json_writer_object_end(
{
wfp_impl_json_writer_reserve(writer, 1);
wfp_impl_json_writer_write_raw_char(writer, '}');
wfp_impl_json_writer_pop(writer);
wfp_impl_json_writer_end_value(writer);
}
void
@@ -150,13 +322,32 @@ wfp_impl_json_writer_object_key(
char const * key)
{
wfp_impl_json_writer_reserve(writer, 1);
wfp_impl_json_writer_write_raw_char(writer, '[');
size_t length = strlen(key);
wfp_impl_json_writer_reserve(writer, length + 4);
if (WFP_JSON_WRITER_STATE_OBJECT_NEXT == writer->state[writer->level])
{
wfp_impl_json_writer_write_raw_char(writer, ',');
}
else
{
writer->state[writer->level] = WFP_JSON_WRITER_STATE_OBJECT_NEXT;
}
wfp_impl_json_writer_write_raw_char(writer, '\"');
wfp_impl_json_writer_write_raw(writer, key, length);
wfp_impl_json_writer_write_raw_char(writer, '\"');
wfp_impl_json_writer_write_raw_char(writer, ':');
}
void
wfp_impl_json_writer_array_begin(
struct wfp_json_writer * writer)
{
wfp_impl_json_writer_begin_value(writer);
wfp_impl_json_writer_push(writer, WFP_JSON_WRITER_STATE_ARRAY_FIRST);
wfp_impl_json_writer_reserve(writer, 1);
wfp_impl_json_writer_write_raw_char(writer, '[');
}
@@ -167,4 +358,7 @@ wfp_impl_json_writer_array_end(
{
wfp_impl_json_writer_reserve(writer, 1);
wfp_impl_json_writer_write_raw_char(writer, ']');
wfp_impl_json_writer_pop(writer);
wfp_impl_json_writer_end_value(writer);
}

View File

@@ -4,7 +4,7 @@
#ifndef __cplusplus
#include <stddef.h>
#else
#include <cstddef.h>
#include <cstddef>
#endif
#ifdef __cplusplus
@@ -23,9 +23,14 @@ extern void
wfp_impl_json_writer_dispose(
struct wfp_json_writer * writer);
extern void
wfp_impl_json_writer_reset(
struct wfp_json_writer * writer);
extern char *
wfp_impl_json_writer_take_data(
struct wfp_json_writer * writer);
struct wfp_json_writer * writer,
size_t * size);
extern void
wfp_impl_json_writer_write_int(
@@ -37,6 +42,11 @@ wfp_impl_json_writer_write_string(
struct wfp_json_writer * writer,
char const * value);
extern void
wfp_impl_json_writer_write_string_nocheck(
struct wfp_json_writer * writer,
char const * value);
extern void
wfp_impl_json_writer_write_bytes(
struct wfp_json_writer * writer,