#ifndef UCX_JSON_H
#define UCX_JSON_H
#include "common.h"
#include "allocator.h"
#include "string.h"
#include "buffer.h"
#include "array_list.h"
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
enum cx_json_token_type {
CX_JSON_NO_TOKEN,
CX_JSON_TOKEN_ERROR,
CX_JSON_TOKEN_BEGIN_ARRAY,
CX_JSON_TOKEN_BEGIN_OBJECT,
CX_JSON_TOKEN_END_ARRAY,
CX_JSON_TOKEN_END_OBJECT,
CX_JSON_TOKEN_NAME_SEPARATOR,
CX_JSON_TOKEN_VALUE_SEPARATOR,
CX_JSON_TOKEN_STRING,
CX_JSON_TOKEN_INTEGER,
CX_JSON_TOKEN_NUMBER,
CX_JSON_TOKEN_LITERAL,
CX_JSON_TOKEN_SPACE
};
enum cx_json_value_type {
CX_JSON_NOTHING,
CX_JSON_OBJECT,
CX_JSON_ARRAY,
CX_JSON_STRING,
CX_JSON_INTEGER,
CX_JSON_NUMBER,
CX_JSON_LITERAL
};
enum cx_json_literal {
CX_JSON_NULL,
CX_JSON_TRUE,
CX_JSON_FALSE
};
typedef enum cx_json_token_type CxJsonTokenType;
typedef enum cx_json_value_type CxJsonValueType;
typedef struct cx_json_s CxJson;
typedef struct cx_json_token_s CxJsonToken;
typedef struct cx_json_value_s CxJsonValue;
typedef struct cx_json_array_s CxJsonArray;
typedef struct cx_json_object_s CxJsonObject;
typedef struct cx_mutstr_s CxJsonString;
typedef int64_t CxJsonInteger;
typedef double CxJsonNumber;
typedef enum cx_json_literal CxJsonLiteral;
typedef struct cx_json_obj_value_s CxJsonObjValue;
struct cx_json_array_s {
CX_ARRAY_DECLARE(CxJsonValue*, array);
};
struct cx_json_object_s {
CX_ARRAY_DECLARE(CxJsonObjValue, values);
size_t *indices;
};
struct cx_json_obj_value_s {
cxmutstr name;
CxJsonValue *value;
};
struct cx_json_value_s {
const CxAllocator *allocator;
CxJsonValueType type;
union {
CxJsonArray array;
CxJsonObject object;
CxJsonString string;
CxJsonInteger integer;
CxJsonNumber number;
CxJsonLiteral literal;
} value;
};
struct cx_json_token_s {
CxJsonTokenType tokentype;
bool allocated;
cxmutstr content;
};
struct cx_json_s {
const CxAllocator *allocator;
CxBuffer buffer;
CxJsonToken uncompleted;
CxJsonValue *parsed;
CxJsonObjValue uncompleted_member;
CX_ARRAY_DECLARE_SIZED(
int, states,
unsigned);
CX_ARRAY_DECLARE_SIZED(CxJsonValue*, vbuf,
unsigned);
int states_internal[
8];
CxJsonValue* vbuf_internal[
8];
bool tokenizer_escape;
};
enum cx_json_status {
CX_JSON_NO_ERROR,
CX_JSON_NO_DATA,
CX_JSON_INCOMPLETE_DATA,
CX_JSON_OK,
CX_JSON_NULL_DATA,
CX_JSON_BUFFER_ALLOC_FAILED,
CX_JSON_VALUE_ALLOC_FAILED,
CX_JSON_FORMAT_ERROR_NUMBER,
CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN
};
typedef enum cx_json_status CxJsonStatus;
struct cx_json_writer_s {
bool pretty;
bool sort_members;
uint8_t frac_max_digits;
bool indent_space;
uint8_t indent;
};
typedef struct cx_json_writer_s CxJsonWriter;
cx_attr_nodiscard
CxJsonWriter cxJsonWriterCompact(
void);
cx_attr_nodiscard
CxJsonWriter cxJsonWriterPretty(bool use_spaces);
cx_attr_nonnull_arg(
1,
2,
3)
int cxJsonWrite(
void* target,
const CxJsonValue* value,
cx_write_func wfunc,
const CxJsonWriter* settings
);
cx_attr_nonnull_arg(
1)
void cxJsonInit(CxJson *json,
const CxAllocator *allocator);
cx_attr_nonnull
void cxJsonDestroy(CxJson *json);
cx_attr_nonnull
static inline
void cxJsonReset(CxJson *json) {
const CxAllocator *allocator = json->allocator;
cxJsonDestroy(json);
cxJsonInit(json, allocator);
}
cx_attr_nonnull
cx_attr_access_r(
2,
3)
int cxJsonFilln(CxJson *json,
const char *buf,
size_t len);
#ifdef __cplusplus
}
cx_attr_nonnull
static inline
int cxJsonFill(
CxJson *json,
cxstring str
) {
return cxJsonFilln(json, str.ptr, str.length);
}
cx_attr_nonnull
static inline
int cxJsonFill(
CxJson *json,
cxmutstr str
) {
return cxJsonFilln(json, str.ptr, str.length);
}
cx_attr_nonnull
cx_attr_cstr_arg(
2)
static inline
int cxJsonFill(
CxJson *json,
const char *str
) {
return cxJsonFilln(json, str, strlen(str));
}
extern "C" {
#else
#define cxJsonFill(json, str) _Generic((str), \
cxstring: cx_json_fill_cxstr, \
cxmutstr: cx_json_fill_mutstr, \
char*: cx_json_fill_str, \
const char*: cx_json_fill_str) \
(json, str)
cx_attr_nonnull
static inline
int cx_json_fill_cxstr(
CxJson *json,
cxstring str
) {
return cxJsonFilln(json, str.ptr, str.length);
}
cx_attr_nonnull
static inline
int cx_json_fill_mutstr(
CxJson *json,
cxmutstr str
) {
return cxJsonFilln(json, str.ptr, str.length);
}
cx_attr_nonnull
cx_attr_cstr_arg(
2)
static inline
int cx_json_fill_str(
CxJson *json,
const char *str
) {
return cxJsonFilln(json, str, strlen(str));
}
#endif
cx_attr_nodiscard
CxJsonValue* cxJsonCreateObj(
const CxAllocator* allocator);
cx_attr_nodiscard
CxJsonValue* cxJsonCreateArr(
const CxAllocator* allocator);
cx_attr_nodiscard
CxJsonValue* cxJsonCreateNumber(
const CxAllocator* allocator,
double num);
cx_attr_nodiscard
CxJsonValue* cxJsonCreateInteger(
const CxAllocator* allocator,
int64_t num);
cx_attr_nodiscard
cx_attr_nonnull_arg(
2)
cx_attr_cstr_arg(
2)
CxJsonValue* cxJsonCreateString(
const CxAllocator* allocator,
const char *str);
cx_attr_nodiscard
CxJsonValue* cxJsonCreateCxString(
const CxAllocator* allocator, cxstring str);
cx_attr_nodiscard
CxJsonValue* cxJsonCreateLiteral(
const CxAllocator* allocator, CxJsonLiteral lit);
cx_attr_nonnull
cx_attr_access_r(
2,
3)
int cxJsonArrAddNumbers(CxJsonValue* arr,
const double* num,
size_t count);
cx_attr_nonnull
cx_attr_access_r(
2,
3)
int cxJsonArrAddIntegers(CxJsonValue* arr,
const int64_t* num,
size_t count);
cx_attr_nonnull
cx_attr_access_r(
2,
3)
int cxJsonArrAddStrings(CxJsonValue* arr,
const char*
const* str,
size_t count);
cx_attr_nonnull
cx_attr_access_r(
2,
3)
int cxJsonArrAddCxStrings(CxJsonValue* arr,
const cxstring* str,
size_t count);
cx_attr_nonnull
cx_attr_access_r(
2,
3)
int cxJsonArrAddLiterals(CxJsonValue* arr,
const CxJsonLiteral* lit,
size_t count);
cx_attr_nonnull
cx_attr_access_r(
2,
3)
int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue*
const* val,
size_t count);
cx_attr_nonnull
int cxJsonObjPut(CxJsonValue* obj, cxstring name, CxJsonValue* child);
cx_attr_nonnull
CxJsonValue* cxJsonObjPutObj(CxJsonValue* obj, cxstring name);
cx_attr_nonnull
CxJsonValue* cxJsonObjPutArr(CxJsonValue* obj, cxstring name);
cx_attr_nonnull
CxJsonValue* cxJsonObjPutNumber(CxJsonValue* obj, cxstring name,
double num);
cx_attr_nonnull
CxJsonValue* cxJsonObjPutInteger(CxJsonValue* obj, cxstring name,
int64_t num);
cx_attr_nonnull
cx_attr_cstr_arg(
3)
CxJsonValue* cxJsonObjPutString(CxJsonValue* obj, cxstring name,
const char* str);
cx_attr_nonnull
CxJsonValue* cxJsonObjPutCxString(CxJsonValue* obj, cxstring name, cxstring str);
cx_attr_nonnull
CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, cxstring name, CxJsonLiteral lit);
void cxJsonValueFree(CxJsonValue *value);
cx_attr_nonnull
cx_attr_access_w(
2)
CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value);
cx_attr_nonnull
static inline bool cxJsonIsObject(
const CxJsonValue *value) {
return value->type ==
CX_JSON_OBJECT;
}
cx_attr_nonnull
static inline bool cxJsonIsArray(
const CxJsonValue *value) {
return value->type ==
CX_JSON_ARRAY;
}
cx_attr_nonnull
static inline bool cxJsonIsString(
const CxJsonValue *value) {
return value->type ==
CX_JSON_STRING;
}
cx_attr_nonnull
static inline bool cxJsonIsNumber(
const CxJsonValue *value) {
return value->type ==
CX_JSON_NUMBER || value->type ==
CX_JSON_INTEGER;
}
cx_attr_nonnull
static inline bool cxJsonIsInteger(
const CxJsonValue *value) {
return value->type ==
CX_JSON_INTEGER;
}
cx_attr_nonnull
static inline bool cxJsonIsLiteral(
const CxJsonValue *value) {
return value->type ==
CX_JSON_LITERAL;
}
cx_attr_nonnull
static inline bool cxJsonIsBool(
const CxJsonValue *value) {
return cxJsonIsLiteral(value) && value->value.literal !=
CX_JSON_NULL;
}
cx_attr_nonnull
static inline bool cxJsonIsTrue(
const CxJsonValue *value) {
return cxJsonIsLiteral(value) && value->value.literal ==
CX_JSON_TRUE;
}
cx_attr_nonnull
static inline bool cxJsonIsFalse(
const CxJsonValue *value) {
return cxJsonIsLiteral(value) && value->value.literal ==
CX_JSON_FALSE;
}
cx_attr_nonnull
static inline bool cxJsonIsNull(
const CxJsonValue *value) {
return cxJsonIsLiteral(value) && value->value.literal ==
CX_JSON_NULL;
}
cx_attr_nonnull
cx_attr_returns_nonnull
static inline
char *cxJsonAsString(
const CxJsonValue *value) {
return value->value.string.ptr;
}
cx_attr_nonnull
static inline cxstring cxJsonAsCxString(
const CxJsonValue *value) {
return cx_strcast(value->value.string);
}
cx_attr_nonnull
static inline cxmutstr cxJsonAsCxMutStr(
const CxJsonValue *value) {
return value->value.string;
}
cx_attr_nonnull
static inline
double cxJsonAsDouble(
const CxJsonValue *value) {
if (value->type ==
CX_JSON_INTEGER) {
return (
double) value->value.integer;
}
else {
return value->value.number;
}
}
cx_attr_nonnull
static inline
int64_t cxJsonAsInteger(
const CxJsonValue *value) {
if (value->type ==
CX_JSON_INTEGER) {
return value->value.integer;
}
else {
return (
int64_t) value->value.number;
}
}
cx_attr_nonnull
static inline bool cxJsonAsBool(
const CxJsonValue *value) {
return value->value.literal ==
CX_JSON_TRUE;
}
cx_attr_nonnull
static inline
size_t cxJsonArrSize(
const CxJsonValue *value) {
return value->value.array.array_size;
}
cx_attr_nonnull
cx_attr_returns_nonnull
CxJsonValue *cxJsonArrGet(
const CxJsonValue *value,
size_t index);
cx_attr_nonnull
cx_attr_nodiscard
CxIterator cxJsonArrIter(
const CxJsonValue *value);
cx_attr_nonnull
cx_attr_nodiscard
CxIterator cxJsonObjIter(
const CxJsonValue *value);
cx_attr_nonnull
cx_attr_returns_nonnull
CxJsonValue *cx_json_obj_get_cxstr(
const CxJsonValue *value, cxstring name);
#ifdef __cplusplus
}
CxJsonValue *cxJsonObjGet(
const CxJsonValue *value, cxstring name) {
return cx_json_obj_get_cxstr(value, name);
}
CxJsonValue *cxJsonObjGet(
const CxJsonValue *value, cxmutstr name) {
return cx_json_obj_get_cxstr(value, cx_strcast(name));
}
CxJsonValue *cxJsonObjGet(
const CxJsonValue *value,
const char *name) {
return cx_json_obj_get_cxstr(value, cx_str(name));
}
extern "C" {
#else
#define cxJsonObjGet(value, name) _Generic((name), \
cxstring: cx_json_obj_get_cxstr, \
cxmutstr: cx_json_obj_get_mutstr, \
char*: cx_json_obj_get_str, \
const char*: cx_json_obj_get_str) \
(value, name)
cx_attr_nonnull
cx_attr_returns_nonnull
static inline CxJsonValue *cx_json_obj_get_mutstr(
const CxJsonValue *value, cxmutstr name) {
return cx_json_obj_get_cxstr(value, cx_strcast(name));
}
cx_attr_nonnull
cx_attr_returns_nonnull
cx_attr_cstr_arg(
2)
static inline CxJsonValue *cx_json_obj_get_str(
const CxJsonValue *value,
const char *name) {
return cx_json_obj_get_cxstr(value, cx_str(name));
}
#endif
#ifdef __cplusplus
}
#endif
#endif