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