cson commit
This commit is contained in:
commit
7cb343e85c
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef JANSSON_H
|
||||
#define JANSSON_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for size_t */
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "jansson_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* version */
|
||||
|
||||
#define JANSSON_MAJOR_VERSION 2
|
||||
#define JANSSON_MINOR_VERSION 12
|
||||
#define JANSSON_MICRO_VERSION 0
|
||||
|
||||
/* Micro version is omitted if it's 0 */
|
||||
#define JANSSON_VERSION "2.12"
|
||||
|
||||
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
|
||||
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
|
||||
#define JANSSON_VERSION_HEX ((JANSSON_MAJOR_VERSION << 16) | \
|
||||
(JANSSON_MINOR_VERSION << 8) | \
|
||||
(JANSSON_MICRO_VERSION << 0))
|
||||
|
||||
/* If __atomic or __sync builtins are available the library is thread
|
||||
* safe for all read-only functions plus reference counting. */
|
||||
#if JSON_HAVE_ATOMIC_BUILTINS || JSON_HAVE_SYNC_BUILTINS
|
||||
#define JANSSON_THREAD_SAFE_REFCOUNT 1
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define JANSSON_ATTRS(...) __attribute__((__VA_ARGS__))
|
||||
#else
|
||||
#define JANSSON_ATTRS(...)
|
||||
#endif
|
||||
|
||||
/* types */
|
||||
|
||||
typedef enum {
|
||||
JSON_OBJECT,
|
||||
JSON_ARRAY,
|
||||
JSON_STRING,
|
||||
JSON_INTEGER,
|
||||
JSON_REAL,
|
||||
JSON_TRUE,
|
||||
JSON_FALSE,
|
||||
JSON_NULL
|
||||
} json_type;
|
||||
|
||||
typedef struct json_t {
|
||||
json_type type;
|
||||
volatile size_t refcount;
|
||||
} json_t;
|
||||
|
||||
#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
|
||||
#if JSON_INTEGER_IS_LONG_LONG
|
||||
#ifdef _WIN32
|
||||
#define JSON_INTEGER_FORMAT "I64d"
|
||||
#else
|
||||
#define JSON_INTEGER_FORMAT "lld"
|
||||
#endif
|
||||
typedef long long json_int_t;
|
||||
#else
|
||||
#define JSON_INTEGER_FORMAT "ld"
|
||||
typedef long json_int_t;
|
||||
#endif /* JSON_INTEGER_IS_LONG_LONG */
|
||||
#endif
|
||||
|
||||
#define json_typeof(json) ((json)->type)
|
||||
#define json_is_object(json) ((json) && json_typeof(json) == JSON_OBJECT)
|
||||
#define json_is_array(json) ((json) && json_typeof(json) == JSON_ARRAY)
|
||||
#define json_is_string(json) ((json) && json_typeof(json) == JSON_STRING)
|
||||
#define json_is_integer(json) ((json) && json_typeof(json) == JSON_INTEGER)
|
||||
#define json_is_real(json) ((json) && json_typeof(json) == JSON_REAL)
|
||||
#define json_is_number(json) (json_is_integer(json) || json_is_real(json))
|
||||
#define json_is_true(json) ((json) && json_typeof(json) == JSON_TRUE)
|
||||
#define json_is_false(json) ((json) && json_typeof(json) == JSON_FALSE)
|
||||
#define json_boolean_value json_is_true
|
||||
#define json_is_boolean(json) (json_is_true(json) || json_is_false(json))
|
||||
#define json_is_null(json) ((json) && json_typeof(json) == JSON_NULL)
|
||||
|
||||
/* construction, destruction, reference counting */
|
||||
|
||||
json_t *json_object(void);
|
||||
json_t *json_array(void);
|
||||
json_t *json_string(const char *value);
|
||||
json_t *json_stringn(const char *value, size_t len);
|
||||
json_t *json_string_nocheck(const char *value);
|
||||
json_t *json_stringn_nocheck(const char *value, size_t len);
|
||||
json_t *json_integer(json_int_t value);
|
||||
json_t *json_real(double value);
|
||||
json_t *json_true(void);
|
||||
json_t *json_false(void);
|
||||
#define json_boolean(val) ((val) ? json_true() : json_false())
|
||||
json_t *json_null(void);
|
||||
|
||||
/* do not call JSON_INTERNAL_INCREF or JSON_INTERNAL_DECREF directly */
|
||||
#if JSON_HAVE_ATOMIC_BUILTINS
|
||||
#define JSON_INTERNAL_INCREF(json) __atomic_add_fetch(&json->refcount, 1, __ATOMIC_ACQUIRE)
|
||||
#define JSON_INTERNAL_DECREF(json) __atomic_sub_fetch(&json->refcount, 1, __ATOMIC_RELEASE)
|
||||
#elif JSON_HAVE_SYNC_BUILTINS
|
||||
#define JSON_INTERNAL_INCREF(json) __sync_add_and_fetch(&json->refcount, 1)
|
||||
#define JSON_INTERNAL_DECREF(json) __sync_sub_and_fetch(&json->refcount, 1)
|
||||
#else
|
||||
#define JSON_INTERNAL_INCREF(json) (++json->refcount)
|
||||
#define JSON_INTERNAL_DECREF(json) (--json->refcount)
|
||||
#endif
|
||||
|
||||
static JSON_INLINE
|
||||
json_t *json_incref(json_t *json)
|
||||
{
|
||||
if(json && json->refcount != (size_t)-1)
|
||||
JSON_INTERNAL_INCREF(json);
|
||||
return json;
|
||||
}
|
||||
|
||||
/* do not call json_delete directly */
|
||||
void json_delete(json_t *json);
|
||||
|
||||
static JSON_INLINE
|
||||
void json_decref(json_t *json)
|
||||
{
|
||||
if(json && json->refcount != (size_t)-1 && JSON_INTERNAL_DECREF(json) == 0)
|
||||
json_delete(json);
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
static JSON_INLINE
|
||||
void json_decrefp(json_t **json)
|
||||
{
|
||||
if(json) {
|
||||
json_decref(*json);
|
||||
*json = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define json_auto_t json_t __attribute__((cleanup(json_decrefp)))
|
||||
#endif
|
||||
|
||||
|
||||
/* error reporting */
|
||||
|
||||
#define JSON_ERROR_TEXT_LENGTH 160
|
||||
#define JSON_ERROR_SOURCE_LENGTH 80
|
||||
|
||||
typedef struct json_error_t {
|
||||
int line;
|
||||
int column;
|
||||
int position;
|
||||
char source[JSON_ERROR_SOURCE_LENGTH];
|
||||
char text[JSON_ERROR_TEXT_LENGTH];
|
||||
} json_error_t;
|
||||
|
||||
enum json_error_code {
|
||||
json_error_unknown,
|
||||
json_error_out_of_memory,
|
||||
json_error_stack_overflow,
|
||||
json_error_cannot_open_file,
|
||||
json_error_invalid_argument,
|
||||
json_error_invalid_utf8,
|
||||
json_error_premature_end_of_input,
|
||||
json_error_end_of_input_expected,
|
||||
json_error_invalid_syntax,
|
||||
json_error_invalid_format,
|
||||
json_error_wrong_type,
|
||||
json_error_null_character,
|
||||
json_error_null_value,
|
||||
json_error_null_byte_in_key,
|
||||
json_error_duplicate_key,
|
||||
json_error_numeric_overflow,
|
||||
json_error_item_not_found,
|
||||
json_error_index_out_of_range
|
||||
};
|
||||
|
||||
static JSON_INLINE enum json_error_code json_error_code(const json_error_t *e) {
|
||||
return (enum json_error_code)e->text[JSON_ERROR_TEXT_LENGTH - 1];
|
||||
}
|
||||
|
||||
/* getters, setters, manipulation */
|
||||
|
||||
void json_object_seed(size_t seed);
|
||||
size_t json_object_size(const json_t *object);
|
||||
json_t *json_object_get(const json_t *object, const char *key) JANSSON_ATTRS(warn_unused_result);
|
||||
int json_object_set_new(json_t *object, const char *key, json_t *value);
|
||||
int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value);
|
||||
int json_object_del(json_t *object, const char *key);
|
||||
int json_object_clear(json_t *object);
|
||||
int json_object_update(json_t *object, json_t *other);
|
||||
int json_object_update_existing(json_t *object, json_t *other);
|
||||
int json_object_update_missing(json_t *object, json_t *other);
|
||||
void *json_object_iter(json_t *object);
|
||||
void *json_object_iter_at(json_t *object, const char *key);
|
||||
void *json_object_key_to_iter(const char *key);
|
||||
void *json_object_iter_next(json_t *object, void *iter);
|
||||
const char *json_object_iter_key(void *iter);
|
||||
json_t *json_object_iter_value(void *iter);
|
||||
int json_object_iter_set_new(json_t *object, void *iter, json_t *value);
|
||||
|
||||
#define json_object_foreach(object, key, value) \
|
||||
for(key = json_object_iter_key(json_object_iter(object)); \
|
||||
key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
|
||||
key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key))))
|
||||
|
||||
#define json_object_foreach_safe(object, n, key, value) \
|
||||
for(key = json_object_iter_key(json_object_iter(object)), \
|
||||
n = json_object_iter_next(object, json_object_key_to_iter(key)); \
|
||||
key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
|
||||
key = json_object_iter_key(n), \
|
||||
n = json_object_iter_next(object, json_object_key_to_iter(key)))
|
||||
|
||||
#define json_array_foreach(array, index, value) \
|
||||
for(index = 0; \
|
||||
index < json_array_size(array) && (value = json_array_get(array, index)); \
|
||||
index++)
|
||||
|
||||
static JSON_INLINE
|
||||
int json_object_set(json_t *object, const char *key, json_t *value)
|
||||
{
|
||||
return json_object_set_new(object, key, json_incref(value));
|
||||
}
|
||||
|
||||
static JSON_INLINE
|
||||
int json_object_set_nocheck(json_t *object, const char *key, json_t *value)
|
||||
{
|
||||
return json_object_set_new_nocheck(object, key, json_incref(value));
|
||||
}
|
||||
|
||||
static JSON_INLINE
|
||||
int json_object_iter_set(json_t *object, void *iter, json_t *value)
|
||||
{
|
||||
return json_object_iter_set_new(object, iter, json_incref(value));
|
||||
}
|
||||
|
||||
size_t json_array_size(const json_t *array);
|
||||
json_t *json_array_get(const json_t *array, size_t index) JANSSON_ATTRS(warn_unused_result);
|
||||
int json_array_set_new(json_t *array, size_t index, json_t *value);
|
||||
int json_array_append_new(json_t *array, json_t *value);
|
||||
int json_array_insert_new(json_t *array, size_t index, json_t *value);
|
||||
int json_array_remove(json_t *array, size_t index);
|
||||
int json_array_clear(json_t *array);
|
||||
int json_array_extend(json_t *array, json_t *other);
|
||||
|
||||
static JSON_INLINE
|
||||
int json_array_set(json_t *array, size_t ind, json_t *value)
|
||||
{
|
||||
return json_array_set_new(array, ind, json_incref(value));
|
||||
}
|
||||
|
||||
static JSON_INLINE
|
||||
int json_array_append(json_t *array, json_t *value)
|
||||
{
|
||||
return json_array_append_new(array, json_incref(value));
|
||||
}
|
||||
|
||||
static JSON_INLINE
|
||||
int json_array_insert(json_t *array, size_t ind, json_t *value)
|
||||
{
|
||||
return json_array_insert_new(array, ind, json_incref(value));
|
||||
}
|
||||
|
||||
const char *json_string_value(const json_t *string);
|
||||
size_t json_string_length(const json_t *string);
|
||||
json_int_t json_integer_value(const json_t *integer);
|
||||
double json_real_value(const json_t *real);
|
||||
double json_number_value(const json_t *json);
|
||||
|
||||
int json_string_set(json_t *string, const char *value);
|
||||
int json_string_setn(json_t *string, const char *value, size_t len);
|
||||
int json_string_set_nocheck(json_t *string, const char *value);
|
||||
int json_string_setn_nocheck(json_t *string, const char *value, size_t len);
|
||||
int json_integer_set(json_t *integer, json_int_t value);
|
||||
int json_real_set(json_t *real, double value);
|
||||
|
||||
/* pack, unpack */
|
||||
|
||||
json_t *json_pack(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result);
|
||||
json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) JANSSON_ATTRS(warn_unused_result);
|
||||
json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result);
|
||||
|
||||
#define JSON_VALIDATE_ONLY 0x1
|
||||
#define JSON_STRICT 0x2
|
||||
|
||||
int json_unpack(json_t *root, const char *fmt, ...);
|
||||
int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...);
|
||||
int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, va_list ap);
|
||||
|
||||
/* sprintf */
|
||||
|
||||
json_t *json_sprintf(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 2));
|
||||
json_t *json_vsprintf(const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 0));
|
||||
|
||||
|
||||
/* equality */
|
||||
|
||||
int json_equal(const json_t *value1, const json_t *value2);
|
||||
|
||||
|
||||
/* copying */
|
||||
|
||||
json_t *json_copy(json_t *value) JANSSON_ATTRS(warn_unused_result);
|
||||
json_t *json_deep_copy(const json_t *value) JANSSON_ATTRS(warn_unused_result);
|
||||
|
||||
|
||||
/* decoding */
|
||||
|
||||
#define JSON_REJECT_DUPLICATES 0x1
|
||||
#define JSON_DISABLE_EOF_CHECK 0x2
|
||||
#define JSON_DECODE_ANY 0x4
|
||||
#define JSON_DECODE_INT_AS_REAL 0x8
|
||||
#define JSON_ALLOW_NUL 0x10
|
||||
|
||||
typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data);
|
||||
|
||||
json_t *json_loads(const char *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
|
||||
json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
|
||||
json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
|
||||
json_t *json_loadfd(int input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
|
||||
json_t *json_load_file(const char *path, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
|
||||
json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
|
||||
|
||||
|
||||
/* encoding */
|
||||
|
||||
#define JSON_MAX_INDENT 0x1F
|
||||
#define JSON_INDENT(n) ((n) & JSON_MAX_INDENT)
|
||||
#define JSON_COMPACT 0x20
|
||||
#define JSON_ENSURE_ASCII 0x40
|
||||
#define JSON_SORT_KEYS 0x80
|
||||
#define JSON_PRESERVE_ORDER 0x100
|
||||
#define JSON_ENCODE_ANY 0x200
|
||||
#define JSON_ESCAPE_SLASH 0x400
|
||||
#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
|
||||
#define JSON_EMBED 0x10000
|
||||
|
||||
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
|
||||
|
||||
char *json_dumps(const json_t *json, size_t flags) JANSSON_ATTRS(warn_unused_result);
|
||||
size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags);
|
||||
int json_dumpf(const json_t *json, FILE *output, size_t flags);
|
||||
int json_dumpfd(const json_t *json, int output, size_t flags);
|
||||
int json_dump_file(const json_t *json, const char *path, size_t flags);
|
||||
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags);
|
||||
|
||||
/* custom memory allocation */
|
||||
|
||||
typedef void *(*json_malloc_t)(size_t);
|
||||
typedef void (*json_free_t)(void *);
|
||||
|
||||
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn);
|
||||
void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*
|
||||
*
|
||||
* This file specifies a part of the site-specific configuration for
|
||||
* Jansson, namely those things that affect the public API in
|
||||
* jansson.h.
|
||||
*
|
||||
* The configure script copies this file to jansson_config.h and
|
||||
* replaces @var@ substitutions by values that fit your system. If you
|
||||
* cannot run the configure script, you can do the value substitution
|
||||
* by hand.
|
||||
*/
|
||||
|
||||
#ifndef JANSSON_CONFIG_H
|
||||
#define JANSSON_CONFIG_H
|
||||
|
||||
/* If your compiler supports the inline keyword in C, JSON_INLINE is
|
||||
defined to `inline', otherwise empty. In C++, the inline is always
|
||||
supported. */
|
||||
#ifdef __cplusplus
|
||||
#define JSON_INLINE inline
|
||||
#else
|
||||
#define JSON_INLINE inline
|
||||
#endif
|
||||
|
||||
/* If your compiler supports the `long long` type and the strtoll()
|
||||
library function, JSON_INTEGER_IS_LONG_LONG is defined to 1,
|
||||
otherwise to 0. */
|
||||
#define JSON_INTEGER_IS_LONG_LONG 1
|
||||
|
||||
/* If locale.h and localeconv() are available, define to 1,
|
||||
otherwise to 0. */
|
||||
#define JSON_HAVE_LOCALECONV 1
|
||||
|
||||
/* If __atomic builtins are available they will be used to manage
|
||||
reference counts of json_t. */
|
||||
#define JSON_HAVE_ATOMIC_BUILTINS 1
|
||||
|
||||
/* If __atomic builtins are not available we try using __sync builtins
|
||||
to manage reference counts of json_t. */
|
||||
#define JSON_HAVE_SYNC_BUILTINS 1
|
||||
|
||||
/* Maximum recursion depth for parsing JSON input.
|
||||
This limits the depth of e.g. array-within-array constructions. */
|
||||
#define JSON_PARSER_MAX_DEPTH 2048
|
||||
|
||||
#endif
|
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 sunchb
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,44 @@
|
|||
# Define the command of tool
|
||||
CC := gcc
|
||||
AR := ar
|
||||
MD := mkdir -p
|
||||
RM := rm -rf
|
||||
|
||||
# Define the JSON parsing library used (cjson or jansson supported)
|
||||
JSON_LIB = cjson
|
||||
#JSON_LIB = jansson
|
||||
|
||||
# output files
|
||||
OUT_DIR := ./output
|
||||
TARGET := $(OUT_DIR)/libcson.a
|
||||
|
||||
# source files
|
||||
SRC_DIR = ./src
|
||||
SRC_FILES += $(wildcard $(SRC_DIR)/*.c)
|
||||
|
||||
ADP_SRC_DIR = ./adapter/$(JSON_LIB)
|
||||
ADP_SRC_FILES += $(wildcard $(ADP_SRC_DIR)/*.c)
|
||||
|
||||
# *.o
|
||||
OBJS += $(patsubst $(SRC_DIR)/%.c, $(OUT_DIR)/%.o, $(SRC_FILES))
|
||||
OBJS += $(patsubst $(ADP_SRC_DIR)/%.c, $(OUT_DIR)/%.o, $(ADP_SRC_FILES))
|
||||
|
||||
# include path
|
||||
INC_PATH += -I./inc/
|
||||
INC_PATH += -I./3rd/inc/
|
||||
|
||||
$(TARGET):$(OBJS)
|
||||
@$(MD) $(OUT_DIR)
|
||||
@$(AR) rc $(TARGET) $(OBJS)
|
||||
|
||||
$(OUT_DIR)/%.o:$(SRC_DIR)/%.c
|
||||
@$(MD) $(OUT_DIR)
|
||||
@$(CC) $(INC_PATH) -c $< -o $@
|
||||
|
||||
$(OUT_DIR)/%.o:$(ADP_SRC_DIR)/%.c
|
||||
@$(MD) $(OUT_DIR)
|
||||
@$(CC) $(INC_PATH) -c $< -o $@
|
||||
|
||||
.PHONY:clean
|
||||
clean:
|
||||
@$(RM) $(OUT_DIR)
|
|
@ -0,0 +1,202 @@
|
|||
# cson
|
||||
Transformation between json string and struct.
|
||||
|
||||
The transformation between string to JSON objects (e.g. json_t in Jansson)
|
||||
is implemented by a third-party library (Jansson or cJSON. Refer to Dependence).
|
||||
What cson really implements is the transformation between JSON object and structure.
|
||||
|
||||
## Compilation
|
||||
### Compile static library
|
||||
``` shell
|
||||
$ git clone https://github.com/sunchb/cson.git
|
||||
$ cd cson
|
||||
$ make
|
||||
```
|
||||
### Compile demo
|
||||
``` shell
|
||||
$ cd demo
|
||||
$ make
|
||||
$ ./test
|
||||
```
|
||||
## How to use
|
||||
1. Define the data structure for JSON.
|
||||
2. Define the property description table for data structure.
|
||||
3. Call cson api to decode or encode.
|
||||
|
||||
## Dependence
|
||||
https://github.com/akheron/jansson.git
|
||||
https://github.com/DaveGamble/cJSON.git
|
||||
|
||||
## Demo
|
||||
Here is a JSON with various data types. eg. Interger, String, Real, Boolean, Object, and Array.
|
||||
We're going to decode and encode it by cson.
|
||||
|
||||
``` json
|
||||
{
|
||||
"name":"jay zhou",
|
||||
"creater":"dahuaxia",
|
||||
"songNum":2,
|
||||
"songList":[
|
||||
{
|
||||
"songName":"qilixiang",
|
||||
"signerName":"jay zhou",
|
||||
"albumName":"qilixiang",
|
||||
"url":"www.kugou.com",
|
||||
"duration":200,
|
||||
"paid":false,
|
||||
"price":6.6600000000000001,
|
||||
"lyricNum":2,
|
||||
"lyric":[
|
||||
{
|
||||
"time":1,
|
||||
"text":"Sparrow outside the window"
|
||||
},
|
||||
{
|
||||
"time":10,
|
||||
"text":"Multi mouth on the pole"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"songName":"dongfengpo",
|
||||
"signerName":"jay zhou",
|
||||
"albumName":"dongfengpo",
|
||||
"url":"music.qq.com",
|
||||
"duration":180,
|
||||
"paid":true,
|
||||
"price":0.88,
|
||||
"lyricNum":2,
|
||||
"lyric":[
|
||||
{
|
||||
"time":10,
|
||||
"text":"A sad parting, standing alone in the window"
|
||||
},
|
||||
{
|
||||
"time":20,
|
||||
"text":"I'm behind the door pretending you're not gone"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"extData":{
|
||||
"a":999,
|
||||
"b":1.05
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 1. Define the data structure for JSON.
|
||||
Even if you don't use cson, you usually need to do like this.
|
||||
|
||||
#### Attention
|
||||
- String must be declared as char*.
|
||||
- Array must be declared as pointer.
|
||||
- Declare additional properties to hold the array size for every array property.
|
||||
|
||||
``` c
|
||||
typedef struct {
|
||||
int time;
|
||||
char* text; /* String must be declared as char* */
|
||||
} Lyric;
|
||||
|
||||
typedef struct {
|
||||
char* songName;
|
||||
char* signerName;
|
||||
char* albumName;
|
||||
char* url;
|
||||
int duration;
|
||||
int paid;
|
||||
double price;
|
||||
size_t lyricNum; /* Declare additional properties to hold the array size */
|
||||
Lyric* lyric; /* Array must be declared as pointer */
|
||||
} SongInfo;
|
||||
|
||||
typedef struct {
|
||||
int a;
|
||||
double b;
|
||||
} ExtData;
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
char* creater;
|
||||
size_t songNum;
|
||||
SongInfo* songList;
|
||||
ExtData extData;
|
||||
} PlayList;
|
||||
```
|
||||
|
||||
### 2. Define the property description table for data structure.
|
||||
Use following definitions to help you describe the structure.
|
||||
- _property_int(type, field)
|
||||
- _property_real(type, field)
|
||||
- _property_bool(type, field)
|
||||
- _property_string(type, field)
|
||||
- _property_obj(type, field, tbl)
|
||||
- _property_array_object(type, field, tbl, arrayType, countfild) # I know it's a little cumbersome, I'm trying to simplify it.
|
||||
- _property_array_int(type, field, arrayType, countfild)
|
||||
- _property_array_string(type, field, arrayType, countfild)
|
||||
- _property_array_real(type, field, arrayType, countfild)
|
||||
- _property_array_bool(type, field, arrayType, countfild)
|
||||
|
||||
Args notes:
|
||||
- type: type of data structure
|
||||
- field: property name
|
||||
- tbl: description table of the property type. use when object or object array
|
||||
- arrayType: type of the array (Used to calculate size when dynamically get array memory)
|
||||
- countfild: property to save array size
|
||||
|
||||
``` c
|
||||
/* description for Lyric */
|
||||
reflect_item_t lyric_ref_tbl[] = {
|
||||
_property_int(Lyric, time),
|
||||
_property_string(Lyric, text),
|
||||
_property_end()
|
||||
};
|
||||
|
||||
/* description for SongInfo */
|
||||
reflect_item_t song_ref_tbl[] = {
|
||||
_property_string(SongInfo, songName),
|
||||
_property_string(SongInfo, signerName),
|
||||
_property_string(SongInfo, albumName),
|
||||
_property_string(SongInfo, url),
|
||||
_property_int(SongInfo, duration),
|
||||
_property_bool(SongInfo, paid),
|
||||
_property_real(SongInfo, price),
|
||||
_property_int(SongInfo, lyricNum),
|
||||
_property_array(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum), /* Lyric: type of array; lyricNum: property to save array size */
|
||||
_property_end()
|
||||
};
|
||||
|
||||
/* description for ExtData */
|
||||
reflect_item_t ext_data_ref_tbl[] = {
|
||||
_property_int(ExtData, a),
|
||||
_property_real(ExtData, b),
|
||||
_property_end()
|
||||
};
|
||||
|
||||
/* description for PlayList */
|
||||
reflect_item_t play_list_ref_tbl[] = {
|
||||
_property_string(PlayList, name),
|
||||
_property_string(PlayList, creater),
|
||||
_property_int(PlayList, songNum),
|
||||
_property_array(PlayList, songList, song_ref_tbl, SongInfo, songNum),
|
||||
_property_obj(PlayList, extData, ext_data_ref_tbl),
|
||||
_property_end()
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Call cson api to decode or encode.
|
||||
``` c
|
||||
PlayList playList;
|
||||
|
||||
/* Decode */
|
||||
csonJsonStr2Struct(jStr, &playList, play_list_ref_tbl);
|
||||
|
||||
/* Encode */
|
||||
char* jstrOutput;
|
||||
csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl);
|
||||
```
|
||||
|
||||
## restrict
|
||||
- Multidimensional arrays are not supported.
|
||||
- Cjson is used by default. If you want to use jannson or other json lib, please modify $(JSON_LIB) in makefile
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef cJSON__h
|
||||
#define cJSON__h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
|
||||
#define __WINDOWS__
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
||||
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
|
||||
|
||||
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
|
||||
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
|
||||
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
|
||||
|
||||
For *nix builds that support visibility attribute, you can define similar behavior by
|
||||
|
||||
setting default visibility to hidden by adding
|
||||
-fvisibility=hidden (for gcc)
|
||||
or
|
||||
-xldscope=hidden (for sun cc)
|
||||
to CFLAGS
|
||||
|
||||
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
|
||||
|
||||
*/
|
||||
|
||||
#define CJSON_CDECL __cdecl
|
||||
#define CJSON_STDCALL __stdcall
|
||||
|
||||
/* export symbols by default, this is necessary for copy pasting the C and header file */
|
||||
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
|
||||
#define CJSON_EXPORT_SYMBOLS
|
||||
#endif
|
||||
|
||||
#if defined(CJSON_HIDE_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) type CJSON_STDCALL
|
||||
#elif defined(CJSON_EXPORT_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
|
||||
#elif defined(CJSON_IMPORT_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
|
||||
#endif
|
||||
#else /* !__WINDOWS__ */
|
||||
#define CJSON_CDECL
|
||||
#define CJSON_STDCALL
|
||||
|
||||
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
|
||||
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
|
||||
#else
|
||||
#define CJSON_PUBLIC(type) type
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* project version */
|
||||
#define CJSON_VERSION_MAJOR 1
|
||||
#define CJSON_VERSION_MINOR 7
|
||||
#define CJSON_VERSION_PATCH 12
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* cJSON Types: */
|
||||
#define cJSON_Invalid (0)
|
||||
#define cJSON_False (1 << 0)
|
||||
#define cJSON_True (1 << 1)
|
||||
#define cJSON_NULL (1 << 2)
|
||||
#define cJSON_Number (1 << 3)
|
||||
#define cJSON_String (1 << 4)
|
||||
#define cJSON_Array (1 << 5)
|
||||
#define cJSON_Object (1 << 6)
|
||||
#define cJSON_Raw (1 << 7) /* raw json */
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
#define cJSON_StringIsConst 512
|
||||
|
||||
/* The cJSON structure: */
|
||||
typedef struct cJSON
|
||||
{
|
||||
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||
struct cJSON *next;
|
||||
struct cJSON *prev;
|
||||
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||
struct cJSON *child;
|
||||
|
||||
/* The type of the item, as above. */
|
||||
int type;
|
||||
|
||||
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
|
||||
char *valuestring;
|
||||
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
|
||||
int valueint;
|
||||
/* The item's number, if type==cJSON_Number */
|
||||
double valuedouble;
|
||||
|
||||
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||
char *string;
|
||||
} cJSON;
|
||||
|
||||
typedef struct cJSON_Hooks
|
||||
{
|
||||
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
|
||||
void *(CJSON_CDECL *malloc_fn)(size_t sz);
|
||||
void (CJSON_CDECL *free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
typedef int cJSON_bool;
|
||||
|
||||
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
|
||||
* This is to prevent stack overflows. */
|
||||
#ifndef CJSON_NESTING_LIMIT
|
||||
#define CJSON_NESTING_LIMIT 1000
|
||||
#endif
|
||||
|
||||
/* Precision of double variables comparison */
|
||||
#ifndef CJSON_DOUBLE_PRECISION
|
||||
#define CJSON_DOUBLE_PRECISION .0000000000000001
|
||||
#endif
|
||||
|
||||
/* returns the version of cJSON as a string */
|
||||
CJSON_PUBLIC(const char*) cJSON_Version(void);
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||
|
||||
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
|
||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
|
||||
|
||||
/* Render a cJSON entity to text for transfer/storage. */
|
||||
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
|
||||
/* Render a cJSON entity to text for transfer/storage without any formatting. */
|
||||
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
|
||||
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
||||
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
|
||||
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
|
||||
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
||||
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
|
||||
|
||||
/* Check if the item is a string and return its valuestring */
|
||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
|
||||
|
||||
/* These functions check the type of an item */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
|
||||
/* raw json */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
|
||||
|
||||
/* Create a string where valuestring references a string so
|
||||
* it will not be freed by cJSON_Delete */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
|
||||
/* Create an object/array that only references it's elements so
|
||||
* they will not be freed by cJSON_Delete */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
|
||||
|
||||
/* These utilities create an Array of count items.
|
||||
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
||||
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
|
||||
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
|
||||
* writing to `item->string` */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
|
||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||
|
||||
/* Remove/Detach items from Arrays/Objects. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
|
||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||
* The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
|
||||
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
|
||||
|
||||
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
|
||||
* The input pointer json cannot point to a read-only address area, such as a string constant,
|
||||
* but should point to a readable and writable adress area. */
|
||||
CJSON_PUBLIC(void) cJSON_Minify(char *json);
|
||||
|
||||
/* Helper functions for creating and adding items to an object at the same time.
|
||||
* They return the added item or NULL on failure. */
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
|
||||
/* helper for the cJSON_SetNumberValue macro */
|
||||
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
|
||||
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
|
||||
|
||||
/* Macro for iterating over an array or object */
|
||||
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
|
||||
|
||||
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
|
||||
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
|
||||
CJSON_PUBLIC(void) cJSON_free(void *object);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* @file cjson_impl.c
|
||||
* @author sun_chb@126.com
|
||||
*/
|
||||
#include "cJSON.h"
|
||||
#include "cson_interface.h"
|
||||
#include "string.h"
|
||||
|
||||
cson_t cjson_impl_object_get(const cson_t object, const char* key){
|
||||
return cJSON_GetObjectItem((cJSON*)object, key);
|
||||
}
|
||||
|
||||
cson_type cjson_impl_typeof(cson_t object){
|
||||
switch(((cJSON*)object)->type){
|
||||
case cJSON_Invalid:
|
||||
case cJSON_NULL:
|
||||
return CSON_NULL;
|
||||
case cJSON_False:
|
||||
return CSON_FALSE;
|
||||
case cJSON_True:
|
||||
return CSON_TRUE;
|
||||
case cJSON_Number:
|
||||
return CSON_REAL;
|
||||
case cJSON_String:
|
||||
case cJSON_Raw:
|
||||
return CSON_STRING;
|
||||
case cJSON_Array:
|
||||
return CSON_ARRAY;
|
||||
case cJSON_Object:
|
||||
return CSON_OBJECT;
|
||||
default:
|
||||
return CSON_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
cson_t cjson_impl_loadb(const char *buffer, size_t buflen){
|
||||
return cJSON_Parse(buffer);
|
||||
}
|
||||
|
||||
void cjson_impl_decref(cson_t object){
|
||||
cJSON_Delete((cJSON*)object);
|
||||
}
|
||||
|
||||
const char *cjson_impl_string_value(const cson_t object){
|
||||
return cJSON_GetStringValue((cJSON*)object);
|
||||
}
|
||||
|
||||
size_t cjson_impl_string_length(const cson_t object){
|
||||
return strlen(cJSON_GetStringValue((cJSON*)object));
|
||||
}
|
||||
|
||||
long long cjson_impl_integer_value(const cson_t object){
|
||||
return ((cJSON*)object)->valueint;
|
||||
}
|
||||
|
||||
double cjson_impl_real_value(const cson_t object){
|
||||
return ((cJSON*)object)->valuedouble;
|
||||
}
|
||||
|
||||
char cjson_impl_bool_value(const cson_t object){
|
||||
return ((cJSON*)object)->type == cJSON_True;
|
||||
}
|
||||
|
||||
size_t cjson_impl_array_size(const cson_t object){
|
||||
return cJSON_GetArraySize((cJSON*)object);
|
||||
}
|
||||
|
||||
cson_t cjson_impl_array_get(const cson_t object, size_t index){
|
||||
return cJSON_GetArrayItem((cJSON*)object, index);
|
||||
}
|
||||
|
||||
cson_t cjson_impl_new(){
|
||||
return cJSON_CreateObject();
|
||||
}
|
||||
|
||||
char* cjson_impl_to_string(cson_t object){
|
||||
return cJSON_PrintUnformatted((cJSON*)object);
|
||||
}
|
||||
|
||||
cson_t cjson_impl_integer(long long val){
|
||||
cJSON* tmp = cJSON_CreateNumber(0);
|
||||
cJSON_SetNumberValue(tmp, val);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
cson_t cjson_impl_string(const char* val){
|
||||
return cJSON_CreateString(val);
|
||||
}
|
||||
|
||||
cson_t cjson_impl_bool(char val){
|
||||
return cJSON_CreateBool(val);
|
||||
}
|
||||
cson_t cjson_impl_real(double val){
|
||||
return cJSON_CreateNumber(val);
|
||||
}
|
||||
|
||||
cson_t cjson_impl_array(){
|
||||
return cJSON_CreateArray();
|
||||
}
|
||||
|
||||
int cjson_impl_array_add(cson_t array, cson_t obj){
|
||||
cJSON_AddItemToArray((cJSON*)array, (cJSON*)obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cjson_impl_object_set_new(cson_t rootObj, const char* field, cson_t obj){
|
||||
cJSON_AddItemToObject((cJSON*)rootObj, field, (cJSON*)obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cson_interface csomImpl = {
|
||||
cjson_impl_object_get,
|
||||
cjson_impl_typeof,
|
||||
cjson_impl_loadb,
|
||||
cjson_impl_decref,
|
||||
cjson_impl_string_value,
|
||||
cjson_impl_string_length,
|
||||
cjson_impl_integer_value,
|
||||
cjson_impl_real_value,
|
||||
cjson_impl_bool_value,
|
||||
cjson_impl_array_size,
|
||||
cjson_impl_array_get,
|
||||
cjson_impl_new,
|
||||
cjson_impl_to_string,
|
||||
cjson_impl_integer,
|
||||
cjson_impl_string,
|
||||
cjson_impl_bool,
|
||||
cjson_impl_real,
|
||||
cjson_impl_array,
|
||||
cjson_impl_array_add,
|
||||
cjson_impl_object_set_new
|
||||
};
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* @file jansson_impl.c
|
||||
* @author sun_chb@126.com
|
||||
*/
|
||||
#include "cson_interface.h"
|
||||
#include "jansson.h"
|
||||
|
||||
cson_t jansson_impl_object_get(const cson_t object, const char* key){
|
||||
return json_object_get((json_t*)object, key);
|
||||
}
|
||||
|
||||
cson_type jansson_impl_typeof(cson_t object){
|
||||
return (cson_type)json_typeof((json_t*)object);
|
||||
}
|
||||
|
||||
cson_t jansson_impl_loadb(const char *buffer, size_t buflen){
|
||||
json_error_t err;
|
||||
return json_loadb(buffer, buflen, JSON_DECODE_ANY, &err);
|
||||
}
|
||||
|
||||
void jansson_impl_decref(cson_t object){
|
||||
json_decref((json_t*)object);
|
||||
}
|
||||
|
||||
const char *jansson_impl_string_value(const cson_t object){
|
||||
return json_string_value((json_t*)object);
|
||||
}
|
||||
|
||||
size_t jansson_impl_string_length(const cson_t object){
|
||||
return json_string_length((json_t*)object);
|
||||
}
|
||||
|
||||
long long jansson_impl_integer_value(const cson_t object){
|
||||
return json_integer_value((json_t*)object);
|
||||
}
|
||||
|
||||
double jansson_impl_real_value(const cson_t object){
|
||||
return json_real_value((json_t*)object);
|
||||
}
|
||||
|
||||
char jansson_impl_bool_value(const cson_t object){
|
||||
return json_boolean_value((json_t*)object);
|
||||
}
|
||||
|
||||
size_t jansson_impl_array_size(const cson_t object){
|
||||
return json_array_size((json_t*)object);
|
||||
}
|
||||
|
||||
cson_t jansson_impl_array_get(const cson_t object, size_t index){
|
||||
return json_array_get((json_t*)object, index);
|
||||
}
|
||||
|
||||
cson_t jansson_impl_new(){
|
||||
return json_object();
|
||||
}
|
||||
|
||||
char* jansson_impl_to_string(cson_t object){
|
||||
return json_dumps((json_t*)object, JSON_COMPACT | JSON_PRESERVE_ORDER);
|
||||
}
|
||||
|
||||
cson_t jansson_impl_integer(long long val){
|
||||
return json_integer(val);
|
||||
}
|
||||
|
||||
cson_t jansson_impl_string(const char* val){
|
||||
return json_string(val);
|
||||
}
|
||||
|
||||
cson_t jansson_impl_bool(char val){
|
||||
return json_boolean(val);
|
||||
}
|
||||
|
||||
cson_t jansson_impl_real(double val){
|
||||
return json_real(val);
|
||||
}
|
||||
|
||||
cson_t jansson_impl_array(){
|
||||
return json_array();
|
||||
}
|
||||
|
||||
int jansson_impl_array_add(cson_t array, cson_t obj){
|
||||
return json_array_append_new((json_t*)array, (json_t*)obj);
|
||||
}
|
||||
|
||||
int jansson_impl_object_set_new(cson_t rootObj, const char* field, cson_t obj){
|
||||
return json_object_set_new((json_t*)rootObj, field, (json_t*)obj);
|
||||
}
|
||||
|
||||
cson_interface csomImpl = {
|
||||
jansson_impl_object_get,
|
||||
jansson_impl_typeof,
|
||||
jansson_impl_loadb,
|
||||
jansson_impl_decref,
|
||||
jansson_impl_string_value,
|
||||
jansson_impl_string_length,
|
||||
jansson_impl_integer_value,
|
||||
jansson_impl_real_value,
|
||||
jansson_impl_bool_value,
|
||||
jansson_impl_array_size,
|
||||
jansson_impl_array_get,
|
||||
jansson_impl_new,
|
||||
jansson_impl_to_string,
|
||||
jansson_impl_integer,
|
||||
jansson_impl_string,
|
||||
jansson_impl_bool,
|
||||
jansson_impl_real,
|
||||
jansson_impl_array,
|
||||
jansson_impl_array_add,
|
||||
jansson_impl_object_set_new
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
INC += -I../3rd/inc
|
||||
INC += -I../inc
|
||||
LIB_PATH += -L../3rd/lib
|
||||
LIB_PATH += -L../output
|
||||
CC=gcc
|
||||
test:test.c main.c
|
||||
@$(CC) $(INC) $(LIB_PATH) -g -o test test.c main.c -Wno-int-conversion -lcson -ljansson
|
||||
clean:
|
||||
@rm -rf test
|
|
@ -0,0 +1,11 @@
|
|||
extern void test1();
|
||||
//extern void test2();
|
||||
|
||||
#include "cson.h"
|
||||
#include "stdio.h"
|
||||
|
||||
void main()
|
||||
{
|
||||
test1();
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,229 @@
|
|||
#include "cson.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
/**
|
||||
* 该示例会使用cson解析如下所示播放列表。
|
||||
*
|
||||
{
|
||||
"name":"jay zhou",
|
||||
"creater":"dahuaxia",
|
||||
"songNum":2,
|
||||
"songList":[
|
||||
{
|
||||
"songName":"qilixiang",
|
||||
"signerName":"jay zhou",
|
||||
"albumName":"qilixiang",
|
||||
"url":"www.kugou.com",
|
||||
"duration":200,
|
||||
"paid":false,
|
||||
"price":6.6600000000000001,
|
||||
"lyricNum":2,
|
||||
"lyric":[
|
||||
{
|
||||
"time":1,
|
||||
"text":"Sparrow outside the window"
|
||||
},
|
||||
{
|
||||
"time":10,
|
||||
"text":"Multi mouth on the pole"
|
||||
}
|
||||
],
|
||||
"key":[
|
||||
1234,
|
||||
5678,
|
||||
9876
|
||||
]
|
||||
},
|
||||
{
|
||||
"songName":"dongfengpo",
|
||||
"signerName":"jay zhou",
|
||||
"albumName":"dongfengpo",
|
||||
"url":"music.qq.com",
|
||||
"duration":180,
|
||||
"paid":true,
|
||||
"price":0.88,
|
||||
"lyricNum":2,
|
||||
"lyric":[
|
||||
{
|
||||
"time":10,
|
||||
"text":"A sad parting, standing alone in the window"
|
||||
},
|
||||
{
|
||||
"time":20,
|
||||
"text":"I'm behind the door pretending you're not gone"
|
||||
}
|
||||
],
|
||||
"key":[
|
||||
1111,
|
||||
2222,
|
||||
3333
|
||||
]
|
||||
}
|
||||
],
|
||||
"extData":{
|
||||
"a":999,
|
||||
"b":1.05
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1)首先我们需要定义与上面json相对应的数据结构。于是有了@PlayList、@ExtData、@SongInfo、@Lyric。
|
||||
* 即使不实用cson,想要解析json,通常你也需要这么做。
|
||||
*
|
||||
* 注意:结构体属性名需与json中字段名一致;
|
||||
* 注意:当某个字段在json中被定义为数组时,那么该字段在结构体中要被声名为指针,并且增加数组size的字段。
|
||||
*
|
||||
* 2)为了C语言能够像java中通过反射来操作结构体中的属性,我们需要先为每个结构体定义一个用于查找结构体属性的“反射表”,
|
||||
* 即play_list_ref_tbl,ext_data_ref_tbl,song_ref_tbl,lyric_ref_tbl。
|
||||
* 有了这个反射表,我们可以迭代访问数组元素。不仅可以帮助我们完成json解析,当我们想要输出对象各属性值、或是释放
|
||||
* 指针指向的堆内存时也很有用。
|
||||
*
|
||||
* TODO:目前反射表的结构有些复杂,虽然提供了宏定义让它用来稍稍方便一些。需要对该结构做出优化。
|
||||
*
|
||||
* 3)正确的完成上面两步,解析工作其实基本上就要完成了。只要再调用csonJsonStr2Struct,所有的属性就都会正确的赋值到结构体。
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Step1:定义与json相对应的数据结构
|
||||
*/
|
||||
typedef struct {
|
||||
int time;
|
||||
char* text;
|
||||
} Lyric;
|
||||
|
||||
typedef struct {
|
||||
char* songName;
|
||||
char* signerName;
|
||||
char* albumName;
|
||||
char* url;
|
||||
int duration;
|
||||
int paid;
|
||||
double price;
|
||||
size_t lyricNum;
|
||||
Lyric* lyric;
|
||||
size_t keyNum;
|
||||
int* key;
|
||||
size_t strNum;
|
||||
char** strList;
|
||||
} SongInfo;
|
||||
|
||||
typedef struct {
|
||||
int a;
|
||||
double b;
|
||||
} ExtData;
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
char* creater;
|
||||
size_t songNum;
|
||||
SongInfo* songList;
|
||||
ExtData extData;
|
||||
} PlayList;
|
||||
|
||||
/*
|
||||
Step2:定义数据结构的反射表
|
||||
*/
|
||||
reflect_item_t lyric_ref_tbl[] = {
|
||||
_property_int(Lyric, time),
|
||||
_property_string(Lyric, text),
|
||||
_property_end()
|
||||
};
|
||||
|
||||
reflect_item_t song_ref_tbl[] = {
|
||||
_property_string(SongInfo, songName),
|
||||
_property_string(SongInfo, signerName),
|
||||
_property_string(SongInfo, albumName),
|
||||
_property_string(SongInfo, url),
|
||||
_property_int(SongInfo, duration),
|
||||
_property_bool(SongInfo, paid),
|
||||
_property_real(SongInfo, price),
|
||||
_property_int(SongInfo, lyricNum),
|
||||
_property_array_object(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum),
|
||||
_property_int(SongInfo, keyNum),
|
||||
_property_array_int(SongInfo, key, int, keyNum),
|
||||
_property_int(SongInfo, strNum),
|
||||
_property_array_string(SongInfo, strList, char*, strNum),
|
||||
_property_end()
|
||||
};
|
||||
|
||||
reflect_item_t ext_data_ref_tbl[] = {
|
||||
_property_int(ExtData, a),
|
||||
_property_real(ExtData, b),
|
||||
_property_end()
|
||||
};
|
||||
|
||||
reflect_item_t play_list_ref_tbl[] = {
|
||||
_property_string(PlayList, name),
|
||||
_property_string(PlayList, creater),
|
||||
_property_int(PlayList, songNum),
|
||||
_property_array_object(PlayList, songList, song_ref_tbl, SongInfo, songNum),
|
||||
_property_obj(PlayList, extData, ext_data_ref_tbl),
|
||||
_property_end()
|
||||
};
|
||||
|
||||
void printPlayList(PlayList* list);
|
||||
void freePlayList(PlayList* list);
|
||||
|
||||
const static char* jStr = "{\"name\":\"jay zhou\",\"creater\":\"dahuaxia\",\"songList\":[{\"songName\":\"qilixiang\",\"signerName\":\"jay zhou\",\"albumName\":\"qilixiang\",\"url\":\"www.kugou.com\",\"duration\":20093999939292928292234.1,\"paid\":false,\"price\":6.66,\"lyric\":[{\"time\":1,\"text\":\"Sparrow outside the window\"},{\"time\":10,\"text\":\"Multi mouth on the pole\"}],\"key\":[1111,2222,3333]},{\"songName\":\"dongfengpo\",\"signerName\":\"jay zhou\",\"albumName\":\"dongfengpo\",\"url\":\"music.qq.com\",\"duration\":180.9,\"paid\":true,\"price\":0.88,\"lyric\":[{\"time\":10,\"text\":\"A sad parting, standing alone in the window\"},{\"time\":20,\"text\":\"I'm behind the door pretending you're not gone\"}],\"key\":[1234,5678,9876],\"strList\":[\"abcd\",\"efgh\",\"ijkl\"]}],\"extData\":{\"a\":999,\"b\":1}}";
|
||||
|
||||
/*
|
||||
Step3:调用csonJsonStr2Struct/csonStruct2JsonStr实现反序列化和序列化
|
||||
*/
|
||||
void test1()
|
||||
{
|
||||
printf("=========================================\n");
|
||||
printf("\t\tRunning %s\n", __FUNCTION__);
|
||||
printf("=========================================\n");
|
||||
PlayList playList;
|
||||
|
||||
/* string to struct */
|
||||
int ret = csonJsonStr2Struct(jStr, &playList, play_list_ref_tbl);
|
||||
/* test print */
|
||||
printf("ret=%d\n", ret);
|
||||
printPlayList(&playList);
|
||||
|
||||
char* jstrOutput;
|
||||
ret = csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl);
|
||||
printf("ret=%d\nJson:%s\n", ret, jstrOutput);
|
||||
free(jstrOutput);
|
||||
freePlayList(&playList);
|
||||
}
|
||||
|
||||
void* printProperty(void* pData, const reflect_item_t* tbl)
|
||||
{
|
||||
if (tbl->type == CSON_ARRAY || tbl->type == CSON_OBJECT) return NULL;
|
||||
|
||||
if (tbl->type == CSON_INTEGER || tbl->type == CSON_TRUE || tbl->type == CSON_FALSE) printf("%s:%d\n", tbl->field, *(int*)pData);
|
||||
|
||||
if (tbl->type == CSON_REAL) printf("%s:%f\n", tbl->field, *(double*)pData);
|
||||
|
||||
if (tbl->type == CSON_STRING) printf("%s:%s\n", tbl->field, *((char**)pData));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* freePointer(void* pData, const reflect_item_t* tbl)
|
||||
{
|
||||
if (tbl->type == CSON_ARRAY || tbl->type == CSON_STRING) {
|
||||
printf("free field %s.\n", tbl->field);
|
||||
free(*(void**)pData);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void printPlayList(PlayList* list)
|
||||
{
|
||||
/* 调用loopProperty迭代结构体中的属性,完成迭代输出属性值 */
|
||||
csonLoopProperty(list, play_list_ref_tbl, printProperty);
|
||||
}
|
||||
|
||||
void freePlayList(PlayList* list)
|
||||
{
|
||||
/* 调用loopProperty迭代结构体中的属性,释放字符串和数组申请的内存空间 */
|
||||
csonLoopProperty(list, play_list_ref_tbl, freePointer);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file cson.h
|
||||
* @author sun_chb@126.com
|
||||
*/
|
||||
#ifndef _CSON_H_
|
||||
#define _CSON_H_
|
||||
|
||||
#include "cson_reflect.h"
|
||||
|
||||
/**
|
||||
* @brief error code of parser.
|
||||
*/
|
||||
#define ERR_NONE (0) /**< success */
|
||||
#define ERR_MEMORY (-1) /**< malloc failed */
|
||||
#define ERR_TYPE (-2) /**< type matching error */
|
||||
#define ERR_MISSING_FIELD (-3) /**< field not found */
|
||||
#define ERR_FORMAT (-4) /**< input json string format error */
|
||||
#define ERR_ARGS (-5) /**< args error */
|
||||
#define ERR_OVERFLOW (-6) /**< value overflow */
|
||||
|
||||
/**
|
||||
* @brief convert json string to struct object.
|
||||
*
|
||||
* @param jstr: json string
|
||||
* @param output: target object
|
||||
* @param tbl: property table of output.
|
||||
*
|
||||
* @return ERR_NONE on success, otherwise failed.
|
||||
*/
|
||||
int csonJsonStr2Struct(const char* jstr, void* output, const reflect_item_t* tbl);
|
||||
|
||||
/**
|
||||
* @brief convert struct object to json string.
|
||||
*
|
||||
* @param jstr: output json string
|
||||
* @param output: input struct object
|
||||
* @param tbl: property table of input.
|
||||
*
|
||||
* @return ERR_NONE on success, otherwise failed.
|
||||
*/
|
||||
int csonStruct2JsonStr(char** jstr, void* input, const reflect_item_t* tbl);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* @file cson_interface.h
|
||||
* @author sun_chb@126.com
|
||||
*/
|
||||
#ifndef _CSON_INTERFACE_
|
||||
#define _CSON_INTERFACE_
|
||||
|
||||
/**
|
||||
* Initially I used the Jansson library as a parser. The Jansson library
|
||||
* is powerful, but it obviously increases the size of the executable.
|
||||
* So, I found cjson, which is very small and convenient for code
|
||||
* integration. Now I want to support Jansson and cjson, so I need
|
||||
* to abstract the parser into an interface. Users can choose which one
|
||||
* to use, or define other parser which conforms to this interface.
|
||||
* */
|
||||
|
||||
/**
|
||||
* @brief the type of json object.
|
||||
*/
|
||||
typedef enum {
|
||||
CSON_OBJECT,
|
||||
CSON_ARRAY,
|
||||
CSON_STRING,
|
||||
CSON_INTEGER,
|
||||
CSON_REAL,
|
||||
CSON_TRUE,
|
||||
CSON_FALSE,
|
||||
CSON_NULL
|
||||
} cson_type;
|
||||
|
||||
typedef void* cson_t;
|
||||
|
||||
/**
|
||||
* @brief define the function type of json parse/pack function group
|
||||
*/
|
||||
typedef cson_t (*func_cson_object_get)(const cson_t object, const char* key);
|
||||
typedef cson_type (*func_cson_typeof)(cson_t object);
|
||||
typedef cson_t (*func_cson_loadb)(const char *buffer, size_t buflen);
|
||||
typedef void (*func_cson_decref)(cson_t object);
|
||||
typedef const char* (*func_cson_string_value)(const cson_t object);
|
||||
typedef size_t (*func_cson_string_length)(const cson_t object);
|
||||
typedef long long (*func_cson_integer_value)(const cson_t object);
|
||||
typedef double (*func_cson_real_value)(const cson_t object);
|
||||
typedef char (*func_cson_bool_value)(const cson_t object);
|
||||
typedef size_t (*func_cson_array_size)(const cson_t object);
|
||||
typedef cson_t (*func_cson_array_get)(const cson_t object, size_t index);
|
||||
typedef cson_t (*func_cson_new)();
|
||||
typedef char* (*func_cson_to_string)(cson_t object);
|
||||
typedef cson_t (*func_cson_integer)(long long val);
|
||||
typedef cson_t (*func_cson_string)(const char* val);
|
||||
typedef cson_t (*func_cson_bool)(char val);
|
||||
typedef cson_t (*func_cson_real)(double val);
|
||||
typedef cson_t (*func_cson_array)();
|
||||
typedef int (*func_cson_array_add)(cson_t array, cson_t obj);
|
||||
typedef int (*func_cson_object_set_new)(cson_t rootObj, const char* field, cson_t obj);
|
||||
|
||||
/**
|
||||
* @brief define the cson interface
|
||||
*/
|
||||
typedef struct {
|
||||
func_cson_object_get cson_object_get;
|
||||
func_cson_typeof cson_typeof;
|
||||
func_cson_loadb cson_loadb;
|
||||
func_cson_decref cson_decref;
|
||||
func_cson_string_value cson_string_value;
|
||||
func_cson_string_length cson_string_length;
|
||||
func_cson_integer_value cson_integer_value;
|
||||
func_cson_real_value cson_real_value;
|
||||
func_cson_bool_value cson_bool_value;
|
||||
func_cson_array_size cson_array_size;
|
||||
func_cson_array_get cson_array_get;
|
||||
func_cson_new cson_object;
|
||||
func_cson_to_string cson_to_string;
|
||||
func_cson_integer cson_integer;
|
||||
func_cson_string cson_string;
|
||||
func_cson_bool cson_bool;
|
||||
func_cson_real cson_real;
|
||||
func_cson_array cson_array;
|
||||
func_cson_array_add cson_array_add;
|
||||
func_cson_object_set_new cson_object_set_new;
|
||||
} cson_interface;
|
||||
|
||||
extern cson_interface csomImpl;
|
||||
|
||||
#define cson_object_get csomImpl.cson_object_get
|
||||
#define cson_typeof csomImpl.cson_typeof
|
||||
#define cson_loadb csomImpl.cson_loadb
|
||||
#define cson_decref csomImpl.cson_decref
|
||||
#define cson_string_value csomImpl.cson_string_value
|
||||
#define cson_string_length csomImpl.cson_string_length
|
||||
#define cson_integer_value csomImpl.cson_integer_value
|
||||
#define cson_real_value csomImpl.cson_real_value
|
||||
#define cson_bool_value csomImpl.cson_bool_value
|
||||
#define cson_array_size csomImpl.cson_array_size
|
||||
#define cson_array_get csomImpl.cson_array_get
|
||||
#define cson_object csomImpl.cson_object
|
||||
#define cson_to_string csomImpl.cson_to_string
|
||||
#define cson_integer csomImpl.cson_integer
|
||||
#define cson_string csomImpl.cson_string
|
||||
#define cson_bool csomImpl.cson_bool
|
||||
#define cson_real csomImpl.cson_real
|
||||
#define cson_array csomImpl.cson_array
|
||||
#define cson_array_add csomImpl.cson_array_add
|
||||
#define cson_object_set_new csomImpl.cson_object_set_new
|
||||
|
||||
#define cson_is_number(type) (type == CSON_REAL || type == CSON_INTEGER)
|
||||
#define cson_is_bool(type) (type == CSON_TRUE || type == CSON_FALSE)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,170 @@
|
|||
/**
|
||||
* @file cson_reflect.h
|
||||
* @author sun_chb@126.com
|
||||
*/
|
||||
#ifndef _REFLECT_H_
|
||||
#define _REFLECT_H_
|
||||
|
||||
#include "stddef.h"
|
||||
#include "cson_interface.h"
|
||||
|
||||
/**
|
||||
* @brief the description of property in struct.
|
||||
*
|
||||
* @TODO: Try to simplify the struct
|
||||
*/
|
||||
typedef struct reflect_item_t {
|
||||
char* field; /**< field */
|
||||
size_t offset; /**< offset of property */
|
||||
size_t size; /**< size of property */
|
||||
cson_type type; /**< corresponding json type */
|
||||
const struct reflect_item_t* reflect_tbl; /**< must be specified when type is object or object array */
|
||||
size_t arraySize; /**< size of per array item. must be specified when type is array */
|
||||
char* arrayCountField; /**< field saving array size */
|
||||
int nullable; /**< paser return failure when the field is not found and nullable equals to 0 */
|
||||
} reflect_item_t;
|
||||
|
||||
extern const reflect_item_t integerReflectTbl[];
|
||||
extern const reflect_item_t stringReflectTbl[];
|
||||
extern const reflect_item_t boolReflectTbl[];
|
||||
extern const reflect_item_t realReflectTbl[];
|
||||
|
||||
#define _offset(type, field) (&(((type*)0)->field))
|
||||
#define _size(type, field) (sizeof(((type*)0)->field))
|
||||
#define _property(type, field, jtype, tbl, nullable) {#field, _offset(type, field), _size(type, field), jtype, tbl, 0, NULL, nullable}
|
||||
#define _property_end() {NULL, 0, 0, CSON_NULL, NULL, 0, NULL, 1}
|
||||
|
||||
/**
|
||||
* @brief Declaring integer properties.
|
||||
*
|
||||
* @param type: type of struct
|
||||
* @param field: field name of properties
|
||||
*
|
||||
*/
|
||||
#define _property_int(type, field) _property(type, field, CSON_INTEGER, integerReflectTbl, 1)
|
||||
|
||||
/**
|
||||
* @brief Declaring real properties.
|
||||
*
|
||||
* @param type: type of struct
|
||||
* @param field: field name of properties
|
||||
*
|
||||
*/
|
||||
#define _property_real(type, field) _property(type, field, CSON_REAL, realReflectTbl, 1)
|
||||
|
||||
/**
|
||||
* @brief Declaring bool properties.
|
||||
*
|
||||
* @param type: type of struct
|
||||
* @param field: field name of properties
|
||||
*
|
||||
*/
|
||||
#define _property_bool(type, field) _property(type, field, CSON_TRUE, boolReflectTbl, 1)
|
||||
|
||||
/**
|
||||
* @brief Declaring string properties.
|
||||
*
|
||||
* @param type: type of struct
|
||||
* @param field: field name of properties
|
||||
*
|
||||
*/
|
||||
#define _property_string(type, field) _property(type, field, CSON_STRING, stringReflectTbl, 1)
|
||||
|
||||
/**
|
||||
* @brief Declaring struct properties.
|
||||
*
|
||||
* @param type: type of struct
|
||||
* @param field: field name of properties
|
||||
* @param tbl: property description table of sub-struct
|
||||
*
|
||||
*/
|
||||
#define _property_obj(type, field, tbl) _property(type, field, CSON_OBJECT, tbl, 1)
|
||||
|
||||
/**
|
||||
* @brief Declaring array properties.
|
||||
*
|
||||
* @param type: type of struct
|
||||
* @param field: field name of properties
|
||||
* @param tbl: property description table of type of array
|
||||
* @param subType: type of array
|
||||
* @param count: property to save the array size
|
||||
*
|
||||
*/
|
||||
#define _property_array(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, 1}
|
||||
#define _property_array_object(type, field, tbl, subType, count) _property_array(type, field, tbl, subType, count)
|
||||
#define _property_array_int(type, field, subType, count) _property_array(type, field, integerReflectTbl, subType, count)
|
||||
#define _property_array_string(type, field, subType, count) _property_array(type, field, stringReflectTbl, subType, count)
|
||||
#define _property_array_real(type, field, subType, count) _property_array(type, field, realReflectTbl, subType, count)
|
||||
#define _property_array_bool(type, field, subType, count) _property_array(type, field, boolReflectTbl, subType, count)
|
||||
|
||||
/**
|
||||
* @brief nonull definitions. parser will stop and return error code when field not found which declared whit it.
|
||||
*
|
||||
* @param refer to comment of nullable definition
|
||||
*/
|
||||
#define _property_int_nonull(type, field) _property(type, field, CSON_INTEGER, NULL, 0)
|
||||
#define _property_real_nonull(type, field) _property(type, field, CSON_REAL, NULL, 0)
|
||||
#define _property_bool_nonull(type, field) _property(type, field, CSON_TRUE, NULL, 0)
|
||||
#define _property_string_nonull(type, field) _property(type, field, CSON_STRING, NULL, 0)
|
||||
#define _property_obj_nonull(type, field, tbl) _property(type, field, CSON_OBJECT, tbl, 0)
|
||||
#define _property_array_nonull(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, 0}
|
||||
#define _property_array_object_nonull(type, field, tbl, subType, count) _property_array_nonull(type, field, tbl, subType, count)
|
||||
#define _property_array_int_nonull(type, field, subType, count) _property_array_nonull(type, field, integerReflectTbl, subType, count)
|
||||
#define _property_array_string_nonull(type, field, subType, count) _property_array_nonull(type, field, stringReflectTbl, subType, count)
|
||||
#define _property_array_real_nonull(type, field, subType, count) _property_array_nonull(type, field, realReflectTbl, subType, count)
|
||||
#define _property_array_bool_nonull(type, field, subType, count) _property_array_nonull(type, field, boolReflectTbl, subType, count)
|
||||
/**
|
||||
* @brief get the address of field by retrieve the property table.
|
||||
*
|
||||
* @param obj: object to be operated.
|
||||
* @param field:
|
||||
* @param tbl: property table of the type.
|
||||
*
|
||||
* @return address of field.
|
||||
*/
|
||||
void* csonGetProperty(void* obj, const char* field, const reflect_item_t* tbl);
|
||||
|
||||
/**
|
||||
* @brief set the field of object to specified data.
|
||||
*
|
||||
* @param obj: object to be operated.
|
||||
* @param field:
|
||||
* @param data: pointer of specified data.
|
||||
* @param tbl: property table of the type.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void csonSetProperty(void* obj, const char* field, void* data, const reflect_item_t* tbl);
|
||||
|
||||
/**
|
||||
* @brief set the field of object to specified data without retrieve the property table.
|
||||
*
|
||||
* @param obj: object to be operated.
|
||||
* @param data: pointer of specified data.
|
||||
* @param tbl: property of field.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void csonSetPropertyFast(void* obj, const void* data, const reflect_item_t* tbl);
|
||||
|
||||
/**
|
||||
* @brief function type of csonLoopProperty.
|
||||
*
|
||||
* @param obj: pointer of property.
|
||||
* @param tbl: property of field.
|
||||
*
|
||||
* @return void*(reserved).
|
||||
*/
|
||||
typedef void* (*loop_func_t)(void* pData, const reflect_item_t* tbl);
|
||||
|
||||
/**
|
||||
* @brief loop all property and process property by @func
|
||||
*
|
||||
* @param obj: object to be operated.
|
||||
* @param tbl: property of field.
|
||||
* @param func: callback
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void csonLoopProperty(void* obj, const reflect_item_t* tbl, loop_func_t func);
|
||||
#endif
|
|
@ -0,0 +1,211 @@
|
|||
/**
|
||||
* @file cson_packer.c
|
||||
* @author sun_chb@126.com
|
||||
*/
|
||||
#include "cson.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
typedef int (*json_pack_proc)(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
|
||||
|
||||
static int getJsonObject(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
|
||||
static int getJsonArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
|
||||
static int getJsonString(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
|
||||
static int getJsonInteger(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
|
||||
static int getJsonReal(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
|
||||
static int getJsonBool(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
|
||||
|
||||
json_pack_proc jsonPackTbl[] = {
|
||||
getJsonObject,
|
||||
getJsonArray,
|
||||
getJsonString,
|
||||
getJsonInteger,
|
||||
getJsonReal,
|
||||
getJsonBool,
|
||||
getJsonBool,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int csonStruct2JsonObj(cson_t obj, void* input, const reflect_item_t* tbl);
|
||||
|
||||
int csonStruct2JsonStr(char** jstr, void* input, const reflect_item_t* tbl)
|
||||
{
|
||||
cson_t jsonPack = cson_object();
|
||||
|
||||
if (!jsonPack) return ERR_MEMORY;
|
||||
|
||||
int ret = csonStruct2JsonObj(jsonPack, input, tbl);
|
||||
|
||||
if (ret == ERR_NONE) {
|
||||
char* dumpStr = cson_to_string(jsonPack);
|
||||
if (dumpStr == NULL) {
|
||||
ret = ERR_MEMORY;
|
||||
} else {
|
||||
*jstr = dumpStr;
|
||||
}
|
||||
}
|
||||
|
||||
cson_decref(jsonPack);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int csonStruct2JsonObj(cson_t obj, void* input, const reflect_item_t* tbl)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = ERR_NONE;
|
||||
|
||||
if (!obj || !input || !tbl) return ERR_ARGS;
|
||||
|
||||
while (1) {
|
||||
if (tbl[i].field == NULL) break;
|
||||
|
||||
cson_t joTmp = NULL;
|
||||
int jsonType = tbl[i].type;
|
||||
|
||||
if (jsonPackTbl[jsonType] != NULL) {
|
||||
ret = jsonPackTbl[jsonType](input, tbl, i, &joTmp);
|
||||
}
|
||||
|
||||
if (ret != ERR_NONE ) {
|
||||
printf("!!!!pack error on field:%s, cod=%d!!!!\n", tbl[i].field, ret);
|
||||
if (!tbl[i].nullable) return ret;
|
||||
} else {
|
||||
cson_object_set_new(obj, tbl[i].field, joTmp);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int getJsonInteger(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
|
||||
{
|
||||
if(tbl[index].size != sizeof(char) &&
|
||||
tbl[index].size != sizeof(short) &&
|
||||
tbl[index].size != sizeof(int) &&
|
||||
tbl[index].size != sizeof(long long)){
|
||||
printf("Unsupported size(=%ld) of integer.\n", tbl[index].size);
|
||||
printf("Please check if the type of field %s in char/short/int/long long!\n", tbl[index].field);
|
||||
return ERR_OVERFLOW;
|
||||
}
|
||||
|
||||
void* pSrc = (void*)((char*)input + tbl[index].offset);
|
||||
|
||||
if(tbl[index].size == sizeof(char)){
|
||||
*obj = cson_integer(*((char*)pSrc));
|
||||
}else if(tbl[index].size == sizeof(short)){
|
||||
*obj = cson_integer(*((short*)pSrc));
|
||||
}else if(tbl[index].size == sizeof(int)){
|
||||
*obj = cson_integer(*((int*)pSrc));
|
||||
}else{
|
||||
*obj = cson_integer(*((long long*)pSrc));
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int getJsonString(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
|
||||
{
|
||||
void* pSrc = (void*)((char*)input + tbl[index].offset);
|
||||
|
||||
if (*((char**)pSrc) == NULL) return ERR_MISSING_FIELD;
|
||||
|
||||
*obj = cson_string(*((char**)pSrc));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int getJsonObject(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
|
||||
{
|
||||
void* pSrc = (void*)((char*)input + tbl[index].offset);
|
||||
cson_t jotmp = cson_object();
|
||||
int ret = csonStruct2JsonObj(jotmp, pSrc, tbl[index].reflect_tbl);
|
||||
|
||||
if (ret == ERR_NONE) {
|
||||
*obj = jotmp;
|
||||
} else {
|
||||
cson_decref(jotmp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getJsonArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
|
||||
{
|
||||
int ret = ERR_NONE;
|
||||
char* pSrc = (*(char**)((char*)input + tbl[index].offset));
|
||||
|
||||
if (pSrc == NULL) return ERR_MISSING_FIELD;
|
||||
|
||||
cson_t joArray = cson_array();
|
||||
|
||||
size_t size = *((size_t*)csonGetProperty(input, tbl[index].arrayCountField, tbl));
|
||||
|
||||
size_t successCount = 0;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
cson_t jotmp = cson_object();
|
||||
|
||||
if(tbl[index].reflect_tbl[0].field[0] == '0'){ /* field start with '0' mean basic types. */
|
||||
ret = jsonPackTbl[tbl[index].reflect_tbl[0].type](pSrc + (i * tbl[index].arraySize), tbl[index].reflect_tbl, 0, &jotmp);
|
||||
}else{
|
||||
ret = csonStruct2JsonObj(jotmp, pSrc + (i * tbl[index].arraySize), tbl[index].reflect_tbl);
|
||||
}
|
||||
|
||||
if (ret == ERR_NONE) {
|
||||
successCount++;
|
||||
cson_array_add(joArray, jotmp);
|
||||
} else {
|
||||
cson_decref(jotmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (successCount == 0) {
|
||||
cson_decref(joArray);
|
||||
return ERR_MISSING_FIELD;
|
||||
} else {
|
||||
*obj = joArray;
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getJsonReal(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
|
||||
{
|
||||
if(tbl[index].size != sizeof(double)){
|
||||
printf("Unsupported size(=%ld) of real.\n", tbl[index].size);
|
||||
printf("Please check if the type of field %s is double!\n", tbl[index].field);
|
||||
return ERR_OVERFLOW;
|
||||
}
|
||||
|
||||
void* pSrc = (void*)((char*)input + tbl[index].offset);
|
||||
*obj = cson_real(*((double*)pSrc));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int getJsonBool(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
|
||||
{
|
||||
if(tbl[index].size != sizeof(char) &&
|
||||
tbl[index].size != sizeof(short) &&
|
||||
tbl[index].size != sizeof(int) &&
|
||||
tbl[index].size != sizeof(long long)){
|
||||
printf("Unsupported size(=%ld) of bool.\n", tbl[index].size);
|
||||
printf("Please check if the type of field %s in char/short/int/long long!\n", tbl[index].field);
|
||||
return ERR_OVERFLOW;
|
||||
}
|
||||
|
||||
void* pSrc = (void*)((char*)input + tbl[index].offset);
|
||||
|
||||
if(tbl[index].size == sizeof(char)){
|
||||
*obj = cson_bool(*((char*)pSrc));
|
||||
}else if(tbl[index].size == sizeof(short)){
|
||||
*obj = cson_bool(*((short*)pSrc));
|
||||
}else if(tbl[index].size == sizeof(int)){
|
||||
*obj = cson_bool(*((int*)pSrc));
|
||||
}else{
|
||||
*obj = cson_bool(*((long long*)pSrc));
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
/**
|
||||
* @file cson_parser.h
|
||||
* @author sun_chb@126.com
|
||||
*/
|
||||
#include "cson.h"
|
||||
#include "string.h"
|
||||
#include "limits.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
typedef int (*json_obj_proc)(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
|
||||
static int parseJsonObject(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonString(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonInteger(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonReal(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonBool(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
|
||||
json_obj_proc jsonObjProcTbl[] = {
|
||||
parseJsonObject,
|
||||
parseJsonArray,
|
||||
parseJsonString,
|
||||
parseJsonInteger,
|
||||
parseJsonReal,
|
||||
parseJsonBool,
|
||||
parseJsonBool,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int parseJsonObjectDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonArrayDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonStringDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonIntegerDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
static int parseJsonRealDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
|
||||
|
||||
json_obj_proc jsonObjDefaultTbl[] = {
|
||||
parseJsonObjectDefault,
|
||||
parseJsonArrayDefault,
|
||||
parseJsonStringDefault,
|
||||
parseJsonIntegerDefault,
|
||||
parseJsonRealDefault,
|
||||
parseJsonIntegerDefault,
|
||||
parseJsonIntegerDefault,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int csonJsonObj2Struct(cson_t jo, void* output, const reflect_item_t* tbl);
|
||||
|
||||
int csonJsonStr2Struct(const char* jstr, void* output, const reflect_item_t* tbl)
|
||||
{
|
||||
/* load json string */
|
||||
cson_t jo = cson_loadb(jstr, strlen(jstr));
|
||||
|
||||
if (!jo) return ERR_FORMAT;
|
||||
|
||||
int ret = csonJsonObj2Struct(jo, output, tbl);
|
||||
cson_decref(jo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int csonJsonObj2Struct(cson_t jo, void* output, const reflect_item_t* tbl)
|
||||
{
|
||||
if (!jo || !output || !tbl) return ERR_ARGS;
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
int ret = ERR_NONE;
|
||||
if (tbl[i].field == NULL) break;
|
||||
|
||||
cson_t jo_tmp = cson_object_get(jo, tbl[i].field);
|
||||
|
||||
if (jo_tmp == NULL) {
|
||||
ret = ERR_MISSING_FIELD;
|
||||
} else {
|
||||
|
||||
int jsonType = cson_typeof(jo_tmp);
|
||||
|
||||
if (jsonType == tbl[i].type ||
|
||||
(cson_is_number(cson_typeof(jo_tmp)) && cson_is_number(tbl[i].type)) ||
|
||||
(cson_is_bool(cson_typeof(jo_tmp)) && cson_is_bool(tbl[i].type))) {
|
||||
if (jsonObjProcTbl[tbl[i].type] != NULL) {
|
||||
ret = jsonObjProcTbl[tbl[i].type](jo_tmp, output, tbl, i);
|
||||
}
|
||||
} else {
|
||||
ret = ERR_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != ERR_NONE ) {
|
||||
printf("!!!!parse error on field:%s, cod=%d!!!!\n", tbl[i].field, ret);
|
||||
jsonObjDefaultTbl[tbl[i].type](NULL, output, tbl, i);
|
||||
if (!tbl[i].nullable) return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int parseJsonString(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
|
||||
{
|
||||
const char* tempstr = cson_string_value(jo_tmp);
|
||||
if (NULL != tempstr) {
|
||||
char* pDst = malloc(strlen(tempstr) + 1);
|
||||
if (pDst == NULL) {
|
||||
return ERR_MEMORY;
|
||||
}
|
||||
strcpy(pDst, tempstr);
|
||||
csonSetPropertyFast(output, &pDst, tbl + index);
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
return ERR_MISSING_FIELD;
|
||||
}
|
||||
|
||||
|
||||
int parseJsonInteger(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
|
||||
{
|
||||
union{
|
||||
char c;
|
||||
short s;
|
||||
int i;
|
||||
long long l;
|
||||
}ret;
|
||||
|
||||
long long temp;
|
||||
if(cson_typeof(jo_tmp) == CSON_INTEGER){
|
||||
temp = cson_integer_value(jo_tmp);
|
||||
}else{
|
||||
double tempDouble = cson_real_value(jo_tmp);
|
||||
if(tempDouble > LLONG_MAX || tempDouble < LLONG_MIN){
|
||||
printf("value of field %s overflow.size=%ld,value=%f.\n", tbl[index].field, tbl[index].size, tempDouble);
|
||||
return ERR_OVERFLOW;
|
||||
}else{
|
||||
temp = tempDouble;
|
||||
}
|
||||
}
|
||||
|
||||
if(tbl[index].size != sizeof(char) &&
|
||||
tbl[index].size != sizeof(short) &&
|
||||
tbl[index].size != sizeof(int) &&
|
||||
tbl[index].size != sizeof(long long)){
|
||||
printf("Unsupported size(=%ld) of integer.\n", tbl[index].size);
|
||||
printf("Please check if the type of field %s in char/short/int/long long!\n", tbl[index].field);
|
||||
return ERR_OVERFLOW;
|
||||
}
|
||||
|
||||
if(tbl[index].size == sizeof(char) && (temp > CHAR_MAX || temp < CHAR_MIN)){
|
||||
printf("value of field %s overflow.size=%ld,value=%lld.\n", tbl[index].field, tbl[index].size, temp);
|
||||
return ERR_OVERFLOW;
|
||||
}else if(tbl[index].size == sizeof(short) && (temp > SHRT_MAX || temp < SHRT_MIN)){
|
||||
printf("value of field %s overflow.size=%ld,value=%lld.\n", tbl[index].field, tbl[index].size, temp);
|
||||
return ERR_OVERFLOW;
|
||||
}else if(tbl[index].size == sizeof(int) && (temp > INT_MAX || temp < INT_MIN)){
|
||||
printf("value of field %s overflow.size=%ld,value=%lld.\n", tbl[index].field, tbl[index].size, temp);
|
||||
return ERR_OVERFLOW;
|
||||
}else{
|
||||
}
|
||||
|
||||
/* avoid error on big endian */
|
||||
if(tbl[index].size == sizeof(char)){
|
||||
ret.c = temp;
|
||||
}else if(tbl[index].size == sizeof(short)){
|
||||
ret.s = temp;
|
||||
}else if(tbl[index].size == sizeof(int)){
|
||||
ret.i = temp;
|
||||
}else{
|
||||
ret.l = temp;
|
||||
}
|
||||
|
||||
csonSetPropertyFast(output, &ret, tbl + index);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
int parseJsonObject(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
|
||||
{
|
||||
return csonJsonObj2Struct(jo_tmp, (char*)output + tbl[index].offset, tbl[index].reflect_tbl);
|
||||
}
|
||||
|
||||
int parseJsonArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
|
||||
{
|
||||
size_t arraySize = cson_array_size(jo_tmp);
|
||||
|
||||
if (arraySize == 0) {
|
||||
csonSetProperty(output, tbl->arrayCountField, &arraySize, tbl);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
char* pMem = (char*)malloc(arraySize * tbl[index].arraySize);
|
||||
if (pMem == NULL) return ERR_MEMORY;
|
||||
|
||||
size_t successCount = 0;
|
||||
for (int j = 0; j < arraySize; j++) {
|
||||
cson_t item = cson_array_get(jo_tmp, j);
|
||||
if (item != NULL) {
|
||||
int ret;
|
||||
|
||||
if(tbl[index].reflect_tbl[0].field[0] == '0'){ /* field start with '0' mean basic types. */
|
||||
ret = jsonObjProcTbl[tbl[index].reflect_tbl[0].type](item, pMem + (successCount * tbl[index].arraySize), tbl[index].reflect_tbl, 0);
|
||||
}else{
|
||||
ret = csonJsonObj2Struct(item, pMem + (successCount * tbl[index].arraySize), tbl[index].reflect_tbl);
|
||||
}
|
||||
|
||||
if (ret == ERR_NONE) {
|
||||
successCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (successCount == 0) {
|
||||
csonSetProperty(output, tbl[index].arrayCountField, &successCount, tbl);
|
||||
free(pMem);
|
||||
pMem = NULL;
|
||||
csonSetPropertyFast(output, &pMem, tbl + index);
|
||||
return ERR_MISSING_FIELD;
|
||||
} else {
|
||||
csonSetProperty(output, tbl[index].arrayCountField, &successCount, tbl);
|
||||
csonSetPropertyFast(output, &pMem, tbl + index);
|
||||
return ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
int parseJsonReal(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
|
||||
{
|
||||
if(tbl[index].size != sizeof(double)){
|
||||
printf("Unsupported size(=%ld) of real.\n", tbl[index].size);
|
||||
printf("Please check if the type of field %s is double!\n", tbl[index].field);
|
||||
return ERR_OVERFLOW;
|
||||
}
|
||||
|
||||
double temp;
|
||||
if(cson_typeof(jo_tmp) == CSON_REAL){
|
||||
temp = cson_real_value(jo_tmp);
|
||||
}else{
|
||||
temp = cson_integer_value(jo_tmp);
|
||||
}
|
||||
|
||||
csonSetPropertyFast(output, &temp, tbl + index);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int parseJsonBool(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
|
||||
{
|
||||
if(tbl[index].size != sizeof(char) &&
|
||||
tbl[index].size != sizeof(short) &&
|
||||
tbl[index].size != sizeof(int) &&
|
||||
tbl[index].size != sizeof(long long)){
|
||||
printf("Unsupported size(=%ld) of bool.\n", tbl[index].size);
|
||||
printf("Please check if the type of field %s in char/short/int/long long!\n", tbl[index].field);
|
||||
return ERR_OVERFLOW;
|
||||
}
|
||||
|
||||
union{
|
||||
char c;
|
||||
short s;
|
||||
int i;
|
||||
long long l;
|
||||
}temp;
|
||||
|
||||
/* avoid error on big endian */
|
||||
if(tbl[index].size == sizeof(char)){
|
||||
temp.c = cson_bool_value(jo_tmp);
|
||||
}else if(tbl[index].size == sizeof(short)){
|
||||
temp.s = cson_bool_value(jo_tmp);
|
||||
}else if(tbl[index].size == sizeof(int)){
|
||||
temp.i = cson_bool_value(jo_tmp);
|
||||
}else{
|
||||
temp.l = cson_bool_value(jo_tmp);
|
||||
}
|
||||
|
||||
csonSetPropertyFast(output, &temp, tbl + index);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int parseJsonObjectDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index){
|
||||
int i = 0;
|
||||
while(1){
|
||||
if (tbl[index].reflect_tbl[i].field == NULL) break;
|
||||
jsonObjDefaultTbl[tbl[index].reflect_tbl[i].type](NULL, output, tbl[index].reflect_tbl, i);
|
||||
i++;
|
||||
};
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int parseJsonArrayDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index){
|
||||
void* temp = NULL;
|
||||
csonSetPropertyFast(output, &temp, tbl + index);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int parseJsonStringDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index){
|
||||
char* temp = NULL;
|
||||
csonSetPropertyFast(output, &temp, tbl + index);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int parseJsonIntegerDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index){
|
||||
long long temp = 0;
|
||||
|
||||
if(tbl[index].size != sizeof(char) &&
|
||||
tbl[index].size != sizeof(short) &&
|
||||
tbl[index].size != sizeof(int) &&
|
||||
tbl[index].size != sizeof(long long)){
|
||||
printf("Unsupported size(=%ld) of bool.\n", tbl[index].size);
|
||||
printf("Please check if the type of field %s in char/short/int/long long!\n", tbl[index].field);
|
||||
return ERR_OVERFLOW;
|
||||
}
|
||||
|
||||
union{
|
||||
char c;
|
||||
short s;
|
||||
int i;
|
||||
long long l;
|
||||
}ret;
|
||||
|
||||
/* avoid error on big endian */
|
||||
if(tbl[index].size == sizeof(char)){
|
||||
ret.c = temp;
|
||||
}else if(tbl[index].size == sizeof(short)){
|
||||
ret.s = temp;
|
||||
}else if(tbl[index].size == sizeof(int)){
|
||||
ret.i = temp;
|
||||
}else{
|
||||
ret.l = temp;
|
||||
}
|
||||
|
||||
csonSetPropertyFast(output, &ret, tbl + index);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
int parseJsonRealDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index){
|
||||
if(tbl[index].size != sizeof(double)){
|
||||
printf("Unsupported size(=%ld) of bool.\n", tbl[index].size);
|
||||
printf("Please check if the type of field %s is double!\n", tbl[index].field);
|
||||
return ERR_OVERFLOW;
|
||||
}
|
||||
|
||||
double temp = 0.0;
|
||||
csonSetPropertyFast(output, &temp, tbl + index);
|
||||
return ERR_NONE;
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* @file cson_reflect.c
|
||||
* @author sun_chb@126.com
|
||||
*/
|
||||
#include "cson_reflect.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
const reflect_item_t integerReflectTbl[] = {
|
||||
{"0Integer", 0, sizeof(int), CSON_INTEGER, NULL, 0, NULL, 1},
|
||||
{}
|
||||
};
|
||||
|
||||
const reflect_item_t stringReflectTbl[] = {
|
||||
{"0String", 0, sizeof(char*), CSON_STRING, NULL, 0, NULL, 1},
|
||||
{}
|
||||
};
|
||||
|
||||
const reflect_item_t realReflectTbl[] = {
|
||||
{"0Real", 0, sizeof(double), CSON_REAL, NULL, 0, NULL, 1},
|
||||
{}
|
||||
};
|
||||
|
||||
const reflect_item_t boolReflectTbl[] = {
|
||||
{"0Bool", 0, sizeof(int), CSON_TRUE, NULL, 0, NULL, 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const reflect_item_t* getReflexItem(const char* field, const reflect_item_t* tbl)
|
||||
{
|
||||
const reflect_item_t* ret = NULL;
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
if (!(tbl[i].field)) break;
|
||||
if (strcmp(field, tbl[i].field) == 0) {
|
||||
ret = &(tbl[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret) printf("Can not find field:%s.", field);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* csonGetProperty(void* obj, const char* field, const reflect_item_t* tbl)
|
||||
{
|
||||
if (!(obj && field && tbl)) return NULL;
|
||||
const reflect_item_t* ret = getReflexItem(field, tbl);
|
||||
|
||||
if (!ret) return NULL;
|
||||
|
||||
return (void*)((char*)obj + ret->offset);
|
||||
}
|
||||
|
||||
void csonSetProperty(void* obj, const char* field, void* data, const reflect_item_t* tbl)
|
||||
{
|
||||
if (!(obj && field && data && tbl)) return;
|
||||
|
||||
const reflect_item_t* ret = getReflexItem(field, tbl);
|
||||
|
||||
if (!ret) return;
|
||||
|
||||
void* pDst = (void*)((char*)obj + ret->offset);
|
||||
memcpy(pDst, data, ret->size);
|
||||
return;
|
||||
}
|
||||
|
||||
void csonSetPropertyFast(void* obj, const void* data, const reflect_item_t* tbl)
|
||||
{
|
||||
if (!(obj && data && tbl)) return;
|
||||
|
||||
void* pDst = (void*)((char*)obj + tbl->offset);
|
||||
memcpy(pDst, data, tbl->size);
|
||||
return;
|
||||
}
|
||||
|
||||
void csonLoopProperty(void* pData, const reflect_item_t* tbl, loop_func_t func)
|
||||
{
|
||||
int i = 0;
|
||||
while (1) {
|
||||
if (!tbl[i].field) break;
|
||||
|
||||
char* pProperty = (char*)pData + tbl[i].offset;
|
||||
if (tbl[i].type == CSON_ARRAY) {
|
||||
size_t size = *((size_t*)csonGetProperty(pData, tbl[i].arrayCountField, tbl));
|
||||
for (int j = 0; j < size; j++) {
|
||||
csonLoopProperty(*((char**)pProperty) + j * tbl[i].arraySize, tbl[i].reflect_tbl, func);
|
||||
}
|
||||
} else if (tbl[i].type == CSON_OBJECT) {
|
||||
csonLoopProperty(pProperty, tbl[i].reflect_tbl, func);
|
||||
}
|
||||
|
||||
func(pProperty, tbl + i);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue