cson commit

This commit is contained in:
sunchb 2019-12-24 23:13:45 -08:00
commit 7cb343e85c
19 changed files with 5423 additions and 0 deletions

367
3rd/inc/jansson.h Normal file
View File

@ -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

51
3rd/inc/jansson_config.h Normal file
View File

@ -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

BIN
3rd/lib/libjansson.a Normal file

Binary file not shown.

21
LICENSE Normal file
View File

@ -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.

44
Makefile Normal file
View File

@ -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)

202
README.md Normal file
View File

@ -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

2979
adapter/cjson/cJSON.c Normal file

File diff suppressed because it is too large Load Diff

293
adapter/cjson/cJSON.h Normal file
View File

@ -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

132
adapter/cjson/cjson_impl.c Normal file
View File

@ -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
};

View File

@ -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
};

9
demo/Makefile Normal file
View File

@ -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

11
demo/main.c Normal file
View File

@ -0,0 +1,11 @@
extern void test1();
//extern void test2();
#include "cson.h"
#include "stdio.h"
void main()
{
test1();
return;
}

229
demo/test.c Normal file
View File

@ -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
}
}
*/
/**
* 1json相对应的数据结构@PlayList@ExtData@SongInfo@Lyric
* 使csonjson
*
* :json中字段名一致;
* :json中被定义为数组时size的字段
*
* 2C语言能够像java中通过反射来操作结构体中的属性
* play_list_ref_tblext_data_ref_tblsong_ref_tbllyric_ref_tbl
* 访json解析
*
*
* TODO:便
*
* 3csonJsonStr2Struct
*
*/
/*
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);
}

43
inc/cson.h Normal file
View File

@ -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

109
inc/cson_interface.h Normal file
View File

@ -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

170
inc/cson_reflect.h Normal file
View File

@ -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

211
src/cson_packer.c Normal file
View File

@ -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;
}

343
src/cson_parser.c Normal file
View File

@ -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;
}

99
src/cson_reflect.c Normal file
View File

@ -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++;
}
}