mirror of
https://github.com/falk-werner/webfuse-provider
synced 2024-10-27 20:44:10 +00:00
added implementation of json parser
This commit is contained in:
parent
7542f0bbc0
commit
63ca5d5a6d
167
lib/webfuse_provider/impl/json/node.c
Normal file
167
lib/webfuse_provider/impl/json/node.c
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include "webfuse_provider/impl/json/node.h"
|
||||||
|
#include "webfuse_provider/impl/json/node_intern.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
bool
|
||||||
|
wfp_impl_json_is_bool(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_BOOL == json->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
wfp_impl_json_is_int(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_INT == json->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
wfp_impl_json_is_string(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_STRING == json->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
wfp_impl_json_is_array(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_ARRAY == json->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
wfp_impl_json_is_object(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_OBJECT == json->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
wfp_impl_json_get_bool(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_BOOL == json->type) ? json->value.b : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wfp_impl_json_get_int(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_INT == json->type) ? json->value.i : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
wfp_impl_json_get_string(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_STRING == json->type) ? json->value.s : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wfp_json const *
|
||||||
|
wfp_impl_json_array_get(
|
||||||
|
struct wfp_json const * json,
|
||||||
|
size_t pos)
|
||||||
|
{
|
||||||
|
struct wfp_json const * result = NULL;
|
||||||
|
if ((WFP_JSON_ARRAY == json->type) && (pos < json->value.a.size))
|
||||||
|
{
|
||||||
|
return &(json->value.a.items[pos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
wfp_impl_json_array_size(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_ARRAY == json->type) ? json->value.a.size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
wfp_impl_json_object_size(
|
||||||
|
struct wfp_json const * json)
|
||||||
|
{
|
||||||
|
return (WFP_JSON_OBJECT == json->type) ? json->value.o.size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wfp_json const *
|
||||||
|
wfp_impl_json_object_get(
|
||||||
|
struct wfp_json const * json,
|
||||||
|
char const * key)
|
||||||
|
{
|
||||||
|
size_t const count = wfp_impl_json_object_size(json);
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (0 == strcmp(key, json->value.o.items[i].key))
|
||||||
|
{
|
||||||
|
return &(json->value.o.items[i].json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *
|
||||||
|
wfp_impl_json_object_key(
|
||||||
|
struct wfp_json const * json,
|
||||||
|
size_t pos)
|
||||||
|
{
|
||||||
|
size_t const count = wfp_impl_json_object_size(json);
|
||||||
|
if (pos < count)
|
||||||
|
{
|
||||||
|
return json->value.o.items[pos].key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wfp_json const *
|
||||||
|
wfp_impl_json_object_value(
|
||||||
|
struct wfp_json const * json,
|
||||||
|
size_t pos)
|
||||||
|
{
|
||||||
|
size_t const count = wfp_impl_json_object_size(json);
|
||||||
|
if (pos < count)
|
||||||
|
{
|
||||||
|
return &(json->value.o.items[pos].json);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wfp_impl_json_cleanup(
|
||||||
|
struct wfp_json * json)
|
||||||
|
{
|
||||||
|
switch (json->type)
|
||||||
|
{
|
||||||
|
case WFP_JSON_ARRAY:
|
||||||
|
{
|
||||||
|
size_t const count = json->value.a.size;
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
wfp_impl_json_cleanup(&(json->value.a.items[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(json->value.a.items);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WFP_JSON_OBJECT:
|
||||||
|
{
|
||||||
|
size_t const count = json->value.o.size;
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
wfp_impl_json_cleanup(&(json->value.o.items[i].json));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(json->value.o.items);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
83
lib/webfuse_provider/impl/json/node.h
Normal file
83
lib/webfuse_provider/impl/json/node.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#ifndef WFP_IMPL_JSON_NODE_H
|
||||||
|
#define WFP_IMPL_JSON_NODE_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#else
|
||||||
|
#include <cstddef>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct wfp_json;
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_is_bool(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_is_int(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_is_string(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_is_array(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_is_object(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_get_bool(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
wfp_impl_json_get_int(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern const char *
|
||||||
|
wfp_impl_json_get_string(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern struct wfp_json const *
|
||||||
|
wfp_impl_json_array_get(
|
||||||
|
struct wfp_json const * json,
|
||||||
|
size_t pos);
|
||||||
|
|
||||||
|
extern size_t
|
||||||
|
wfp_impl_json_array_size(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern size_t
|
||||||
|
wfp_impl_json_object_size(
|
||||||
|
struct wfp_json const * json);
|
||||||
|
|
||||||
|
extern struct wfp_json const *
|
||||||
|
wfp_impl_json_object_get(
|
||||||
|
struct wfp_json const * json,
|
||||||
|
char const * key);
|
||||||
|
|
||||||
|
extern char const *
|
||||||
|
wfp_impl_json_object_key(
|
||||||
|
struct wfp_json const * json,
|
||||||
|
size_t pos);
|
||||||
|
|
||||||
|
extern struct wfp_json const *
|
||||||
|
wfp_impl_json_object_value(
|
||||||
|
struct wfp_json const * json,
|
||||||
|
size_t pos);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
75
lib/webfuse_provider/impl/json/node_intern.h
Normal file
75
lib/webfuse_provider/impl/json/node_intern.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef WFP_IMPL_JSON_NODE_INTERN_H
|
||||||
|
#define WFP_IMPL_JSON_NODE_INTERN_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#else
|
||||||
|
#include <cstddef>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum wfp_json_type
|
||||||
|
{
|
||||||
|
WFP_JSON_BOOL,
|
||||||
|
WFP_JSON_INT,
|
||||||
|
WFP_JSON_STRING,
|
||||||
|
WFP_JSON_ARRAY,
|
||||||
|
WFP_JSON_OBJECT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wfp_json_object_item;
|
||||||
|
|
||||||
|
struct wfp_json_array
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
struct wfp_json * items;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wfp_json_object
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
struct wfp_json_object_item * items;
|
||||||
|
};
|
||||||
|
|
||||||
|
union wfp_json_value
|
||||||
|
{
|
||||||
|
bool b;
|
||||||
|
int i;
|
||||||
|
char * s;
|
||||||
|
struct wfp_json_array a;
|
||||||
|
struct wfp_json_object o;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wfp_json
|
||||||
|
{
|
||||||
|
enum wfp_json_type type;
|
||||||
|
union wfp_json_value value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct wfp_json_object_item
|
||||||
|
{
|
||||||
|
struct wfp_json json;
|
||||||
|
char * key;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void
|
||||||
|
wfp_impl_json_cleanup(
|
||||||
|
struct wfp_json * json);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
275
lib/webfuse_provider/impl/json/parser.c
Normal file
275
lib/webfuse_provider/impl/json/parser.c
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
#include "webfuse_provider/impl/json/parser.h"
|
||||||
|
#include "webfuse_provider/impl/json/node_intern.h"
|
||||||
|
#include "webfuse_provider/impl/json/reader.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define WFP_IMPL_JSON_DEFAULT_CAPACITY 4
|
||||||
|
|
||||||
|
struct wfp_json_doc
|
||||||
|
{
|
||||||
|
struct wfp_json root;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_value(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_true(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_false(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json);
|
||||||
|
|
||||||
|
static void
|
||||||
|
wfp_impl_json_parse_int(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char first,
|
||||||
|
struct wfp_json * json);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_string(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_array(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_object(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json);
|
||||||
|
|
||||||
|
struct wfp_json_doc *
|
||||||
|
wfp_impl_json_parse_buffer(
|
||||||
|
char * data,
|
||||||
|
size_t length)
|
||||||
|
{
|
||||||
|
struct wfp_json_reader reader;
|
||||||
|
wfp_impl_json_reader_init(&reader, data, length);
|
||||||
|
|
||||||
|
struct wfp_json_doc * doc = malloc(sizeof(struct wfp_json_doc));
|
||||||
|
if (!wfp_impl_json_parse_value(&reader, &doc->root))
|
||||||
|
{
|
||||||
|
free(doc);
|
||||||
|
doc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wfp_impl_json_dispose(
|
||||||
|
struct wfp_json_doc * doc)
|
||||||
|
{
|
||||||
|
wfp_impl_json_cleanup(&doc->root);
|
||||||
|
free(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wfp_json const *
|
||||||
|
wfp_impl_json_root(
|
||||||
|
struct wfp_json_doc * doc)
|
||||||
|
{
|
||||||
|
return &(doc->root);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_value(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json)
|
||||||
|
{
|
||||||
|
wfp_impl_json_reader_skip_whitespace(reader);
|
||||||
|
char c = wfp_impl_json_reader_read_char(reader);
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 't':
|
||||||
|
return wfp_impl_json_parse_true(reader, json);
|
||||||
|
case 'f':
|
||||||
|
return wfp_impl_json_parse_false(reader, json);
|
||||||
|
case '\"':
|
||||||
|
wfp_impl_json_reader_unget_char(reader);
|
||||||
|
return wfp_impl_json_parse_string(reader, json);
|
||||||
|
case '{':
|
||||||
|
return wfp_impl_json_parse_object(reader, json);
|
||||||
|
case '[':
|
||||||
|
return wfp_impl_json_parse_array(reader, json);
|
||||||
|
default:
|
||||||
|
if ((('0' <= c) && (c <= '9')) || ('-' == c))
|
||||||
|
{
|
||||||
|
wfp_impl_json_parse_int(reader, c, json);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_true(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json)
|
||||||
|
{
|
||||||
|
bool const result = wfp_impl_json_reader_read_const(reader, "rue", 3);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
json->type = WFP_JSON_BOOL;
|
||||||
|
json->value.b = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_false(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json)
|
||||||
|
{
|
||||||
|
bool const result = wfp_impl_json_reader_read_const(reader, "alse", 4);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
json->type = WFP_JSON_BOOL;
|
||||||
|
json->value.b = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wfp_impl_json_parse_int(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char first,
|
||||||
|
struct wfp_json * json)
|
||||||
|
{
|
||||||
|
json->type = WFP_JSON_INT;
|
||||||
|
json->value.i = wfp_impl_json_reader_read_int(reader, first);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_string(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json)
|
||||||
|
{
|
||||||
|
json->type = WFP_JSON_STRING;
|
||||||
|
return wfp_impl_json_reader_read_string(reader, &json->value.s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_array(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json)
|
||||||
|
{
|
||||||
|
size_t capacity = WFP_IMPL_JSON_DEFAULT_CAPACITY;
|
||||||
|
json->type = WFP_JSON_ARRAY;
|
||||||
|
json->value.a.size = 0;
|
||||||
|
json->value.a.items = malloc(sizeof(struct wfp_json) * capacity);
|
||||||
|
|
||||||
|
wfp_impl_json_reader_skip_whitespace(reader);
|
||||||
|
char c = wfp_impl_json_reader_peek(reader);
|
||||||
|
if (']' == c)
|
||||||
|
{
|
||||||
|
wfp_impl_json_reader_read_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 wfp_json) * capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = wfp_impl_json_parse_value(reader, &(json->value.a.items[json->value.a.size]));
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
json->value.a.size++;
|
||||||
|
wfp_impl_json_reader_skip_whitespace(reader);
|
||||||
|
c = wfp_impl_json_reader_read_char(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while ((result) && (',' == c));
|
||||||
|
|
||||||
|
if ((result) && (']' != c))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
wfp_impl_json_cleanup(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wfp_impl_json_parse_object(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
struct wfp_json * json)
|
||||||
|
{
|
||||||
|
size_t capacity = WFP_IMPL_JSON_DEFAULT_CAPACITY;
|
||||||
|
json->type = WFP_JSON_OBJECT;
|
||||||
|
json->value.o.size = 0;
|
||||||
|
json->value.o.items = malloc(sizeof(struct wfp_json_object_item) * capacity);
|
||||||
|
|
||||||
|
wfp_impl_json_reader_skip_whitespace(reader);
|
||||||
|
char c = wfp_impl_json_reader_peek(reader);
|
||||||
|
if ('}' == c)
|
||||||
|
{
|
||||||
|
wfp_impl_json_reader_read_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 wfp_json_object_item) * capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wfp_json_object_item * item = &(json->value.o.items[json->value.o.size]);
|
||||||
|
result = wfp_impl_json_reader_read_string(reader, &(item->key));
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
wfp_impl_json_reader_skip_whitespace(reader);
|
||||||
|
result = (':' == wfp_impl_json_reader_read_char(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
result = wfp_impl_json_parse_value(reader, &(item->json));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
json->value.o.size++;
|
||||||
|
wfp_impl_json_reader_skip_whitespace(reader);
|
||||||
|
c = wfp_impl_json_reader_read_char(reader);
|
||||||
|
}
|
||||||
|
} while ((result) && (',' == c));
|
||||||
|
|
||||||
|
if ((result) && ('}' != c))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
wfp_impl_json_cleanup(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
35
lib/webfuse_provider/impl/json/parser.h
Normal file
35
lib/webfuse_provider/impl/json/parser.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef WFP_IMPL_JSON_PARSER_H
|
||||||
|
#define WFP_IMPL_JSON_PARSER_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stddef.h>
|
||||||
|
#else
|
||||||
|
#include <cstddef>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct wfp_json;
|
||||||
|
struct wfp_json_doc;
|
||||||
|
|
||||||
|
extern struct wfp_json_doc *
|
||||||
|
wfp_impl_json_parse_buffer(
|
||||||
|
char * data,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
wfp_impl_json_dispose(
|
||||||
|
struct wfp_json_doc * doc);
|
||||||
|
|
||||||
|
extern struct wfp_json const *
|
||||||
|
wfp_impl_json_root(
|
||||||
|
struct wfp_json_doc * doc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
169
lib/webfuse_provider/impl/json/reader.c
Normal file
169
lib/webfuse_provider/impl/json/reader.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#include "webfuse_provider/impl/json/reader.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
wfp_impl_json_reader_init(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char * contents,
|
||||||
|
size_t length)
|
||||||
|
{
|
||||||
|
reader->contents =contents;
|
||||||
|
reader->length = length;
|
||||||
|
reader->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wfp_impl_json_reader_skip_whitespace(
|
||||||
|
struct wfp_json_reader * reader)
|
||||||
|
{
|
||||||
|
char c = reader->contents[reader->pos];
|
||||||
|
|
||||||
|
while ((' ' == c) || ('\n' == c) || ('\t' == c)|| ('\r' == c))
|
||||||
|
{
|
||||||
|
reader->pos++;
|
||||||
|
c = reader->contents[reader->pos];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char
|
||||||
|
wfp_impl_json_reader_peek(
|
||||||
|
struct wfp_json_reader * reader)
|
||||||
|
{
|
||||||
|
char result = '\0';
|
||||||
|
if (reader->pos < reader->length)
|
||||||
|
{
|
||||||
|
result = reader->contents[reader->pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
wfp_impl_json_reader_read_char(
|
||||||
|
struct wfp_json_reader * reader)
|
||||||
|
{
|
||||||
|
char result = '\0';
|
||||||
|
if (reader->pos < reader->length)
|
||||||
|
{
|
||||||
|
result = reader->contents[reader->pos];
|
||||||
|
reader->pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wfp_impl_json_reader_unget_char(
|
||||||
|
struct wfp_json_reader * reader)
|
||||||
|
{
|
||||||
|
if (0 < reader->pos)
|
||||||
|
{
|
||||||
|
reader->pos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
wfp_impl_json_reader_read_const(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char const * value,
|
||||||
|
size_t length)
|
||||||
|
{
|
||||||
|
size_t const remaining = reader->length - reader->pos;
|
||||||
|
bool const result = ((remaining >= length) && (0 == strncmp(&(reader->contents[reader->pos]), value, length)));
|
||||||
|
{
|
||||||
|
reader->pos += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wfp_impl_json_reader_read_int(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char first)
|
||||||
|
{
|
||||||
|
bool const is_signed = ('-' == first);
|
||||||
|
int value = is_signed ? 0 : first - '0';
|
||||||
|
|
||||||
|
while (reader->pos < reader->length)
|
||||||
|
{
|
||||||
|
char c = reader->contents[reader->pos];
|
||||||
|
if (('0' <= c) && (c <= '9'))
|
||||||
|
{
|
||||||
|
value *= 10;
|
||||||
|
value += (c - '0');
|
||||||
|
reader->pos++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return (is_signed ? -value : value);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_reader_read_string(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char * * value)
|
||||||
|
{
|
||||||
|
wfp_impl_json_reader_skip_whitespace(reader);
|
||||||
|
char c = wfp_impl_json_reader_read_char(reader);
|
||||||
|
if ('\"' != c) { return false; }
|
||||||
|
|
||||||
|
size_t p = reader->pos;
|
||||||
|
*value = &(reader->contents[p]);
|
||||||
|
c = wfp_impl_json_reader_read_char(reader);
|
||||||
|
while (('\"' != c) && ('\0' != c))
|
||||||
|
{
|
||||||
|
if ('\\' != c)
|
||||||
|
{
|
||||||
|
reader->contents[p++] = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = wfp_impl_json_reader_read_char(reader);
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\"':
|
||||||
|
reader->contents[p++] = '\"';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
reader->contents[p++] = '\\';
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
reader->contents[p++] = '/';
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
reader->contents[p++] = '\b';
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
reader->contents[p++] = '\f';
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
reader->contents[p++] = '\n';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
reader->contents[p++] = '\r';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
reader->contents[p++] = '\t';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c = wfp_impl_json_reader_read_char(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool const result = ('\"' == c);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
reader->contents[p] = '\0';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
65
lib/webfuse_provider/impl/json/reader.h
Normal file
65
lib/webfuse_provider/impl/json/reader.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#ifndef WFP_IMPL_JSON_READER_H
|
||||||
|
#define WFP_IMPL_JSON_READER_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#else
|
||||||
|
#include <cstddef>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct wfp_json_reader
|
||||||
|
{
|
||||||
|
char * contents;
|
||||||
|
size_t length;
|
||||||
|
size_t pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void
|
||||||
|
wfp_impl_json_reader_init(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char * contents,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
wfp_impl_json_reader_skip_whitespace(
|
||||||
|
struct wfp_json_reader * reader);
|
||||||
|
|
||||||
|
extern char
|
||||||
|
wfp_impl_json_reader_peek(
|
||||||
|
struct wfp_json_reader * reader);
|
||||||
|
|
||||||
|
extern char
|
||||||
|
wfp_impl_json_reader_read_char(
|
||||||
|
struct wfp_json_reader * reader);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
wfp_impl_json_reader_unget_char(
|
||||||
|
struct wfp_json_reader * reader);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_reader_read_const(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char const * value,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
wfp_impl_json_reader_read_int(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char first);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
wfp_impl_json_reader_read_string(
|
||||||
|
struct wfp_json_reader * reader,
|
||||||
|
char * * value);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,6 @@
|
|||||||
#include "webfuse_provider/impl/util/json_util.h"
|
#include "webfuse_provider/impl/util/json_util.h"
|
||||||
|
|
||||||
int wfp_impl_json_get_int(json_t const * object, char const * key, int default_value)
|
int wfp_impl_json_get_integer(json_t const * object, char const * key, int default_value)
|
||||||
{
|
{
|
||||||
int result = default_value;
|
int result = default_value;
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ wfp_impl_jsonrpc_get_status(
|
|||||||
wfp_status status = WFP_GOOD;
|
wfp_status status = WFP_GOOD;
|
||||||
if (NULL != error)
|
if (NULL != error)
|
||||||
{
|
{
|
||||||
status = wfp_impl_json_get_int(error, "code", WFP_BAD_FORMAT);
|
status = wfp_impl_json_get_integer(error, "code", WFP_BAD_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -10,7 +10,7 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
wfp_impl_json_get_int(
|
wfp_impl_json_get_integer(
|
||||||
json_t const * object,
|
json_t const * object,
|
||||||
char const * key,
|
char const * key,
|
||||||
int default_value);
|
int default_value);
|
||||||
|
@ -30,6 +30,9 @@ webfuse_provider_static = static_library('webfuse_provider',
|
|||||||
'lib/webfuse_provider/impl/timer/timepoint.c',
|
'lib/webfuse_provider/impl/timer/timepoint.c',
|
||||||
'lib/webfuse_provider/impl/timer/timer.c',
|
'lib/webfuse_provider/impl/timer/timer.c',
|
||||||
'lib/webfuse_provider/impl/json/writer.c',
|
'lib/webfuse_provider/impl/json/writer.c',
|
||||||
|
'lib/webfuse_provider/impl/json/node.c',
|
||||||
|
'lib/webfuse_provider/impl/json/reader.c',
|
||||||
|
'lib/webfuse_provider/impl/json/parser.c',
|
||||||
'lib/webfuse_provider/impl/jsonrpc/proxy.c',
|
'lib/webfuse_provider/impl/jsonrpc/proxy.c',
|
||||||
'lib/webfuse_provider/impl/jsonrpc/proxy_variadic.c',
|
'lib/webfuse_provider/impl/jsonrpc/proxy_variadic.c',
|
||||||
'lib/webfuse_provider/impl/jsonrpc/request.c',
|
'lib/webfuse_provider/impl/jsonrpc/request.c',
|
||||||
@ -113,6 +116,7 @@ alltests = executable('alltests',
|
|||||||
'test/webfuse_provider/mocks/mock_provider.cc',
|
'test/webfuse_provider/mocks/mock_provider.cc',
|
||||||
'test/webfuse_provider/mocks/mock_jsonrpc_proxy.cc',
|
'test/webfuse_provider/mocks/mock_jsonrpc_proxy.cc',
|
||||||
'test/webfuse_provider/json/test_json_writer.cc',
|
'test/webfuse_provider/json/test_json_writer.cc',
|
||||||
|
'test/webfuse_provider/json/test_json_parser.cc',
|
||||||
'test/webfuse_provider/jsonrpc/mock_timer_callback.cc',
|
'test/webfuse_provider/jsonrpc/mock_timer_callback.cc',
|
||||||
'test/webfuse_provider/jsonrpc/mock_timer.cc',
|
'test/webfuse_provider/jsonrpc/mock_timer.cc',
|
||||||
'test/webfuse_provider/jsonrpc/test_is_request.cc',
|
'test/webfuse_provider/jsonrpc/test_is_request.cc',
|
||||||
|
133
test/webfuse_provider/json/test_json_parser.cc
Normal file
133
test/webfuse_provider/json/test_json_parser.cc
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#include "webfuse_provider/impl/json/parser.h"
|
||||||
|
#include "webfuse_provider/impl/json/node.h"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
wfp_json_doc * parse_json(char * text)
|
||||||
|
{
|
||||||
|
return wfp_impl_json_parse_buffer(text, strlen(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(json_parser, parse_true)
|
||||||
|
{
|
||||||
|
char text[] = "true";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_NE(nullptr, doc);
|
||||||
|
wfp_json const * root = wfp_impl_json_root(doc);
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_bool(root));
|
||||||
|
ASSERT_TRUE(wfp_impl_json_get_bool(root));
|
||||||
|
|
||||||
|
wfp_impl_json_dispose(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(json_parser, parse_false)
|
||||||
|
{
|
||||||
|
char text[] = "false";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_NE(nullptr, doc);
|
||||||
|
wfp_json const * root = wfp_impl_json_root(doc);
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_bool(root));
|
||||||
|
ASSERT_FALSE(wfp_impl_json_get_bool(root));
|
||||||
|
|
||||||
|
wfp_impl_json_dispose(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(json_parser, parse_int)
|
||||||
|
{
|
||||||
|
char text[] = "42";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_NE(nullptr, doc);
|
||||||
|
wfp_json const * root = wfp_impl_json_root(doc);
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_int(root));
|
||||||
|
ASSERT_EQ(42, wfp_impl_json_get_int(root));
|
||||||
|
|
||||||
|
wfp_impl_json_dispose(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(json_parser, parse_negative_int)
|
||||||
|
{
|
||||||
|
char text[] = "-1234";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_NE(nullptr, doc);
|
||||||
|
wfp_json const * root = wfp_impl_json_root(doc);
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_int(root));
|
||||||
|
ASSERT_EQ(-1234, wfp_impl_json_get_int(root));
|
||||||
|
|
||||||
|
wfp_impl_json_dispose(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(json_parser, parse_string)
|
||||||
|
{
|
||||||
|
char text[] = "\"brummni\"";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_NE(nullptr, doc);
|
||||||
|
wfp_json const * root = wfp_impl_json_root(doc);
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_string(root));
|
||||||
|
ASSERT_STREQ("brummni", wfp_impl_json_get_string(root));
|
||||||
|
|
||||||
|
wfp_impl_json_dispose(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(json_parser, parse_array)
|
||||||
|
{
|
||||||
|
char text[] = "[true,1,\"foo\",[42]]";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_NE(nullptr, doc);
|
||||||
|
wfp_json const * root = wfp_impl_json_root(doc);
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_array(root));
|
||||||
|
ASSERT_EQ(4, wfp_impl_json_array_size(root));
|
||||||
|
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_bool(wfp_impl_json_array_get(root, 0)));
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_int(wfp_impl_json_array_get(root, 1)));
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_string(wfp_impl_json_array_get(root, 2)));
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_array(wfp_impl_json_array_get(root, 3)));
|
||||||
|
|
||||||
|
wfp_impl_json_dispose(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(json_parser, parse_object)
|
||||||
|
{
|
||||||
|
char text[] = "{\"method\":\"add\",\"params\":[1,2],\"id\":42}";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_NE(nullptr, doc);
|
||||||
|
wfp_json const * root = wfp_impl_json_root(doc);
|
||||||
|
ASSERT_TRUE(wfp_impl_json_is_object(root));
|
||||||
|
ASSERT_EQ(3, wfp_impl_json_object_size(root));
|
||||||
|
|
||||||
|
ASSERT_STREQ("method", wfp_impl_json_object_key(root, 0));
|
||||||
|
ASSERT_STREQ("params", wfp_impl_json_object_key(root, 1));
|
||||||
|
ASSERT_STREQ("id", wfp_impl_json_object_key(root, 2));
|
||||||
|
|
||||||
|
wfp_impl_json_dispose(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(json_parser, parse_fail_invalid_json)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
char text[] = "True";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_EQ(nullptr, doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char text[] = "flas";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_EQ(nullptr, doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char text[] = "[1,2,3}";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_EQ(nullptr, doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char text[] = "{\"method\":\"add\",\"params\":[1,2],\"id\":42";
|
||||||
|
wfp_json_doc * doc = parse_json(text);
|
||||||
|
ASSERT_EQ(nullptr, doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,7 +5,7 @@ TEST(jsonrpc_util, get_int)
|
|||||||
{
|
{
|
||||||
json_t * object = json_object();
|
json_t * object = json_object();
|
||||||
json_object_set_new(object, "key", json_integer(23));
|
json_object_set_new(object, "key", json_integer(23));
|
||||||
int value = wfp_impl_json_get_int(object, "key", 42);
|
int value = wfp_impl_json_get_integer(object, "key", 42);
|
||||||
ASSERT_EQ(23, value);
|
ASSERT_EQ(23, value);
|
||||||
|
|
||||||
json_decref(object);
|
json_decref(object);
|
||||||
@ -13,7 +13,7 @@ TEST(jsonrpc_util, get_int)
|
|||||||
|
|
||||||
TEST(jsonrpc_util, failed_to_get_null_object)
|
TEST(jsonrpc_util, failed_to_get_null_object)
|
||||||
{
|
{
|
||||||
int value = wfp_impl_json_get_int(nullptr, "key", 42);
|
int value = wfp_impl_json_get_integer(nullptr, "key", 42);
|
||||||
|
|
||||||
ASSERT_EQ(42, value);
|
ASSERT_EQ(42, value);
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ TEST(jsonrpc_util, failed_to_get_null_object)
|
|||||||
TEST(jsonrpc_util, failed_to_get_not_object)
|
TEST(jsonrpc_util, failed_to_get_not_object)
|
||||||
{
|
{
|
||||||
json_t * object = json_array();
|
json_t * object = json_array();
|
||||||
int value = wfp_impl_json_get_int(nullptr, "key", 42);
|
int value = wfp_impl_json_get_integer(nullptr, "key", 42);
|
||||||
ASSERT_EQ(42, value);
|
ASSERT_EQ(42, value);
|
||||||
|
|
||||||
json_decref(object);
|
json_decref(object);
|
||||||
@ -30,7 +30,7 @@ TEST(jsonrpc_util, failed_to_get_not_object)
|
|||||||
TEST(jsonrpc_util, failed_to_get_invalid_key)
|
TEST(jsonrpc_util, failed_to_get_invalid_key)
|
||||||
{
|
{
|
||||||
json_t * object = json_object();
|
json_t * object = json_object();
|
||||||
int value = wfp_impl_json_get_int(object, "key", 42);
|
int value = wfp_impl_json_get_integer(object, "key", 42);
|
||||||
ASSERT_EQ(42, value);
|
ASSERT_EQ(42, value);
|
||||||
|
|
||||||
json_decref(object);
|
json_decref(object);
|
||||||
@ -40,7 +40,7 @@ TEST(jsonrpc_util, failed_to_get_invalid_value_type)
|
|||||||
{
|
{
|
||||||
json_t * object = json_object();
|
json_t * object = json_object();
|
||||||
json_object_set_new(object, "key", json_string("42"));
|
json_object_set_new(object, "key", json_string("42"));
|
||||||
int value = wfp_impl_json_get_int(object, "key", 42);
|
int value = wfp_impl_json_get_integer(object, "key", 42);
|
||||||
ASSERT_EQ(42, value);
|
ASSERT_EQ(42, value);
|
||||||
|
|
||||||
json_decref(object);
|
json_decref(object);
|
||||||
|
Loading…
Reference in New Issue
Block a user