#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 "map.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 CxMap* CxJsonObject;
typedef struct cx_mutstr_s CxJsonString;
typedef int64_t CxJsonInteger;
typedef double CxJsonNumber;
typedef enum cx_json_literal CxJsonLiteral;
struct cx_json_array_s {
CX_ARRAY_DECLARE(CxJsonValue*, data);
};
struct cx_json_value_s {
const CxAllocator *allocator;
CxJsonValueType type;
union {
CxJsonArray array;
CxJsonObject object;
CxJsonString string;
CxJsonInteger integer;
CxJsonNumber number;
CxJsonLiteral literal;
};
};
struct cx_json_token_s {
CxJsonTokenType tokentype;
bool allocated;
cxmutstr content;
};
struct cx_json_s {
const CxAllocator *allocator;
CxBuffer buffer;
CxJsonToken uncompleted;
CxJsonValue *parsed;
cxmutstr uncompleted_member_name;
CX_ARRAY_DECLARE_SIZED(
int, states,
unsigned);
CX_ARRAY_DECLARE_SIZED(CxJsonValue*, vbuf,
unsigned);
int states_internal[
8];
CxJsonValue* vbuf_internal[
8];
};
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;
uint8_t frac_max_digits;
bool indent_space;
uint8_t indent;
bool escape_slash;
};
typedef struct cx_json_writer_s CxJsonWriter;
cx_attr_nodiscard
CX_EXPORT CxJsonWriter cxJsonWriterCompact(
void);
cx_attr_nodiscard
CX_EXPORT CxJsonWriter cxJsonWriterPretty(bool use_spaces);
cx_attr_nonnull_arg(
1,
2,
3)
CX_EXPORT int cxJsonWrite(
void* target,
const CxJsonValue* value,
cx_write_func wfunc,
const CxJsonWriter* settings);
cx_attr_nonnull_arg(
1)
CX_EXPORT cxmutstr cxJsonToString(CxJsonValue *value,
const CxAllocator *allocator);
cx_attr_nonnull_arg(
1)
CX_EXPORT cxmutstr cxJsonToPrettyString(CxJsonValue *value,
const CxAllocator *allocator);
cx_attr_nonnull_arg(
1)
CX_EXPORT void cxJsonInit(CxJson *json,
const CxAllocator *allocator);
cx_attr_nonnull
CX_EXPORT void cxJsonDestroy(CxJson *json);
cx_attr_nonnull
CX_EXPORT void cxJsonReset(CxJson *json);
cx_attr_nonnull_arg(
1) cx_attr_access_r(
2,
3)
CX_EXPORT int cxJsonFilln(CxJson *json,
const char *buf,
size_t len);
cx_attr_nonnull
CX_INLINE int cx_json_fill(CxJson *json, cxstring str) {
return cxJsonFilln(json, str.ptr, str.length);
}
#define cxJsonFill(json, str) cx_json_fill(json, cx_strcast(str))
cx_attr_nonnull_arg(
3)
CX_EXPORT CxJsonStatus cx_json_from_string(
const CxAllocator *allocator,
cxstring str, CxJsonValue **value);
#define cxJsonFromString(allocator, str, value) \
cx_json_from_string(allocator, cx_strcast(str), value)
cx_attr_nodiscard
CX_EXPORT CxJsonValue* cxJsonCreateObj(
const CxAllocator* allocator);
cx_attr_nodiscard
CX_EXPORT CxJsonValue* cxJsonCreateArr(
const CxAllocator* allocator);
cx_attr_nodiscard
CX_EXPORT CxJsonValue* cxJsonCreateNumber(
const CxAllocator* allocator,
double num);
cx_attr_nodiscard
CX_EXPORT CxJsonValue* cxJsonCreateInteger(
const CxAllocator* allocator,
int64_t num);
cx_attr_nodiscard
CX_EXPORT CxJsonValue* cx_json_create_string(
const CxAllocator* allocator, cxstring str);
#define cxJsonCreateString(allocator, str) cx_json_create_string(allocator, cx_strcast(str))
cx_attr_nodiscard
CX_EXPORT CxJsonValue* cxJsonCreateLiteral(
const CxAllocator* allocator, CxJsonLiteral lit);
cx_attr_nonnull cx_attr_access_r(
2,
3)
CX_EXPORT int cxJsonArrAddNumbers(CxJsonValue* arr,
const double* num,
size_t count);
cx_attr_nonnull cx_attr_access_r(
2,
3)
CX_EXPORT int cxJsonArrAddIntegers(CxJsonValue* arr,
const int64_t* num,
size_t count);
cx_attr_nonnull cx_attr_access_r(
2,
3)
CX_EXPORT int cxJsonArrAddStrings(CxJsonValue* arr,
const char*
const* str,
size_t count);
cx_attr_nonnull cx_attr_access_r(
2,
3)
CX_EXPORT int cxJsonArrAddCxStrings(CxJsonValue* arr,
const cxstring* str,
size_t count);
cx_attr_nonnull cx_attr_access_r(
2,
3)
CX_EXPORT int cxJsonArrAddLiterals(CxJsonValue* arr,
const CxJsonLiteral* lit,
size_t count);
cx_attr_nonnull cx_attr_access_r(
2,
3)
CX_EXPORT int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue*
const* val,
size_t count);
cx_attr_nonnull
CX_EXPORT int cx_json_obj_put(CxJsonValue* obj, cxstring name, CxJsonValue* child);
#define cxJsonObjPut(obj, name, child) cx_json_obj_put(obj, cx_strcast(name), child)
cx_attr_nonnull
CX_EXPORT CxJsonValue* cx_json_obj_put_obj(CxJsonValue* obj, cxstring name);
#define cxJsonObjPutObj(obj, name) cx_json_obj_put_obj(obj, cx_strcast(name))
cx_attr_nonnull
CX_EXPORT CxJsonValue* cx_json_obj_put_arr(CxJsonValue* obj, cxstring name);
#define cxJsonObjPutArr(obj, name) cx_json_obj_put_arr(obj, cx_strcast(name))
cx_attr_nonnull
CX_EXPORT CxJsonValue* cx_json_obj_put_number(CxJsonValue* obj, cxstring name,
double num);
#define cxJsonObjPutNumber(obj, name, num) cx_json_obj_put_number(obj, cx_strcast(name), num)
cx_attr_nonnull
CX_EXPORT CxJsonValue* cx_json_obj_put_integer(CxJsonValue* obj, cxstring name,
int64_t num);
#define cxJsonObjPutInteger(obj, name, num) cx_json_obj_put_integer(obj, cx_strcast(name), num)
cx_attr_nonnull
CX_EXPORT CxJsonValue* cx_json_obj_put_string(CxJsonValue* obj, cxstring name, cxstring str);
#define cxJsonObjPutString(obj, name, str) cx_json_obj_put_string(obj, cx_strcast(name), cx_strcast(str))
cx_attr_nonnull
CX_EXPORT CxJsonValue* cx_json_obj_put_literal(CxJsonValue* obj, cxstring name, CxJsonLiteral lit);
#define cxJsonObjPutLiteral(obj, name, lit) cx_json_obj_put_literal(obj, cx_strcast(name), lit)
CX_EXPORT void cxJsonValueFree(CxJsonValue *value);
cx_attr_nonnull cx_attr_access_w(
2)
CX_EXPORT CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value);
cx_attr_nonnull
CX_INLINE bool cxJsonIsObject(
const CxJsonValue *value) {
return value->type ==
CX_JSON_OBJECT;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsArray(
const CxJsonValue *value) {
return value->type ==
CX_JSON_ARRAY;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsString(
const CxJsonValue *value) {
return value->type ==
CX_JSON_STRING;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsNumber(
const CxJsonValue *value) {
return value->type ==
CX_JSON_NUMBER || value->type ==
CX_JSON_INTEGER;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsInteger(
const CxJsonValue *value) {
return value->type ==
CX_JSON_INTEGER;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsLiteral(
const CxJsonValue *value) {
return value->type ==
CX_JSON_LITERAL;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsBool(
const CxJsonValue *value) {
return cxJsonIsLiteral(value) && value->literal !=
CX_JSON_NULL;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsTrue(
const CxJsonValue *value) {
return cxJsonIsLiteral(value) && value->literal ==
CX_JSON_TRUE;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsFalse(
const CxJsonValue *value) {
return cxJsonIsLiteral(value) && value->literal ==
CX_JSON_FALSE;
}
cx_attr_nonnull
CX_INLINE bool cxJsonIsNull(
const CxJsonValue *value) {
return cxJsonIsLiteral(value) && value->literal ==
CX_JSON_NULL;
}
cx_attr_nonnull cx_attr_returns_nonnull
CX_EXPORT char *cxJsonAsString(
const CxJsonValue *value);
cx_attr_nonnull
CX_EXPORT cxstring cxJsonAsCxString(
const CxJsonValue *value);
cx_attr_nonnull
CX_EXPORT cxmutstr cxJsonAsCxMutStr(
const CxJsonValue *value);
cx_attr_nonnull
CX_EXPORT double cxJsonAsDouble(
const CxJsonValue *value);
cx_attr_nonnull
CX_EXPORT int64_t cxJsonAsInteger(
const CxJsonValue *value);
cx_attr_nonnull
CX_INLINE bool cxJsonAsBool(
const CxJsonValue *value) {
return value->literal ==
CX_JSON_TRUE;
}
cx_attr_nonnull
CX_INLINE size_t cxJsonArrSize(
const CxJsonValue *value) {
return value->array.data_size;
}
cx_attr_nonnull cx_attr_returns_nonnull
CX_EXPORT CxJsonValue *cxJsonArrGet(
const CxJsonValue *value,
size_t index);
cx_attr_nonnull
CX_EXPORT CxJsonValue *cxJsonArrRemove(CxJsonValue *value,
size_t index);
cx_attr_nonnull cx_attr_nodiscard
CX_EXPORT CxIterator cxJsonArrIter(
const CxJsonValue *value);
cx_attr_nonnull
CX_INLINE size_t cxJsonObjSize(
const CxJsonValue *value) {
return cxCollectionSize(value->object);
}
cx_attr_nonnull cx_attr_nodiscard
CX_EXPORT CxMapIterator cxJsonObjIter(
const CxJsonValue *value);
cx_attr_nonnull cx_attr_returns_nonnull
CX_EXPORT CxJsonValue *cx_json_obj_get(
const CxJsonValue *value, cxstring name);
#define cxJsonObjGet(value, name) cx_json_obj_get(value, cx_strcast(name))
cx_attr_nonnull
CX_EXPORT CxJsonValue *cx_json_obj_remove(CxJsonValue *value, cxstring name);
#define cxJsonObjRemove(value, name) cx_json_obj_remove(value, cx_strcast(name))
#ifdef __cplusplus
}
#endif
#endif