├── .vscode └── settings.json ├── cmake └── FindJEMALLOC.cmake ├── .gitignore ├── 3rdpart └── jsoncpp │ ├── json.h │ ├── version.h │ ├── version.h.in │ ├── autolink.h │ ├── forwards.h │ ├── features.h │ ├── assertions.h │ ├── json_tool.h │ ├── config.h │ ├── json_valueiterator.inl │ ├── writer.h │ ├── reader.h │ └── value.h ├── README.md ├── src ├── source │ ├── tinybuf_private.h │ ├── tinybuf_buffer_private.h │ ├── tinybuf_memory.c │ ├── tinybuf_log.c │ ├── tinybuf_buffer.c │ ├── avl-tree.h │ ├── avl-tree.c │ ├── tinybuf.c │ └── tinybuf_json.c └── include │ ├── tinybuf_memory.h │ ├── tinybuf_log.h │ ├── tinybuf_buffer.h │ └── tinybuf.h ├── CMakeLists.txt └── benchmark.cpp /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "stdarg.h": "c", 4 | "iosfwd": "cpp" 5 | } 6 | } -------------------------------------------------------------------------------- /cmake/FindJEMALLOC.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | find_path(JEMALLOC_INCLUDE_DIR 4 | NAMES jemalloc/jemalloc.h 5 | ) 6 | 7 | find_library(JEMALLOC_LIBRARY 8 | NAMES jemalloc 9 | ) 10 | 11 | set(JEMALLOC_INCLUDE_DIRS ${JEMALLOC_INCLUDE_DIR}) 12 | set(JEMALLOC_LIBRARIES ${JEMALLOC_LIBRARY}) 13 | 14 | include(FindPackageHandleStandardArgs) 15 | 16 | find_package_handle_standard_args(JEMALLOC DEFAULT_MSG JEMALLOC_LIBRARY JEMALLOC_INCLUDE_DIR) 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | *.d 7 | 8 | # Precompiled Headers 9 | *.gch 10 | *.pch 11 | build 12 | # Compiled Dynamic libraries 13 | #*.dylib 14 | #*.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.lib 24 | 25 | # Executables 26 | #*.exe 27 | *.out 28 | *.app 29 | 30 | *.DS_Store 31 | 32 | /.idea/ 33 | /cmake-build-debug/ 34 | /cmake-build-release/ -------------------------------------------------------------------------------- /3rdpart/jsoncpp/json.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_JSON_H_INCLUDED 7 | #define JSON_JSON_H_INCLUDED 8 | 9 | #include "autolink.h" 10 | #include "features.h" 11 | #include "reader.h" 12 | #include "writer.h" 13 | #include "value.h" 14 | 15 | #endif // JSON_JSON_H_INCLUDED 16 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/version.h: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. This file (and "version") is generated by CMake. 2 | // Run CMake configure step to update it. 3 | #ifndef JSON_VERSION_H_INCLUDED 4 | # define JSON_VERSION_H_INCLUDED 5 | 6 | # define JSONCPP_VERSION_STRING "1.6.5" 7 | # define JSONCPP_VERSION_MAJOR 1 8 | # define JSONCPP_VERSION_MINOR 6 9 | # define JSONCPP_VERSION_PATCH 5 10 | # define JSONCPP_VERSION_QUALIFIER 11 | # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) 12 | 13 | #endif // JSON_VERSION_H_INCLUDED 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 一个高效的序列化反序列化库 2 | 3 | - [x] 支持json序列化反序列化 4 | - [x] 支持tinybuf([私有协议](https://github.com/xiongziliang/tinybuf/wiki/tinybuf%E5%BA%8F%E5%88%97%E5%8C%96%E5%8D%8F%E8%AE%AE))序列化反序列化 5 | - [x] 纯C代码,适合嵌入式系统 6 | - [x] 序列化反序列化性能高效 7 | - [x] tinybuf序列化格式占用字节更少,更利于传输 8 | 9 | # 性能对比(release模式) 10 | - [x] json格式时,序列化性能大约为jsoncpp的3倍 11 | - [x] json格式时,反序列化性能大约为jsoncpp的1.5倍 12 | - [x] tinybuf格式时,序列化性能大约为jsoncpp的10~20倍 13 | - [x] tinybuf格式时,反序列化性能大约为jsoncpp的4倍 14 | 15 | # 测试结果截图 16 | ![image](https://user-images.githubusercontent.com/11495632/65878363-8076b500-e3c0-11e9-807a-c2ef51efe11c.png) 17 | -------------------------------------------------------------------------------- /src/source/tinybuf_private.h: -------------------------------------------------------------------------------- 1 | #ifndef TINYBUF_PRIVATE_H 2 | #define TINYBUF_PRIVATE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "avl-tree.h" 9 | #include "tinybuf.h" 10 | #include "tinybuf_memory.h" 11 | #include "tinybuf_log.h" 12 | #include "tinybuf_buffer_private.h" 13 | 14 | struct T_tinybuf_value{ 15 | union { 16 | int64_t _int; 17 | int _bool; 18 | double _double; 19 | buffer *_string; 20 | AVLTree *_map_array; 21 | } _data; 22 | tinybuf_type _type; 23 | }; 24 | 25 | #endif//TINYBUF_PRIVATE_H 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/version.h.in: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. This file (and "version") is generated by CMake. 2 | // Run CMake configure step to update it. 3 | #ifndef JSON_VERSION_H_INCLUDED 4 | # define JSON_VERSION_H_INCLUDED 5 | 6 | # define JSONCPP_VERSION_STRING "@JSONCPP_VERSION@" 7 | # define JSONCPP_VERSION_MAJOR @JSONCPP_VERSION_MAJOR@ 8 | # define JSONCPP_VERSION_MINOR @JSONCPP_VERSION_MINOR@ 9 | # define JSONCPP_VERSION_PATCH @JSONCPP_VERSION_PATCH@ 10 | # define JSONCPP_VERSION_QUALIFIER 11 | # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) 12 | 13 | #endif // JSON_VERSION_H_INCLUDED 14 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/autolink.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_AUTOLINK_H_INCLUDED 7 | #define JSON_AUTOLINK_H_INCLUDED 8 | 9 | #include "../jsoncpp/config.h" 10 | 11 | #ifdef JSON_IN_CPPTL 12 | #include 13 | #endif 14 | 15 | #if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \ 16 | !defined(JSON_IN_CPPTL) 17 | #define CPPTL_AUTOLINK_NAME "json" 18 | #undef CPPTL_AUTOLINK_DLL 19 | #ifdef JSON_DLL 20 | #define CPPTL_AUTOLINK_DLL 21 | #endif 22 | #include "autolink.h" 23 | #endif 24 | 25 | #endif // JSON_AUTOLINK_H_INCLUDED 26 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/forwards.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_FORWARDS_H_INCLUDED 7 | #define JSON_FORWARDS_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "config.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | 13 | namespace Json { 14 | 15 | // writer.h 16 | class FastWriter; 17 | class StyledWriter; 18 | 19 | // reader.h 20 | class Reader; 21 | 22 | // features.h 23 | class Features; 24 | 25 | // value.h 26 | typedef unsigned int ArrayIndex; 27 | class StaticString; 28 | class Path; 29 | class PathArgument; 30 | class Value; 31 | class ValueIteratorBase; 32 | class ValueIterator; 33 | class ValueConstIterator; 34 | 35 | } // namespace Json 36 | 37 | #endif // JSON_FORWARDS_H_INCLUDED 38 | -------------------------------------------------------------------------------- /src/include/tinybuf_memory.h: -------------------------------------------------------------------------------- 1 | #ifndef TINYBUF_MEMORY_H 2 | #define TINYBUF_MEMORY_H 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif // __cplusplus 6 | 7 | ///////////////////内存相关函数指针声明///////////////////////////// 8 | typedef void *(*malloc_ptr)(int size); 9 | typedef void (*free_ptr)(void *ptr); 10 | typedef void *(*realloc_ptr)(void *ptr,int size); 11 | typedef char *(*strdup_ptr)(const char *str); 12 | 13 | ///////////////////替换内存相关的函数///////////////////////////// 14 | void set_malloc_ptr(malloc_ptr ptr); 15 | void set_free_ptr(free_ptr ptr); 16 | void set_realloc_ptr(realloc_ptr ptr); 17 | void set_strdup_ptr(strdup_ptr ptr); 18 | 19 | ///////////////////内存相关的函数///////////////////////////// 20 | void *tinybuf_malloc(int size); 21 | void tinybuf_free(void *ptr); 22 | void *tinybuf_realloc(void *ptr,int size); 23 | char *tinybuf_strdup(const char *str); 24 | 25 | #ifdef __cplusplus 26 | } // extern "C" 27 | #endif // __cplusplus 28 | #endif //TINYBUF_MEMORY_H 29 | -------------------------------------------------------------------------------- /src/source/tinybuf_buffer_private.h: -------------------------------------------------------------------------------- 1 | #ifndef TINYBUF_BUFFER_PRIVATE_H 2 | #define TINYBUF_BUFFER_PRIVATE_H 3 | 4 | struct T_buffer{ 5 | char *_data; 6 | int _len; 7 | int _capacity; 8 | }; 9 | 10 | #define inline_optimization 1 11 | 12 | #if inline_optimization 13 | #define buffer_get_data_inline(buf) (buf ? buf->_data : NULL) 14 | #define buffer_get_length_inline(buf) (buf ? buf->_len : 0) 15 | #define buffer_get_capacity_inline(buf) (buf ? buf->_capacity : 0) 16 | #define buffer_push_inline(buf,ch)\ 17 | do{\ 18 | assert(buf);\ 19 | if(buf->_len + 1 < buf->_capacity){\ 20 | buf->_data[buf->_len] = ch;\ 21 | ++buf->_len;\ 22 | buf->_data[buf->_len] = '\0';\ 23 | }else{\ 24 | char tmp = ch;\ 25 | buffer_append(buf,&tmp,1);\ 26 | }\ 27 | }while (0); 28 | #else 29 | #define buffer_get_data_inline buffer_get_data 30 | #define buffer_get_length_inline buffer_get_length 31 | #define buffer_get_capacity_inline buffer_get_capacity 32 | #define buffer_push_inline buffer_push 33 | #endif 34 | 35 | #endif //TINYBUF_BUFFER_PRIVATE_H 36 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(tinybuf) 3 | 4 | #使能c++11 5 | #add_compile_options(-std=c++11) 6 | set(CMAKE_CXX_STANDARD 11) 7 | if(NOT MSVC) 8 | add_definitions(-Wno-int-to-void-pointer-cast -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast) 9 | endif() 10 | 11 | 12 | #加载自定义模块 13 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 14 | #设置库文件路径 15 | set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 16 | #设置可执行程序路径 17 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 18 | 19 | #设置工程源码根目录 20 | set(Source_Root ${CMAKE_CURRENT_SOURCE_DIR}/src) 21 | 22 | #设置头文件目录 23 | INCLUDE_DIRECTORIES(${Source_Root}/include) 24 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/3rdpart/) 25 | 26 | 27 | #收集源代码 28 | file(GLOB tinybuf_src_Root ${Source_Root}/source/*.c) 29 | file(GLOB json_src_Root ${CMAKE_CURRENT_SOURCE_DIR}/3rdpart/jsoncpp/*.cpp) 30 | 31 | add_library(tinybuf STATIC ${tinybuf_src_Root}) 32 | add_library(jsoncpp STATIC ${json_src_Root}) 33 | 34 | add_executable(benchmark benchmark.cpp) 35 | 36 | set(LINK_LIST) 37 | find_package(JEMALLOC QUIET) 38 | if(JEMALLOC_FOUND) 39 | set(LINK_LIST ${JEMALLOC_LIBRARY}) 40 | endif() 41 | 42 | if(MSVC) 43 | target_link_libraries(benchmark jsoncpp tinybuf ${LINK_LIST} ws2_32) 44 | else() 45 | target_link_libraries(benchmark jsoncpp tinybuf ${LINK_LIST} pthread) 46 | endif() 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/source/tinybuf_memory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "tinybuf_memory.h" 5 | #include "tinybuf_log.h" 6 | 7 | static malloc_ptr s_malloc_ptr = NULL; 8 | static free_ptr s_free_ptr = NULL; 9 | static realloc_ptr s_realloc_ptr = NULL; 10 | static strdup_ptr s_strdup_ptr = NULL; 11 | 12 | 13 | void set_malloc_ptr(malloc_ptr ptr){ 14 | s_malloc_ptr = ptr; 15 | } 16 | 17 | void set_free_ptr(free_ptr ptr){ 18 | s_free_ptr = ptr; 19 | } 20 | 21 | void set_realloc_ptr(realloc_ptr ptr){ 22 | s_realloc_ptr = ptr; 23 | } 24 | 25 | void set_strdup_ptr(strdup_ptr ptr){ 26 | s_strdup_ptr = ptr; 27 | } 28 | 29 | void *tinybuf_malloc(int size){ 30 | assert(size); 31 | void *ptr = s_malloc_ptr ? s_malloc_ptr(size) : malloc(size); 32 | assert(ptr); 33 | return ptr; 34 | } 35 | 36 | void tinybuf_free(void *ptr){ 37 | if(ptr == NULL){ 38 | return; 39 | } 40 | s_free_ptr ? s_free_ptr(ptr) : free(ptr); 41 | } 42 | 43 | void *tinybuf_realloc(void *ptr,int size){ 44 | assert(ptr); 45 | assert(size); 46 | void *ret = s_realloc_ptr ? s_realloc_ptr(ptr,size) : realloc(ptr,size); 47 | assert(ret); 48 | return ret; 49 | } 50 | 51 | static inline char *strdup_1(const char *str){ 52 | int len = strlen(str) + 1; 53 | char *ret = tinybuf_malloc(len); 54 | memcpy(ret,str,len); 55 | assert(ret); 56 | return ret; 57 | } 58 | 59 | char *tinybuf_strdup(const char *str){ 60 | assert(str); 61 | char *ret = s_strdup_ptr ? s_strdup_ptr(str) : strdup_1(str); 62 | assert(ret); 63 | return ret; 64 | } -------------------------------------------------------------------------------- /src/include/tinybuf_log.h: -------------------------------------------------------------------------------- 1 | #ifndef TINYBUF_LOG_H 2 | #define TINYBUF_LOG_H 3 | 4 | #include 5 | #ifdef ANDROID 6 | #include 7 | #ifdef ANDROID 8 | extern android_LogPriority LogPriorityArr[]; 9 | #endif 10 | #endif //ANDROID 11 | 12 | #define CLEAR_COLOR "\033[0m" 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif // __cplusplus 17 | 18 | /** 19 | * 日志等级 20 | */ 21 | typedef enum { 22 | log_trace = 0, 23 | log_debug , 24 | log_info , 25 | log_warn , 26 | log_error , 27 | } e_log_lev; 28 | 29 | extern const char *LOG_CONST_TABLE[][3]; 30 | 31 | 32 | /** 33 | * 获取当前时间字符串 34 | * @param buf 存放地址 35 | * @param buf_size 存放地址长度 36 | */ 37 | void get_now_time_str(char *buf,int buf_size); 38 | 39 | /** 40 | * 设置日志等级 41 | * @param lev 日志等级 42 | */ 43 | void set_log_level(e_log_lev lev); 44 | 45 | /** 46 | * 获取日志等级 47 | * @return 日志等级 48 | */ 49 | e_log_lev get_log_level(void); 50 | 51 | /** 52 | * printf回调函数 53 | */ 54 | typedef int (*printf_ptr)(const char * fmt, ...) ; 55 | 56 | /** 57 | * 设置printf回调函数 58 | * @param cb 59 | */ 60 | void set_printf_ptr(printf_ptr cb); 61 | 62 | /** 63 | * 获取printf函数 64 | * @return 65 | */ 66 | printf_ptr get_printf_ptr(void); 67 | 68 | 69 | void log_print(e_log_lev lev, const char *file, int line, const char *func, const char *fmt, ...); 70 | #define LOGT(...) log_print(log_trace,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__) 71 | #define LOGD(...) log_print(log_debug,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__) 72 | #define LOGI(...) log_print(log_info,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__) 73 | #define LOGW(...) log_print(log_warn,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__) 74 | #define LOGE(...) log_print(log_error,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__) 75 | 76 | #ifdef __cplusplus 77 | } // extern "C" 78 | #endif // __cplusplus 79 | #endif //TINYBUF_LOG_H 80 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/features.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_FEATURES_H_INCLUDED 7 | #define CPPTL_JSON_FEATURES_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "../jsoncpp/forwards.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | 13 | namespace Json { 14 | 15 | /** \brief Configuration passed to reader and writer. 16 | * This configuration object can be used to force the Reader or Writer 17 | * to behave in a standard conforming way. 18 | */ 19 | class JSON_API Features { 20 | public: 21 | /** \brief A configuration that allows all features and assumes all strings 22 | * are UTF-8. 23 | * - C & C++ comments are allowed 24 | * - Root object can be any JSON value 25 | * - Assumes Value strings are encoded in UTF-8 26 | */ 27 | static Features all(); 28 | 29 | /** \brief A configuration that is strictly compatible with the JSON 30 | * specification. 31 | * - Comments are forbidden. 32 | * - Root object must be either an array or an object value. 33 | * - Assumes Value strings are encoded in UTF-8 34 | */ 35 | static Features strictMode(); 36 | 37 | /** \brief Initialize the configuration like JsonConfig::allFeatures; 38 | */ 39 | Features(); 40 | 41 | /// \c true if comments are allowed. Default: \c true. 42 | bool allowComments_; 43 | 44 | /// \c true if root must be either an array or an object value. Default: \c 45 | /// false. 46 | bool strictRoot_; 47 | 48 | /// \c true if dropped null placeholders are allowed. Default: \c false. 49 | bool allowDroppedNullPlaceholders_; 50 | 51 | /// \c true if numeric object key are allowed. Default: \c false. 52 | bool allowNumericKeys_; 53 | }; 54 | 55 | } // namespace Json 56 | 57 | #endif // CPPTL_JSON_FEATURES_H_INCLUDED 58 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/assertions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED 7 | #define CPPTL_JSON_ASSERTIONS_H_INCLUDED 8 | 9 | #include 10 | #include 11 | 12 | #if !defined(JSON_IS_AMALGAMATION) 13 | #include "../jsoncpp/config.h" 14 | #endif // if !defined(JSON_IS_AMALGAMATION) 15 | 16 | /** It should not be possible for a maliciously designed file to 17 | * cause an abort() or seg-fault, so these macros are used only 18 | * for pre-condition violations and internal logic errors. 19 | */ 20 | #if JSON_USE_EXCEPTION 21 | 22 | // @todo <= add detail about condition in exception 23 | # define JSON_ASSERT(condition) \ 24 | {if (!(condition)) {Json::throwLogicError( "assert json failed" );}} 25 | 26 | # define JSON_FAIL_MESSAGE(message) \ 27 | { \ 28 | std::ostringstream oss; oss << message; \ 29 | Json::throwLogicError(oss.str()); \ 30 | } 31 | 32 | #else // JSON_USE_EXCEPTION 33 | 34 | # define JSON_ASSERT(condition) assert(condition) 35 | 36 | // The call to assert() will show the failure message in debug builds. In 37 | // release builds we abort, for a core-dump or debugger. 38 | # define JSON_FAIL_MESSAGE(message) \ 39 | { \ 40 | std::ostringstream oss; oss << message; \ 41 | assert(false && oss.str().c_str()); \ 42 | abort(); \ 43 | } 44 | 45 | 46 | #endif 47 | 48 | #define JSON_ASSERT_MESSAGE(condition, message) \ 49 | if (!(condition)) { \ 50 | JSON_FAIL_MESSAGE(message); \ 51 | } 52 | 53 | #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED 54 | -------------------------------------------------------------------------------- /src/source/tinybuf_log.c: -------------------------------------------------------------------------------- 1 | #include "tinybuf_log.h" 2 | #include 3 | #ifdef _WIN32 4 | #include 5 | static int gettimeofday(struct timeval* tv, void* tz) { 6 | FILETIME ft; 7 | ULARGE_INTEGER uli; 8 | GetSystemTimeAsFileTime(&ft); 9 | uli.LowPart = ft.dwLowDateTime; 10 | uli.HighPart = ft.dwHighDateTime; 11 | unsigned long long t = (uli.QuadPart - 116444736000000000ULL) / 10ULL; 12 | tv->tv_sec = (long)(t / 1000000ULL); 13 | tv->tv_usec = (long)(t % 1000000ULL); 14 | return 0; 15 | } 16 | #else 17 | #include 18 | #include 19 | #endif 20 | #include 21 | 22 | static e_log_lev s_log_leg = log_trace; 23 | 24 | void set_log_level(e_log_lev lev){ 25 | s_log_leg = lev; 26 | } 27 | e_log_lev get_log_level(){ 28 | return s_log_leg; 29 | } 30 | 31 | const char *LOG_CONST_TABLE[][3] = { 32 | {"\033[44;37m", "\033[34m" , "T"}, 33 | {"\033[42;37m", "\033[32m" , "D"}, 34 | {"\033[46;37m", "\033[36m" , "I"}, 35 | {"\033[43;37m", "\033[33m" , "W"}, 36 | {"\033[41;37m", "\033[31m" , "E"}}; 37 | 38 | #ifdef ANDROID 39 | android_LogPriority LogPriorityArr[] = {ANDROID_LOG_VERBOSE,ANDROID_LOG_DEBUG,ANDROID_LOG_INFO,ANDROID_LOG_WARN,ANDROID_LOG_ERROR}; 40 | #endif 41 | 42 | static void print_time(const struct timeval *tv,char *buf,int buf_size) { 43 | time_t sec_tmp = tv->tv_sec; 44 | struct tm *tm = localtime(&sec_tmp); 45 | snprintf(buf, 46 | buf_size, 47 | "%d-%02d-%02d %02d:%02d:%02d.%03d", 48 | 1900 + tm->tm_year, 49 | 1 + tm->tm_mon, 50 | tm->tm_mday, 51 | tm->tm_hour, 52 | tm->tm_min, 53 | tm->tm_sec, 54 | (int) (tv->tv_usec / 1000)); 55 | } 56 | 57 | void get_now_time_str(char *buf,int buf_size){ 58 | struct timeval tv; 59 | gettimeofday(&tv, NULL); 60 | print_time(&tv,buf,buf_size); 61 | } 62 | 63 | static printf_ptr s_printf = NULL; 64 | void set_printf_ptr(printf_ptr cb){ 65 | s_printf = cb; 66 | } 67 | printf_ptr get_printf_ptr(){ 68 | return s_printf ? s_printf : printf; 69 | } 70 | 71 | void log_print(e_log_lev lev, const char *file, int line, const char *func, const char *fmt, ...){ 72 | if(lev < get_log_level()){ 73 | return; 74 | } 75 | char time_str[26]; 76 | get_now_time_str(time_str,sizeof(time_str)); 77 | printf_ptr p = get_printf_ptr(); 78 | p("%s %s | %s ", time_str, LOG_CONST_TABLE[lev][2], func); 79 | va_list ap; 80 | va_start(ap, fmt); 81 | vprintf(fmt, ap); 82 | va_end(ap); 83 | p("\r\n"); 84 | } 85 | -------------------------------------------------------------------------------- /src/include/tinybuf_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef TINYBUF_BUFFER_H 2 | #define TINYBUF_BUFFER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif // __cplusplus 7 | 8 | typedef struct T_buffer buffer; 9 | 10 | /** 11 | * 在堆上申请开辟buffer对象并且初始化 12 | * 内部会调用buffer_init函数 13 | * @return buffer对象 14 | */ 15 | buffer *buffer_alloc(void); 16 | buffer *buffer_alloc2(const char *str,int len); 17 | 18 | /** 19 | * 释放堆上的buffer对象 20 | * @param buf buffer对象指针 21 | * @return 0:成功 22 | */ 23 | int buffer_free(buffer *buf); 24 | 25 | /** 26 | * 获取数据指针 27 | * @param buf 对象 28 | * @return 数据指针,可能返回NULL 29 | */ 30 | char *buffer_get_data(buffer *buf); 31 | 32 | /** 33 | * 获取数据长度 34 | * @param buf 对象 35 | * @return 数据长度 36 | */ 37 | int buffer_get_length(buffer *buf); 38 | 39 | /** 40 | * 设置长度,不能超过(容量-1) 41 | * @param buf 对象 42 | * @param len 新的长度 43 | * @return 0成功,-1失败 44 | */ 45 | int buffer_set_length(buffer *buf,int len); 46 | 47 | /** 48 | * 获取对象容量 49 | * @param buf 对象 50 | * @return 容量大小 51 | */ 52 | int buffer_get_capacity(buffer *buf); 53 | 54 | /** 55 | * 追加数据至buffer对象末尾 56 | * @param buf 对象指针 57 | * @param data 数据指针 58 | * @param len 数据长度,可以为0,为0时内部使用strlen获得长度 59 | * @return 0为成功 60 | */ 61 | int buffer_append(buffer *buf,const char *data,int len); 62 | 63 | /** 64 | * 追加容量 65 | * @param buf 对象 66 | * @param add 追加的字节数 67 | * @return 68 | */ 69 | int buffer_add_capacity(buffer *buf,int add); 70 | 71 | /** 72 | * 追加数据至buffer对象末尾 73 | * @param buf 对象指针 74 | * @param from 子buffer 75 | * @return 0为成功 76 | */ 77 | int buffer_append_buffer(buffer *buf,const buffer *from); 78 | 79 | /** 80 | * 复制数据至buffer对象 81 | * @param buf 对象指针 82 | * @param data 数据指针 83 | * @param len 数据长度,可以为0,为0时内部使用strlen获得长度 84 | * @return 0为成功 85 | */ 86 | int buffer_assign(buffer *buf,const char *data,int len); 87 | 88 | /** 89 | * 把src对象里面的数据移动至dst,内部有无memcpy 90 | * @param dst 目标对象 91 | * @param src 源对象 92 | * @return 0为成功 93 | */ 94 | int buffer_move(buffer *dst,buffer *src); 95 | 96 | /** 97 | * 压入一个字节 98 | * @param buf 99 | * @param ch 100 | * @return 101 | */ 102 | int buffer_push(buffer *buf,char ch); 103 | 104 | /** 105 | * 弹出一个字节 106 | * @param buf 107 | * @return 108 | */ 109 | int buffer_pop(buffer *buf); 110 | 111 | /** 112 | * 获取最后一个字节 113 | * @param buf 114 | * @return 115 | */ 116 | char buffer_back(buffer *buf); 117 | 118 | /** 119 | * 判断两个对象是否一致 120 | * @param buf 121 | * @param from 122 | * @return 123 | */ 124 | int buffer_is_same(const buffer *buf1,const buffer *buf2); 125 | 126 | #ifdef __cplusplus 127 | } // extern "C" 128 | #endif // __cplusplus 129 | #endif //TINYBUF_BUFFER_H 130 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/json_tool.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED 7 | #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED 8 | 9 | /* This header provides common string manipulation support, such as UTF-8, 10 | * portable conversion from/to string... 11 | * 12 | * It is an internal header that must not be exposed. 13 | */ 14 | 15 | namespace Json { 16 | 17 | /// Converts a unicode code-point to UTF-8. 18 | static inline std::string codePointToUTF8(unsigned int cp) { 19 | std::string result; 20 | 21 | // based on description from http://en.wikipedia.org/wiki/UTF-8 22 | 23 | if (cp <= 0x7f) { 24 | result.resize(1); 25 | result[0] = static_cast(cp); 26 | } else if (cp <= 0x7FF) { 27 | result.resize(2); 28 | result[1] = static_cast(0x80 | (0x3f & cp)); 29 | result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); 30 | } else if (cp <= 0xFFFF) { 31 | result.resize(3); 32 | result[2] = static_cast(0x80 | (0x3f & cp)); 33 | result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); 34 | result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); 35 | } else if (cp <= 0x10FFFF) { 36 | result.resize(4); 37 | result[3] = static_cast(0x80 | (0x3f & cp)); 38 | result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); 39 | result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); 40 | result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); 41 | } 42 | 43 | return result; 44 | } 45 | 46 | /// Returns true if ch is a control character (in range [1,31]). 47 | static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } 48 | 49 | enum { 50 | /// Constant that specify the size of the buffer that must be passed to 51 | /// uintToString. 52 | uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 53 | }; 54 | 55 | // Defines a char buffer for use with uintToString(). 56 | typedef char UIntToStringBuffer[uintToStringBufferSize]; 57 | 58 | /** Converts an unsigned integer to string. 59 | * @param value Unsigned interger to convert to string 60 | * @param current Input/Output string buffer. 61 | * Must have at least uintToStringBufferSize chars free. 62 | */ 63 | static inline void uintToString(LargestUInt value, char*& current) { 64 | *--current = 0; 65 | do { 66 | *--current = static_cast(value % 10U + static_cast('0')); 67 | value /= 10; 68 | } while (value != 0); 69 | } 70 | 71 | /** Change ',' to '.' everywhere in buffer. 72 | * 73 | * We had a sophisticated way, but it did not work in WinCE. 74 | * @see https://github.com/open-source-parsers/jsoncpp/pull/9 75 | */ 76 | static inline void fixNumericLocale(char* begin, char* end) { 77 | while (begin < end) { 78 | if (*begin == ',') { 79 | *begin = '.'; 80 | } 81 | ++begin; 82 | } 83 | } 84 | 85 | } // namespace Json { 86 | 87 | #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED 88 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_CONFIG_H_INCLUDED 7 | #define JSON_CONFIG_H_INCLUDED 8 | 9 | /// If defined, indicates that json library is embedded in CppTL library. 10 | //# define JSON_IN_CPPTL 1 11 | 12 | /// If defined, indicates that json may leverage CppTL library 13 | //# define JSON_USE_CPPTL 1 14 | /// If defined, indicates that cpptl vector based map should be used instead of 15 | /// std::map 16 | /// as Value container. 17 | //# define JSON_USE_CPPTL_SMALLMAP 1 18 | 19 | // If non-zero, the library uses exceptions to report bad input instead of C 20 | // assertion macros. The default is to use exceptions. 21 | #ifndef JSON_USE_EXCEPTION 22 | #define JSON_USE_EXCEPTION 1 23 | #endif 24 | 25 | /// If defined, indicates that the source file is amalgated 26 | /// to prevent private header inclusion. 27 | /// Remarks: it is automatically defined in the generated amalgated header. 28 | // #define JSON_IS_AMALGAMATION 29 | 30 | #ifdef JSON_IN_CPPTL 31 | #include 32 | #ifndef JSON_USE_CPPTL 33 | #define JSON_USE_CPPTL 1 34 | #endif 35 | #endif 36 | 37 | #ifdef JSON_IN_CPPTL 38 | #define JSON_API CPPTL_API 39 | #elif defined(JSON_DLL_BUILD) 40 | #if defined(_MSC_VER) 41 | #define JSON_API __declspec(dllexport) 42 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 43 | #endif // if defined(_MSC_VER) 44 | #elif defined(JSON_DLL) 45 | #if defined(_MSC_VER) 46 | #define JSON_API __declspec(dllimport) 47 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 48 | #endif // if defined(_MSC_VER) 49 | #endif // ifdef JSON_IN_CPPTL 50 | #if !defined(JSON_API) 51 | #define JSON_API 52 | #endif 53 | 54 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for 55 | // integer 56 | // Storages, and 64 bits integer support is disabled. 57 | // #define JSON_NO_INT64 1 58 | 59 | #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 60 | // Microsoft Visual Studio 6 only support conversion from __int64 to double 61 | // (no conversion from unsigned __int64). 62 | #define JSON_USE_INT64_DOUBLE_CONVERSION 1 63 | // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' 64 | // characters in the debug information) 65 | // All projects I've ever seen with VS6 were using this globally (not bothering 66 | // with pragma push/pop). 67 | #pragma warning(disable : 4786) 68 | #endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 69 | 70 | #if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 71 | /// Indicates that the following function is deprecated. 72 | #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) 73 | #elif defined(__clang__) && defined(__has_feature) 74 | #if __has_feature(attribute_deprecated_with_message) 75 | #define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) 76 | #endif 77 | #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) 78 | #define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) 79 | #elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) 80 | #define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) 81 | #endif 82 | 83 | #if !defined(JSONCPP_DEPRECATED) 84 | #define JSONCPP_DEPRECATED(message) 85 | #endif // if !defined(JSONCPP_DEPRECATED) 86 | 87 | namespace Json { 88 | typedef int Int; 89 | typedef unsigned int UInt; 90 | #if defined(JSON_NO_INT64) 91 | typedef int LargestInt; 92 | typedef unsigned int LargestUInt; 93 | #undef JSON_HAS_INT64 94 | #else // if defined(JSON_NO_INT64) 95 | // For Microsoft Visual use specific types as long long is not supported 96 | #if defined(_MSC_VER) // Microsoft Visual Studio 97 | typedef __int64 Int64; 98 | typedef unsigned __int64 UInt64; 99 | #else // if defined(_MSC_VER) // Other platforms, use long long 100 | typedef long long int Int64; 101 | typedef unsigned long long int UInt64; 102 | #endif // if defined(_MSC_VER) 103 | typedef Int64 LargestInt; 104 | typedef UInt64 LargestUInt; 105 | #define JSON_HAS_INT64 106 | #endif // if defined(JSON_NO_INT64) 107 | } // end namespace Json 108 | 109 | #endif // JSON_CONFIG_H_INCLUDED 110 | -------------------------------------------------------------------------------- /src/source/tinybuf_buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tinybuf_buffer.h" 4 | #include "tinybuf_memory.h" 5 | #include "tinybuf_buffer_private.h" 6 | 7 | #define RESERVED_SIZE 64 8 | 9 | 10 | static inline void my_memcpy(char *dst,const char *src,int len){ 11 | assert(dst); 12 | assert(src); 13 | switch (len){ 14 | case 0: 15 | return; 16 | case 1: 17 | dst[0] = *src; 18 | return; 19 | default: 20 | memcpy(dst,src,len); 21 | return; 22 | } 23 | } 24 | 25 | static inline int buffer_release(buffer *buf){ 26 | assert(buf); 27 | if(buf->_capacity && buf->_data){ 28 | tinybuf_free(buf->_data); 29 | //LOGD("free:%d",buf->_capacity); 30 | } 31 | memset(buf,0, sizeof(buffer)); 32 | return 0; 33 | } 34 | 35 | buffer *buffer_alloc(void){ 36 | buffer *ret = (buffer *) tinybuf_malloc(sizeof(buffer)); 37 | assert(ret); 38 | memset(ret,0, sizeof(buffer));; 39 | return ret; 40 | } 41 | 42 | buffer *buffer_alloc2(const char *str,int len){ 43 | buffer *ret = buffer_alloc(); 44 | buffer_assign(ret,str,len); 45 | return ret; 46 | } 47 | 48 | 49 | int buffer_free(buffer *buf){ 50 | assert(buf); 51 | buffer_release(buf); 52 | tinybuf_free(buf); 53 | return 0; 54 | } 55 | 56 | 57 | char *buffer_get_data(buffer *buf){ 58 | if(!buf){ 59 | return NULL; 60 | } 61 | return buf->_data; 62 | } 63 | 64 | int buffer_get_length(buffer *buf){ 65 | if(!buf){ 66 | return 0; 67 | } 68 | return buf->_len; 69 | } 70 | 71 | int buffer_set_length(buffer *buf, int len){ 72 | if(!buf){ 73 | return -1; 74 | } 75 | if(buf->_capacity <= len){ 76 | return -1; 77 | } 78 | 79 | buf->_len = len; 80 | buf->_data[len] = '\0'; 81 | return 0; 82 | } 83 | 84 | int buffer_get_capacity(buffer *buf){ 85 | if(!buf){ 86 | return 0; 87 | } 88 | return buf->_capacity; 89 | } 90 | 91 | int buffer_append_buffer(buffer *buf,const buffer *from){ 92 | assert(buf); 93 | assert(from); 94 | return buffer_append(buf,from->_data,from->_len); 95 | } 96 | 97 | int buffer_add_capacity(buffer *buf,int len){ 98 | assert(buf); 99 | if(!buf->_capacity){ 100 | //内存尚未开辟 101 | buf->_data = tinybuf_malloc(len); 102 | buf->_capacity = len; 103 | return 0; 104 | } 105 | buf->_data = tinybuf_realloc(buf->_data,len + buf->_capacity); 106 | buf->_capacity += len; 107 | return 0; 108 | } 109 | 110 | int buffer_append(buffer *buf,const char *data,int len){ 111 | assert(buf); 112 | assert(data); 113 | if(len <= 0){ 114 | len = strlen(data); 115 | } 116 | 117 | if(!buf->_capacity){ 118 | //内存尚未开辟 119 | buffer_add_capacity(buf,len + RESERVED_SIZE); 120 | } 121 | 122 | if(buf->_capacity > buf->_len + len){ 123 | //容量够 124 | my_memcpy(buf->_data + buf->_len ,data,len); 125 | buf->_len += len; 126 | buf->_data[buf->_len] = '\0'; 127 | return 0; 128 | } 129 | 130 | //已经开辟的容量不够 131 | buf->_data = tinybuf_realloc(buf->_data,len + buf->_len + RESERVED_SIZE); 132 | assert(buf->_data); 133 | my_memcpy(buf->_data + buf->_len ,data,len); 134 | buf->_len += len; 135 | buf->_data[buf->_len] = '\0'; 136 | buf->_capacity = buf->_len + RESERVED_SIZE; 137 | return 0; 138 | } 139 | int buffer_assign(buffer *buf,const char *data,int len){ 140 | assert(buf); 141 | assert(data); 142 | if(len <= 0){ 143 | len = strlen(data); 144 | } 145 | if(buf->_capacity > len){ 146 | my_memcpy(buf->_data,data,len); 147 | buf->_len = len; 148 | buf->_data[buf->_len] = '\0'; 149 | return 0; 150 | } 151 | buf->_len = 0; 152 | return buffer_append(buf,data,len); 153 | } 154 | 155 | int buffer_move(buffer *dst,buffer *src){ 156 | buffer_release(dst); 157 | dst->_data = src->_data; 158 | dst->_len = src->_len; 159 | dst->_capacity = src->_capacity; 160 | memset(src,0, sizeof(buffer)); 161 | return 0; 162 | } 163 | 164 | static int buffer_length(buffer *buf){ 165 | if(!buf){ 166 | return 0; 167 | } 168 | return buf->_len; 169 | } 170 | 171 | int buffer_push(buffer *buf,char ch){ 172 | assert(buf); 173 | if(buf->_len + 1 < buf->_capacity){ 174 | buf->_data[buf->_len] = ch; 175 | buf->_len += 1; 176 | buf->_data[buf->_len] = '\0'; 177 | }else{ 178 | buffer_append(buf,&ch,1); 179 | } 180 | return 0; 181 | } 182 | 183 | int buffer_pop(buffer *buf){ 184 | assert(buf); 185 | if(!buf->_len){ 186 | return 0; 187 | } 188 | buf->_data[buf->_len - 1] = '\0'; 189 | buf->_len -= 1; 190 | return 0; 191 | } 192 | 193 | char buffer_back(buffer *buf){ 194 | assert(buf); 195 | if(buf->_len){ 196 | return buf->_data[buf->_len - 1]; 197 | } 198 | return 0; 199 | } 200 | 201 | int buffer_is_same(const buffer *buf1,const buffer *buf2){ 202 | assert(buf1); 203 | assert(buf2); 204 | 205 | if(buf1 == buf2){ 206 | return 1; 207 | } 208 | 209 | if(buf1->_len != buf2->_len){ 210 | //长度不一致 211 | return 0; 212 | } 213 | return 0 == memcmp(buf1->_data,buf2->_data,buf1->_len); 214 | } -------------------------------------------------------------------------------- /3rdpart/jsoncpp/json_valueiterator.inl: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | // included by json_value.cpp 7 | 8 | namespace Json { 9 | 10 | // ////////////////////////////////////////////////////////////////// 11 | // ////////////////////////////////////////////////////////////////// 12 | // ////////////////////////////////////////////////////////////////// 13 | // class ValueIteratorBase 14 | // ////////////////////////////////////////////////////////////////// 15 | // ////////////////////////////////////////////////////////////////// 16 | // ////////////////////////////////////////////////////////////////// 17 | 18 | ValueIteratorBase::ValueIteratorBase() 19 | : current_(), isNull_(true) { 20 | } 21 | 22 | ValueIteratorBase::ValueIteratorBase( 23 | const Value::ObjectValues::iterator& current) 24 | : current_(current), isNull_(false) {} 25 | 26 | Value& ValueIteratorBase::deref() const { 27 | return current_->second; 28 | } 29 | 30 | void ValueIteratorBase::increment() { 31 | ++current_; 32 | } 33 | 34 | void ValueIteratorBase::decrement() { 35 | --current_; 36 | } 37 | 38 | ValueIteratorBase::difference_type 39 | ValueIteratorBase::computeDistance(const SelfType& other) const { 40 | #ifdef JSON_USE_CPPTL_SMALLMAP 41 | return other.current_ - current_; 42 | #else 43 | // Iterator for null value are initialized using the default 44 | // constructor, which initialize current_ to the default 45 | // std::map::iterator. As begin() and end() are two instance 46 | // of the default std::map::iterator, they can not be compared. 47 | // To allow this, we handle this comparison specifically. 48 | if (isNull_ && other.isNull_) { 49 | return 0; 50 | } 51 | 52 | // Usage of std::distance is not portable (does not compile with Sun Studio 12 53 | // RogueWave STL, 54 | // which is the one used by default). 55 | // Using a portable hand-made version for non random iterator instead: 56 | // return difference_type( std::distance( current_, other.current_ ) ); 57 | difference_type myDistance = 0; 58 | for (Value::ObjectValues::iterator it = current_; it != other.current_; 59 | ++it) { 60 | ++myDistance; 61 | } 62 | return myDistance; 63 | #endif 64 | } 65 | 66 | bool ValueIteratorBase::isEqual(const SelfType& other) const { 67 | if (isNull_) { 68 | return other.isNull_; 69 | } 70 | return current_ == other.current_; 71 | } 72 | 73 | void ValueIteratorBase::copy(const SelfType& other) { 74 | current_ = other.current_; 75 | isNull_ = other.isNull_; 76 | } 77 | 78 | Value ValueIteratorBase::key() const { 79 | const Value::CZString czstring = (*current_).first; 80 | if (czstring.data()) { 81 | if (czstring.isStaticString()) 82 | return Value(StaticString(czstring.data())); 83 | return Value(czstring.data(), czstring.data() + czstring.length()); 84 | } 85 | return Value(czstring.index()); 86 | } 87 | 88 | UInt ValueIteratorBase::index() const { 89 | const Value::CZString czstring = (*current_).first; 90 | if (!czstring.data()) 91 | return czstring.index(); 92 | return Value::UInt(-1); 93 | } 94 | 95 | std::string ValueIteratorBase::name() const { 96 | char const* keey; 97 | char const* end; 98 | keey = memberName(&end); 99 | if (!keey) return std::string(); 100 | return std::string(keey, end); 101 | } 102 | 103 | char const* ValueIteratorBase::memberName() const { 104 | const char* cname = (*current_).first.data(); 105 | return cname ? cname : ""; 106 | } 107 | 108 | char const* ValueIteratorBase::memberName(char const** end) const { 109 | const char* cname = (*current_).first.data(); 110 | if (!cname) { 111 | *end = NULL; 112 | return NULL; 113 | } 114 | *end = cname + (*current_).first.length(); 115 | return cname; 116 | } 117 | 118 | // ////////////////////////////////////////////////////////////////// 119 | // ////////////////////////////////////////////////////////////////// 120 | // ////////////////////////////////////////////////////////////////// 121 | // class ValueConstIterator 122 | // ////////////////////////////////////////////////////////////////// 123 | // ////////////////////////////////////////////////////////////////// 124 | // ////////////////////////////////////////////////////////////////// 125 | 126 | ValueConstIterator::ValueConstIterator() {} 127 | 128 | ValueConstIterator::ValueConstIterator( 129 | const Value::ObjectValues::iterator& current) 130 | : ValueIteratorBase(current) {} 131 | 132 | ValueConstIterator& ValueConstIterator:: 133 | operator=(const ValueIteratorBase& other) { 134 | copy(other); 135 | return *this; 136 | } 137 | 138 | // ////////////////////////////////////////////////////////////////// 139 | // ////////////////////////////////////////////////////////////////// 140 | // ////////////////////////////////////////////////////////////////// 141 | // class ValueIterator 142 | // ////////////////////////////////////////////////////////////////// 143 | // ////////////////////////////////////////////////////////////////// 144 | // ////////////////////////////////////////////////////////////////// 145 | 146 | ValueIterator::ValueIterator() {} 147 | 148 | ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) 149 | : ValueIteratorBase(current) {} 150 | 151 | ValueIterator::ValueIterator(const ValueConstIterator& other) 152 | : ValueIteratorBase(other) {} 153 | 154 | ValueIterator::ValueIterator(const ValueIterator& other) 155 | : ValueIteratorBase(other) {} 156 | 157 | ValueIterator& ValueIterator::operator=(const SelfType& other) { 158 | copy(other); 159 | return *this; 160 | } 161 | 162 | } // namespace Json 163 | -------------------------------------------------------------------------------- /src/include/tinybuf.h: -------------------------------------------------------------------------------- 1 | #ifndef TINYBUF_H 2 | #define TINYBUF_H 3 | #include 4 | #include "tinybuf_buffer.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif // __cplusplus 9 | 10 | typedef enum { 11 | tinybuf_null = 0, 12 | tinybuf_int, 13 | tinybuf_bool, 14 | tinybuf_double, 15 | tinybuf_string, 16 | tinybuf_map, 17 | tinybuf_array 18 | } tinybuf_type; 19 | 20 | 21 | typedef struct T_tinybuf_value tinybuf_value; 22 | 23 | /** 24 | * 创建对象 25 | * @return 返回对象 26 | */ 27 | tinybuf_value *tinybuf_value_alloc(void); 28 | 29 | 30 | /** 31 | * 创建对象 32 | * @return 返回对象 33 | */ 34 | tinybuf_value *tinybuf_value_alloc_with_type(tinybuf_type type); 35 | 36 | /** 37 | * 销毁对象 38 | * @param value 对象 39 | * @return 40 | */ 41 | int tinybuf_value_free(tinybuf_value *value); 42 | 43 | /** 44 | * 重置对象为null类型 45 | * @param value 对象 46 | * @return 47 | */ 48 | int tinybuf_value_clear(tinybuf_value *value); 49 | 50 | /** 51 | * 复制对象 52 | * @param value 原对象 53 | * @return 54 | */ 55 | tinybuf_value *tinybuf_value_clone(const tinybuf_value *value); 56 | 57 | /** 58 | * 比较两个对象是否一致 59 | * @param value1 对象1 60 | * @param value2 对象2 61 | * @return 1代表一致,0不一致 62 | */ 63 | int tinybuf_value_is_same(const tinybuf_value *value1,const tinybuf_value *value2); 64 | 65 | /** 66 | * 获取数据类型 67 | * @param value 对象 68 | * @return 数据类型 69 | */ 70 | tinybuf_type tinybuf_value_get_type(const tinybuf_value *value); 71 | 72 | /** 73 | * 获取int值 74 | * @param value 对象 75 | * @return int值 76 | */ 77 | int64_t tinybuf_value_get_int(const tinybuf_value *value); 78 | 79 | /** 80 | * 获取double值 81 | * @param value 对象 82 | * @return double值 83 | */ 84 | double tinybuf_value_get_double(const tinybuf_value *value); 85 | 86 | /** 87 | * 读取bool值 88 | * @param value 对象 89 | * @return bool值 90 | */ 91 | int tinybuf_value_get_bool(const tinybuf_value *value); 92 | 93 | /** 94 | * 读取string值 95 | * @param value 对象 96 | * @return string值 97 | */ 98 | buffer* tinybuf_value_get_string(const tinybuf_value *value); 99 | 100 | /** 101 | * 获取array或map类型时的成员个数 102 | * @param value 对象 103 | * @return 成员个数 104 | */ 105 | int tinybuf_value_get_child_size(const tinybuf_value *value); 106 | 107 | /** 108 | * 获取成员 109 | * @param value 对象 110 | * @param index 索引 111 | * @return 成员对象的指针 112 | */ 113 | const tinybuf_value* tinybuf_value_get_array_child(const tinybuf_value *value,int index); 114 | 115 | /** 116 | * 根据key获取成员对象 117 | * @param value 对象 118 | * @param key 键 119 | * @return 成员对象 120 | */ 121 | const tinybuf_value* tinybuf_value_get_map_child(const tinybuf_value *value,const char *key); 122 | const tinybuf_value* tinybuf_value_get_map_child2(const tinybuf_value *value,const char *key, int key_len); 123 | 124 | /** 125 | * 获取map成员对象以及key 126 | * @param value 对象 127 | * @param index 索引 128 | * @param key key指针的指针 129 | * @return 成员对象的指针 130 | */ 131 | const tinybuf_value* tinybuf_value_get_map_child_and_key(const tinybuf_value *value, int index,buffer **key); 132 | ////////////////////////////////赋值//////////////////////////////// 133 | 134 | /** 135 | * 对象赋值为int类型 136 | * @param value 对象 137 | * @param int_val 整数 138 | * @return 139 | */ 140 | int tinybuf_value_init_int(tinybuf_value *value, int64_t int_val); 141 | 142 | /** 143 | * 对象赋值为bool型 144 | * @param value 对象 145 | * @param flag bool值 146 | * @return 147 | */ 148 | int tinybuf_value_init_bool(tinybuf_value *value, int flag); 149 | 150 | /** 151 | * 对象赋值为double类型 152 | * @param value 对象 153 | * @param db_val 双精度浮点型 154 | * @return 155 | */ 156 | int tinybuf_value_init_double(tinybuf_value *value, double db_val); 157 | 158 | /** 159 | * 对象赋值为string类型 160 | * @param value 对象 161 | * @param str 字符串 162 | * @param str_len 字符串长度 163 | * @return 164 | */ 165 | int tinybuf_value_init_string(tinybuf_value *value, const char *str, int str_len); 166 | 167 | /** 168 | * 无拷贝式赋值string 169 | * @param value 对象 170 | * @param buf 被转移所有权的对象,调用该函数后不能再buffer_free 171 | * @return 172 | */ 173 | int tinybuf_value_init_string2(tinybuf_value *value, buffer *buf); 174 | 175 | 176 | /** 177 | * 对象转换成map并添加键值对 178 | * @param parent 对象 179 | * @param key 键 180 | * @param value 被转移所有权的value子对象,调用该函数后不能再tinybuf_value_free 181 | * @return 182 | */ 183 | int tinybuf_value_map_set(tinybuf_value *parent, const char *key, tinybuf_value *value); 184 | 185 | /** 186 | * 对象转换成map并添加键值对 187 | * @param value 被转移所有权的value子对象,调用该函数后不能再tinybuf_value_free 188 | * @param key 被转移所有权的key对象,调用该函数后不能再buffer_free 189 | * @return 190 | */ 191 | int tinybuf_value_map_set2(tinybuf_value *parent,buffer *key,tinybuf_value *value); 192 | 193 | /** 194 | * 对象转换成array并添加成员 195 | * @param parent 对象 196 | * @param value 被转移所有权的value子对象,调用该函数后不能再tinybuf_value_free 197 | * @return 198 | */ 199 | int tinybuf_value_array_append(tinybuf_value *parent, tinybuf_value *value); 200 | 201 | 202 | ////////////////////////////////序列化//////////////////////////////// 203 | 204 | /** 205 | * 对象序列化成字节 206 | * @param value 对象 207 | * @param out 字节流存放地址 208 | * @return 209 | */ 210 | int tinybuf_value_serialize(const tinybuf_value *value, buffer *out); 211 | 212 | /** 213 | * 对象序列化成json字节流 214 | * @param value 对象 215 | * @param out 字节流存放地址 216 | * @param compact 是否紧凑(去除多余的空格回车符等) 217 | * @return 218 | */ 219 | int tinybuf_value_serialize_as_json(const tinybuf_value *value, buffer *out,int compact); 220 | 221 | ////////////////////////////////反序列化//////////////////////////////// 222 | 223 | /** 224 | * 反序列化对象 225 | * @param ptr 字节流 226 | * @param size 字节流长度 227 | * @param out 输出对象,必须不为空 228 | * @return 序列化消耗的字节数 229 | */ 230 | int tinybuf_value_deserialize(const char *ptr, int size, tinybuf_value *out); 231 | 232 | /** 233 | * 加载value部分 234 | * @param ptr json字符串 235 | * @param size json字符串长度 236 | * @param out vlue值输出 237 | * @return 消耗的字节数 238 | */ 239 | int tinybuf_value_deserialize_from_json(const char *ptr, int size, tinybuf_value *out); 240 | 241 | 242 | #ifdef __cplusplus 243 | } 244 | #endif // __cplusplus 245 | 246 | #endif //TINYBUF_H 247 | -------------------------------------------------------------------------------- /src/source/avl-tree.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2005-2008, Simon Howard 4 | 5 | Permission to use, copy, modify, and/or distribute this software 6 | for any purpose with or without fee is hereby granted, provided 7 | that the above copyright notice and this permission notice appear 8 | in all copies. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 | AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 14 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 16 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 17 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | 19 | */ 20 | 21 | /** @file avl-tree.h 22 | * 23 | * @brief Balanced binary tree 24 | * 25 | * The AVL tree structure is a balanced binary tree which stores 26 | * a collection of nodes (see @ref AVLTreeNode). Each node has 27 | * a key and a value associated with it. The nodes are sorted 28 | * within the tree based on the order of their keys. Modifications 29 | * to the tree are constructed such that the tree remains 30 | * balanced at all times (there are always roughly equal numbers 31 | * of nodes on either side of the tree). 32 | * 33 | * Balanced binary trees have several uses. They can be used 34 | * as a mapping (searching for a value based on its key), or 35 | * as a set of keys which is always ordered. 36 | * 37 | * To create a new AVL tree, use @ref avl_tree_new. To destroy 38 | * an AVL tree, use @ref avl_tree_free. 39 | * 40 | * To insert a new key-value pair into an AVL tree, use 41 | * @ref avl_tree_insert. To remove an entry from an 42 | * AVL tree, use @ref avl_tree_remove or @ref avl_tree_remove_node. 43 | * 44 | * To search an AVL tree, use @ref avl_tree_lookup or 45 | * @ref avl_tree_lookup_node. 46 | * 47 | * Tree nodes can be queried using the 48 | * @ref avl_tree_node_child, 49 | * @ref avl_tree_node_parent, 50 | * @ref avl_tree_node_key and 51 | * @ref avl_tree_node_value functions. 52 | */ 53 | 54 | #ifndef ALGORITHM_AVLTREE_H 55 | #define ALGORITHM_AVLTREE_H 56 | 57 | #ifdef __cplusplus 58 | extern "C" { 59 | #endif 60 | 61 | /** 62 | * An AVL tree balanced binary tree. 63 | * 64 | * @see avl_tree_new 65 | */ 66 | 67 | typedef struct _AVLTree AVLTree; 68 | 69 | /** 70 | * A key for an @ref AVLTree. 71 | */ 72 | 73 | typedef void *AVLTreeKey; 74 | 75 | /** 76 | * A value stored in an @ref AVLTree. 77 | */ 78 | 79 | typedef void *AVLTreeValue; 80 | 81 | /** 82 | * A null @ref AVLTreeValue. 83 | */ 84 | 85 | #define AVL_TREE_NULL ((void *) 0) 86 | 87 | /** 88 | * A node in an AVL tree. 89 | * 90 | * @see avl_tree_node_left_child 91 | * @see avl_tree_node_right_child 92 | * @see avl_tree_node_parent 93 | * @see avl_tree_node_key 94 | * @see avl_tree_node_value 95 | */ 96 | 97 | typedef struct _AVLTreeNode AVLTreeNode; 98 | 99 | /** 100 | * An @ref AVLTreeNode can have left and right children. 101 | */ 102 | 103 | typedef enum { 104 | AVL_TREE_NODE_LEFT = 0, 105 | AVL_TREE_NODE_RIGHT = 1 106 | } AVLTreeNodeSide; 107 | 108 | /** 109 | * Type of function used to compare keys in an AVL tree. 110 | * 111 | * @param key1 The first key. 112 | * @param key2 The second key. 113 | * @return A negative number if value1 should be sorted 114 | * before value2, a positive number if value2 should 115 | * be sorted before value1, zero if the two keys 116 | * are equal. 117 | */ 118 | 119 | typedef int (*AVLTreeCompareFunc)(AVLTreeKey key1, AVLTreeKey key2); 120 | 121 | /** 122 | * key内存释放函数 123 | */ 124 | typedef void (*AVLTreeFreeKeyFunc)(AVLTreeKey key); 125 | 126 | /** 127 | * value释放函数 128 | */ 129 | typedef void (*AVLTreeFreeValueFunc)(AVLTreeValue value); 130 | 131 | 132 | 133 | /** 134 | * Create a new AVL tree. 135 | * 136 | * @param compare_func Function to use when comparing keys in the tree. 137 | * @return A new AVL tree, or NULL if it was not possible 138 | * to allocate the memory. 139 | */ 140 | 141 | AVLTree *avl_tree_new(AVLTreeCompareFunc compare_func); 142 | 143 | /** 144 | * Destroy an AVL tree. 145 | * 146 | * @param tree The tree to destroy. 147 | */ 148 | 149 | void avl_tree_free(AVLTree *tree); 150 | 151 | /** 152 | * Insert a new key-value pair into an AVL tree. 153 | * 154 | * @param tree The tree. 155 | * @param key The key to insert. 156 | * @param value The value to insert. 157 | * @return The newly created tree node containing the 158 | * key and value, or NULL if it was not possible 159 | * to allocate the new memory. 160 | */ 161 | 162 | AVLTreeNode *avl_tree_insert(AVLTree *tree, 163 | AVLTreeKey key, 164 | AVLTreeValue value, 165 | AVLTreeFreeKeyFunc freeKey, 166 | AVLTreeFreeValueFunc freeValue); 167 | 168 | /** 169 | * Remove a node from a tree. 170 | * 171 | * @param tree The tree. 172 | * @param node The node to remove 173 | */ 174 | 175 | void avl_tree_remove_node(AVLTree *tree, AVLTreeNode *node); 176 | 177 | /** 178 | * Remove an entry from a tree, specifying the key of the node to 179 | * remove. 180 | * 181 | * @param tree The tree. 182 | * @param key The key of the node to remove. 183 | * @return Zero (false) if no node with the specified key was 184 | * found in the tree, non-zero (true) if a node with 185 | * the specified key was removed. 186 | */ 187 | 188 | int avl_tree_remove(AVLTree *tree, AVLTreeKey key); 189 | 190 | /** 191 | * Search an AVL tree for a node with a particular key. This uses 192 | * the tree as a mapping. 193 | * 194 | * @param tree The AVL tree to search. 195 | * @param key The key to search for. 196 | * @return The tree node containing the given key, or NULL 197 | * if no entry with the given key is found. 198 | */ 199 | 200 | AVLTreeNode *avl_tree_lookup_node(AVLTree *tree, AVLTreeKey key); 201 | 202 | /** 203 | * Search an AVL tree for a value corresponding to a particular key. 204 | * This uses the tree as a mapping. Note that this performs 205 | * identically to @ref avl_tree_lookup_node, except that the value 206 | * at the node is returned rather than the node itself. 207 | * 208 | * @param tree The AVL tree to search. 209 | * @param key The key to search for. 210 | * @return The value associated with the given key, or 211 | * @ref AVL_TREE_NULL if no entry with the given key is 212 | * found. 213 | */ 214 | 215 | AVLTreeValue avl_tree_lookup(AVLTree *tree, AVLTreeKey key); 216 | 217 | /** 218 | * Find the root node of a tree. 219 | * 220 | * @param tree The tree. 221 | * @return The root node of the tree, or NULL if the tree is 222 | * empty. 223 | */ 224 | 225 | AVLTreeNode *avl_tree_root_node(AVLTree *tree); 226 | 227 | /** 228 | * Retrieve the key for a given tree node. 229 | * 230 | * @param node The tree node. 231 | * @return The key to the given node. 232 | */ 233 | 234 | AVLTreeKey avl_tree_node_key(AVLTreeNode *node); 235 | 236 | /** 237 | * Retrieve the value at a given tree node. 238 | * 239 | * @param node The tree node. 240 | * @return The value at the given node. 241 | */ 242 | 243 | AVLTreeValue avl_tree_node_value(AVLTreeNode *node); 244 | 245 | /** 246 | * Find the child of a given tree node. 247 | * 248 | * @param node The tree node. 249 | * @param side Which child node to get (left or right) 250 | * @return The child of the tree node, or NULL if the 251 | * node has no child on the given side. 252 | */ 253 | 254 | AVLTreeNode *avl_tree_node_child(AVLTreeNode *node, AVLTreeNodeSide side); 255 | 256 | /** 257 | * Find the parent node of a given tree node. 258 | * 259 | * @param node The tree node. 260 | * @return The parent node of the tree node, or NULL if 261 | * this is the root node. 262 | */ 263 | 264 | AVLTreeNode *avl_tree_node_parent(AVLTreeNode *node); 265 | 266 | /** 267 | * Find the height of a subtree. 268 | * 269 | * @param node The root node of the subtree. 270 | * @return The height of the subtree. 271 | */ 272 | 273 | int avl_tree_subtree_height(AVLTreeNode *node); 274 | 275 | /** 276 | * Convert the keys in an AVL tree into a C array. This allows 277 | * the tree to be used as an ordered set. 278 | * 279 | * @param tree The tree. 280 | * @return A newly allocated C array containing all the keys 281 | * in the tree, in order. The length of the array 282 | * is equal to the number of entries in the tree 283 | * (see @ref avl_tree_num_entries). 284 | */ 285 | 286 | AVLTreeKey *avl_tree_to_array(AVLTree *tree); 287 | 288 | 289 | 290 | /** 291 | * 获取节点数组,方便遍历 292 | * @param tree 293 | * @return 294 | */ 295 | AVLTreeNode **avl_tree_to_array_node(AVLTree *tree); 296 | 297 | 298 | /** 299 | * Retrieve the number of entries in the tree. 300 | * 301 | * @param tree The tree. 302 | * @return The number of key-value pairs stored in the tree. 303 | */ 304 | 305 | unsigned int avl_tree_num_entries(AVLTree *tree); 306 | 307 | 308 | /** 309 | * 根据索引获取节点 310 | * @param tree 311 | * @param index 索引号 312 | * @return 313 | */ 314 | AVLTreeNode *avl_tree_get_node_by_index(AVLTree *tree , int index); 315 | 316 | /** 317 | * @return 1 代表中断遍历 318 | */ 319 | typedef int (*on_avl_tree_node)(void *user_data,AVLTreeNode *node); 320 | 321 | /** 322 | * 遍历所有节点 323 | * @param AVLTree 树 324 | * @return 1 代表遍历被中断 325 | */ 326 | int avl_tree_for_each_node(AVLTree *tree,void *user_data, on_avl_tree_node cb); 327 | 328 | #ifdef __cplusplus 329 | } 330 | #endif 331 | 332 | #endif /* #ifndef ALGORITHM_AVLTREE_H */ 333 | 334 | -------------------------------------------------------------------------------- /benchmark.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by xzl on 2019/9/26. 3 | // 4 | 5 | #include "tinybuf.h" 6 | #include "tinybuf_log.h" 7 | #include "jsoncpp/json.h" 8 | #include 9 | #ifndef _WIN32 10 | #include 11 | #else 12 | #include 13 | #endif 14 | #include 15 | 16 | 17 | using namespace std; 18 | using namespace Json; 19 | 20 | #define JSON_COMPACT 0 21 | #define MAX_COUNT 1 * 10000 22 | 23 | static inline uint64_t getCurrentMicrosecondOrigin() { 24 | #ifndef _WIN32 25 | struct timeval tv; 26 | gettimeofday(&tv, NULL); 27 | return tv.tv_sec * 1000000LL + tv.tv_usec; 28 | #else 29 | return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 30 | #endif 31 | } 32 | 33 | class TimePrinter { 34 | public: 35 | TimePrinter(const string &str){ 36 | _str = str; 37 | _start_time = getCurrentMicrosecondOrigin(); 38 | } 39 | ~TimePrinter(){ 40 | LOGD("%stime spent:%lld ms",_str.data(),(long long)((getCurrentMicrosecondOrigin() - _start_time) / 1000)); 41 | } 42 | 43 | private: 44 | string _str; 45 | uint64_t _start_time; 46 | }; 47 | 48 | 49 | tinybuf_value *tinybuf_make_test_value(){ 50 | tinybuf_value *value = tinybuf_value_alloc(); 51 | { 52 | tinybuf_value *child = tinybuf_value_alloc(); 53 | tinybuf_value_init_double(child,3.1415); 54 | tinybuf_value_map_set(value,"double",child); 55 | } 56 | 57 | { 58 | tinybuf_value *child = tinybuf_value_alloc(); 59 | tinybuf_value_init_double(child,0.000000012345); 60 | tinybuf_value_map_set(value,"little double",child); 61 | } 62 | 63 | { 64 | tinybuf_value *child = tinybuf_value_alloc(); 65 | tinybuf_value_map_set(value,"null",child); 66 | } 67 | 68 | { 69 | tinybuf_value *child = tinybuf_value_alloc(); 70 | tinybuf_value_init_int(child,123456789); 71 | tinybuf_value_map_set(value,"+int",child); 72 | } 73 | 74 | { 75 | tinybuf_value *child = tinybuf_value_alloc(); 76 | tinybuf_value_init_int(child,-123456789); 77 | tinybuf_value_map_set(value,"-int",child); 78 | } 79 | 80 | { 81 | tinybuf_value *child = tinybuf_value_alloc(); 82 | tinybuf_value_init_bool(child,1); 83 | tinybuf_value_map_set(value,"bool true",child); 84 | } 85 | 86 | { 87 | tinybuf_value *child = tinybuf_value_alloc(); 88 | tinybuf_value_init_bool(child,0); 89 | tinybuf_value_map_set(value,"bool false",child); 90 | } 91 | 92 | { 93 | tinybuf_value *child = tinybuf_value_alloc(); 94 | tinybuf_value_init_string(child,"hello world string",0); 95 | tinybuf_value_map_set(value,"string",child); 96 | } 97 | 98 | { 99 | tinybuf_value *child = tinybuf_value_alloc(); 100 | tinybuf_value_init_string(child,"",0); 101 | tinybuf_value_map_set(value,"empty string",child); 102 | } 103 | 104 | { 105 | tinybuf_value *child = tinybuf_value_alloc_with_type(tinybuf_map); 106 | tinybuf_value_map_set(value,"empty map",child); 107 | } 108 | 109 | { 110 | tinybuf_value *child = tinybuf_value_alloc_with_type(tinybuf_array); 111 | tinybuf_value_map_set(value,"empty array",child); 112 | } 113 | 114 | { 115 | tinybuf_value *child = tinybuf_value_alloc(); 116 | char bytes[] = "\x1F \xAF 1234\r\nabc\t\b\f\\\"ssds\"\x00\x01\x02中文13kxsdlasdl21"; 117 | tinybuf_value_init_string(child,bytes, sizeof(bytes)); 118 | tinybuf_value_map_set(value,"bytes\r\n",child); 119 | } 120 | 121 | { 122 | tinybuf_value *child = tinybuf_value_alloc(); 123 | char bytes[] = "bytes\r\n\x1F \xAF 1234\r\nabc\t\b\f\\\"ssds\"\x03\x01\x02中文13kxsdlasdl21"; 124 | tinybuf_value_init_string(child,bytes, sizeof(bytes)); 125 | //json cpp 不支持key中带'\0' 126 | tinybuf_value_map_set2(value,buffer_alloc2(bytes, sizeof(bytes) - 1),child); 127 | } 128 | 129 | 130 | { 131 | tinybuf_value *child = tinybuf_value_alloc(); 132 | { 133 | tinybuf_value *array_child = tinybuf_value_alloc(); 134 | tinybuf_value_init_double(array_child,3.1415); 135 | tinybuf_value_array_append(child,array_child); 136 | } 137 | 138 | { 139 | tinybuf_value *array_child = tinybuf_value_alloc(); 140 | tinybuf_value_init_int(array_child,123456789); 141 | tinybuf_value_array_append(child,array_child); 142 | } 143 | 144 | { 145 | tinybuf_value *array_child = tinybuf_value_alloc(); 146 | tinybuf_value_init_int(array_child,-123456789); 147 | tinybuf_value_array_append(child,array_child); 148 | } 149 | 150 | { 151 | tinybuf_value *array_child = tinybuf_value_alloc(); 152 | tinybuf_value_init_bool(array_child,1); 153 | tinybuf_value_array_append(child,array_child); 154 | } 155 | 156 | { 157 | tinybuf_value *array_child = tinybuf_value_alloc(); 158 | tinybuf_value_init_bool(array_child,0); 159 | tinybuf_value_array_append(child,array_child); 160 | } 161 | 162 | tinybuf_value_array_append(child,tinybuf_value_clone(child)); 163 | tinybuf_value_array_append(child,tinybuf_value_clone(value)); 164 | tinybuf_value_map_set(value,"array",child); 165 | } 166 | 167 | tinybuf_value_map_set(value,"map",tinybuf_value_clone(value)); 168 | return value; 169 | } 170 | 171 | 172 | void tinybuf_value_printf(const tinybuf_value *value){ 173 | buffer *out = buffer_alloc(); 174 | tinybuf_value_serialize_as_json(value, out,JSON_COMPACT); 175 | LOGI("\r\n%s",buffer_get_data(out)); 176 | buffer_free(out); 177 | } 178 | 179 | tinybuf_value *deserialize_from_jsoncpp(const char *json){ 180 | Value obj; 181 | stringstream ss(json); 182 | ss >> obj; 183 | string new_json = obj.toStyledString(); 184 | 185 | tinybuf_value *ret = tinybuf_value_alloc(); 186 | tinybuf_value_deserialize_from_json(new_json.data(),new_json.size(),ret); 187 | return ret; 188 | } 189 | 190 | 191 | void tinybuf_value_test(){ 192 | tinybuf_value *value_origin = tinybuf_make_test_value(); 193 | tinybuf_value *value_deserialize = tinybuf_value_alloc(); 194 | tinybuf_value *value_deserialize_from_json = tinybuf_value_alloc(); 195 | 196 | buffer *buf = buffer_alloc(); 197 | 198 | tinybuf_value_serialize(value_origin,buf); 199 | tinybuf_value_deserialize(buffer_get_data(buf),buffer_get_length(buf),value_deserialize); 200 | 201 | buffer_set_length(buf,0); 202 | tinybuf_value_serialize_as_json(value_origin,buf,JSON_COMPACT); 203 | tinybuf_value_deserialize_from_json(buffer_get_data(buf),buffer_get_length(buf),value_deserialize_from_json); 204 | tinybuf_value *value_deserialize_from_jsoncpp = deserialize_from_jsoncpp(buffer_get_data(buf)); 205 | 206 | assert(tinybuf_value_is_same(value_origin,value_deserialize)); 207 | assert(tinybuf_value_is_same(value_origin,value_deserialize_from_json)); 208 | assert(tinybuf_value_is_same(value_origin,value_deserialize_from_jsoncpp)); 209 | 210 | tinybuf_value_printf(value_origin); 211 | 212 | tinybuf_value_free(value_origin); 213 | tinybuf_value_free(value_deserialize); 214 | tinybuf_value_free(value_deserialize_from_json); 215 | tinybuf_value_free(value_deserialize_from_jsoncpp); 216 | buffer_free(buf); 217 | } 218 | 219 | int main(int argc,char *argv[]){ 220 | tinybuf_value_test(); 221 | 222 | //几米对象 223 | tinybuf_value *value = tinybuf_make_test_value(); 224 | //jimi格式序列化的数据 225 | buffer *buf_binary = buffer_alloc(); 226 | //json格式序列化的数据 227 | buffer *buf_json = buffer_alloc(); 228 | 229 | //几米序列化 230 | tinybuf_value_serialize(value,buf_binary); 231 | //json序列化 232 | tinybuf_value_serialize_as_json(value,buf_json,JSON_COMPACT); 233 | 234 | 235 | { 236 | //测试几米序列化性能 237 | TimePrinter printer("serialize to tinybuf"); 238 | buffer *buf = buffer_alloc(); 239 | for(int i = 0 ; i < MAX_COUNT; ++i ){ 240 | buffer_set_length(buf,0); 241 | tinybuf_value_serialize(value,buf); 242 | } 243 | buffer_free(buf); 244 | } 245 | 246 | { 247 | //测试几米序列化成json性能 248 | TimePrinter printer("serialize to json"); 249 | buffer *buf = buffer_alloc(); 250 | for(int i = 0 ; i < MAX_COUNT; ++i ){ 251 | buffer_set_length(buf,0); 252 | tinybuf_value_serialize_as_json(value,buf,JSON_COMPACT); 253 | } 254 | buffer_free(buf); 255 | } 256 | 257 | { 258 | //测试json列化性能 259 | TimePrinter printer("jsoncpp serialize"); 260 | //json对象 261 | Value obj; 262 | stringstream ss(buffer_get_data(buf_json)); 263 | ss >> obj; 264 | for(int i = 0 ; i < MAX_COUNT; ++i ){ 265 | obj.toStyledString(); 266 | } 267 | } 268 | 269 | { 270 | //测试几米反序列化性能 271 | TimePrinter printer("tinybuf deserialize"); 272 | tinybuf_value *value_deserialize = tinybuf_value_alloc(); 273 | for(int i = 0 ; i < MAX_COUNT; ++i ){ 274 | tinybuf_value_clear(value_deserialize); 275 | tinybuf_value_deserialize(buffer_get_data(buf_binary),buffer_get_length(buf_binary),value_deserialize); 276 | } 277 | tinybuf_value_free(value_deserialize); 278 | 279 | } 280 | 281 | { 282 | //测试几米反序列json化性能 283 | TimePrinter printer("json deserialize"); 284 | tinybuf_value *value_deserialize = tinybuf_value_alloc(); 285 | for(int i = 0 ; i < MAX_COUNT; ++i ){ 286 | tinybuf_value_clear(value_deserialize); 287 | tinybuf_value_deserialize_from_json(buffer_get_data(buf_json),buffer_get_length(buf_json),value_deserialize); 288 | } 289 | tinybuf_value_free(value_deserialize); 290 | } 291 | 292 | { 293 | //测试json反序列化性能 294 | TimePrinter printer("jsoncpp deserialize"); 295 | Value obj; 296 | Json::Reader reader; 297 | string str(buffer_get_data(buf_json)); 298 | for(int i = 0 ; i < MAX_COUNT; ++i ){ 299 | reader.parse(str, obj); 300 | } 301 | } 302 | 303 | buffer_free(buf_binary); 304 | buffer_free(buf_json); 305 | tinybuf_value_free(value); 306 | return 0; 307 | } 308 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/writer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_WRITER_H_INCLUDED 7 | #define JSON_WRITER_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "value.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | #include 13 | #include 14 | #include 15 | 16 | // Disable warning C4251: : needs to have dll-interface to 17 | // be used by... 18 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 19 | #pragma warning(push) 20 | #pragma warning(disable : 4251) 21 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 22 | 23 | namespace Json { 24 | 25 | class Value; 26 | 27 | /** 28 | 29 | Usage: 30 | \code 31 | using namespace Json; 32 | void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { 33 | std::unique_ptr const writer( 34 | factory.newStreamWriter()); 35 | writer->write(value, &std::cout); 36 | std::cout << std::endl; // add lf and flush 37 | } 38 | \endcode 39 | */ 40 | class JSON_API StreamWriter { 41 | protected: 42 | std::ostream* sout_; // not owned; will not delete 43 | public: 44 | StreamWriter(); 45 | virtual ~StreamWriter(); 46 | /** Write Value into document as configured in sub-class. 47 | Do not take ownership of sout, but maintain a reference during function. 48 | \pre sout != NULL 49 | \return zero on success (For now, we always return zero, so check the stream instead.) 50 | \throw std::exception possibly, depending on configuration 51 | */ 52 | virtual int write(Value const& root, std::ostream* sout) = 0; 53 | 54 | /** \brief A simple abstract factory. 55 | */ 56 | class JSON_API Factory { 57 | public: 58 | virtual ~Factory(); 59 | /** \brief Allocate a CharReader via operator new(). 60 | * \throw std::exception if something goes wrong (e.g. invalid settings) 61 | */ 62 | virtual StreamWriter* newStreamWriter() const = 0; 63 | }; // Factory 64 | }; // StreamWriter 65 | 66 | /** \brief Write into stringstream, then return string, for convenience. 67 | * A StreamWriter will be created from the factory, used, and then deleted. 68 | */ 69 | std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root); 70 | 71 | 72 | /** \brief Build a StreamWriter implementation. 73 | 74 | Usage: 75 | \code 76 | using namespace Json; 77 | Value value = ...; 78 | StreamWriterBuilder builder; 79 | builder["commentStyle"] = "None"; 80 | builder["indentation"] = " "; // or whatever you like 81 | std::unique_ptr writer( 82 | builder.newStreamWriter()); 83 | writer->write(value, &std::cout); 84 | std::cout << std::endl; // add lf and flush 85 | \endcode 86 | */ 87 | class JSON_API StreamWriterBuilder : public StreamWriter::Factory { 88 | public: 89 | // Note: We use a Json::Value so that we can add data-members to this class 90 | // without a major version bump. 91 | /** Configuration of this builder. 92 | Available settings (case-sensitive): 93 | - "commentStyle": "None" or "All" 94 | - "indentation": "" 95 | - "enableYAMLCompatibility": false or true 96 | - slightly change the whitespace around colons 97 | - "dropNullPlaceholders": false or true 98 | - Drop the "null" string from the writer's output for nullValues. 99 | Strictly speaking, this is not valid JSON. But when the output is being 100 | fed to a browser's Javascript, it makes for smaller output and the 101 | browser can handle the output just fine. 102 | 103 | You can examine 'settings_` yourself 104 | to see the defaults. You can also write and read them just like any 105 | JSON Value. 106 | \sa setDefaults() 107 | */ 108 | Json::Value settings_; 109 | 110 | StreamWriterBuilder(); 111 | virtual ~StreamWriterBuilder(); 112 | 113 | /** 114 | * \throw std::exception if something goes wrong (e.g. invalid settings) 115 | */ 116 | virtual StreamWriter* newStreamWriter() const; 117 | 118 | /** \return true if 'settings' are legal and consistent; 119 | * otherwise, indicate bad settings via 'invalid'. 120 | */ 121 | bool validate(Json::Value* invalid) const; 122 | /** A simple way to update a specific setting. 123 | */ 124 | Value& operator[](std::string key); 125 | 126 | /** Called by ctor, but you can use this to reset settings_. 127 | * \pre 'settings' != NULL (but Json::null is fine) 128 | * \remark Defaults: 129 | * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults 130 | */ 131 | static void setDefaults(Json::Value* settings); 132 | }; 133 | 134 | /** \brief Abstract class for writers. 135 | * \deprecated Use StreamWriter. (And really, this is an implementation detail.) 136 | */ 137 | class JSON_API Writer { 138 | public: 139 | virtual ~Writer(); 140 | 141 | virtual std::string write(const Value& root) = 0; 142 | }; 143 | 144 | /** \brief Outputs a Value in JSON format 145 | *without formatting (not human friendly). 146 | * 147 | * The JSON document is written in a single line. It is not intended for 'human' 148 | *consumption, 149 | * but may be usefull to support feature such as RPC where bandwith is limited. 150 | * \sa Reader, Value 151 | * \deprecated Use StreamWriterBuilder. 152 | */ 153 | class JSON_API FastWriter : public Writer { 154 | 155 | public: 156 | FastWriter(); 157 | virtual ~FastWriter() {} 158 | 159 | void enableYAMLCompatibility(); 160 | 161 | /** \brief Drop the "null" string from the writer's output for nullValues. 162 | * Strictly speaking, this is not valid JSON. But when the output is being 163 | * fed to a browser's Javascript, it makes for smaller output and the 164 | * browser can handle the output just fine. 165 | */ 166 | void dropNullPlaceholders(); 167 | 168 | void omitEndingLineFeed(); 169 | 170 | public: // overridden from Writer 171 | virtual std::string write(const Value& root); 172 | 173 | private: 174 | void writeValue(const Value& value); 175 | 176 | std::string document_; 177 | bool yamlCompatiblityEnabled_; 178 | bool dropNullPlaceholders_; 179 | bool omitEndingLineFeed_; 180 | }; 181 | 182 | /** \brief Writes a Value in JSON format in a 183 | *human friendly way. 184 | * 185 | * The rules for line break and indent are as follow: 186 | * - Object value: 187 | * - if empty then print {} without indent and line break 188 | * - if not empty the print '{', line break & indent, print one value per 189 | *line 190 | * and then unindent and line break and print '}'. 191 | * - Array value: 192 | * - if empty then print [] without indent and line break 193 | * - if the array contains no object value, empty array or some other value 194 | *types, 195 | * and all the values fit on one lines, then print the array on a single 196 | *line. 197 | * - otherwise, it the values do not fit on one line, or the array contains 198 | * object or non empty array, then print one value per line. 199 | * 200 | * If the Value have comments then they are outputed according to their 201 | *#CommentPlacement. 202 | * 203 | * \sa Reader, Value, Value::setComment() 204 | * \deprecated Use StreamWriterBuilder. 205 | */ 206 | class JSON_API StyledWriter : public Writer { 207 | public: 208 | StyledWriter(); 209 | virtual ~StyledWriter() {} 210 | 211 | public: // overridden from Writer 212 | /** \brief Serialize a Value in JSON format. 213 | * \param root Value to serialize. 214 | * \return String containing the JSON document that represents the root value. 215 | */ 216 | virtual std::string write(const Value& root); 217 | 218 | private: 219 | void writeValue(const Value& value); 220 | void writeArrayValue(const Value& value); 221 | bool isMultineArray(const Value& value); 222 | void pushValue(const std::string& value); 223 | void writeIndent(); 224 | void writeWithIndent(const std::string& value); 225 | void indent(); 226 | void unindent(); 227 | void writeCommentBeforeValue(const Value& root); 228 | void writeCommentAfterValueOnSameLine(const Value& root); 229 | bool hasCommentForValue(const Value& value); 230 | static std::string normalizeEOL(const std::string& text); 231 | 232 | typedef std::vector ChildValues; 233 | 234 | ChildValues childValues_; 235 | std::string document_; 236 | std::string indentString_; 237 | int rightMargin_; 238 | int indentSize_; 239 | bool addChildValues_; 240 | }; 241 | 242 | /** \brief Writes a Value in JSON format in a 243 | human friendly way, 244 | to a stream rather than to a string. 245 | * 246 | * The rules for line break and indent are as follow: 247 | * - Object value: 248 | * - if empty then print {} without indent and line break 249 | * - if not empty the print '{', line break & indent, print one value per 250 | line 251 | * and then unindent and line break and print '}'. 252 | * - Array value: 253 | * - if empty then print [] without indent and line break 254 | * - if the array contains no object value, empty array or some other value 255 | types, 256 | * and all the values fit on one lines, then print the array on a single 257 | line. 258 | * - otherwise, it the values do not fit on one line, or the array contains 259 | * object or non empty array, then print one value per line. 260 | * 261 | * If the Value have comments then they are outputed according to their 262 | #CommentPlacement. 263 | * 264 | * \param indentation Each level will be indented by this amount extra. 265 | * \sa Reader, Value, Value::setComment() 266 | * \deprecated Use StreamWriterBuilder. 267 | */ 268 | class JSON_API StyledStreamWriter { 269 | public: 270 | StyledStreamWriter(std::string indentation = "\t"); 271 | ~StyledStreamWriter() {} 272 | 273 | public: 274 | /** \brief Serialize a Value in JSON format. 275 | * \param out Stream to write to. (Can be ostringstream, e.g.) 276 | * \param root Value to serialize. 277 | * \note There is no point in deriving from Writer, since write() should not 278 | * return a value. 279 | */ 280 | void write(std::ostream& out, const Value& root); 281 | 282 | private: 283 | void writeValue(const Value& value); 284 | void writeArrayValue(const Value& value); 285 | bool isMultineArray(const Value& value); 286 | void pushValue(const std::string& value); 287 | void writeIndent(); 288 | void writeWithIndent(const std::string& value); 289 | void indent(); 290 | void unindent(); 291 | void writeCommentBeforeValue(const Value& root); 292 | void writeCommentAfterValueOnSameLine(const Value& root); 293 | bool hasCommentForValue(const Value& value); 294 | static std::string normalizeEOL(const std::string& text); 295 | 296 | typedef std::vector ChildValues; 297 | 298 | ChildValues childValues_; 299 | std::ostream* document_; 300 | std::string indentString_; 301 | int rightMargin_; 302 | std::string indentation_; 303 | bool addChildValues_ : 1; 304 | bool indented_ : 1; 305 | }; 306 | 307 | #if defined(JSON_HAS_INT64) 308 | std::string JSON_API valueToString(Int value); 309 | std::string JSON_API valueToString(UInt value); 310 | #endif // if defined(JSON_HAS_INT64) 311 | std::string JSON_API valueToString(LargestInt value); 312 | std::string JSON_API valueToString(LargestUInt value); 313 | std::string JSON_API valueToString(double value); 314 | std::string JSON_API valueToString(bool value); 315 | std::string JSON_API valueToQuotedString(const char* value); 316 | 317 | /// \brief Output using the StyledStreamWriter. 318 | /// \see Json::operator>>() 319 | JSON_API std::ostream& operator<<(std::ostream&, const Value& root); 320 | 321 | } // namespace Json 322 | 323 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 324 | #pragma warning(pop) 325 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 326 | 327 | #endif // JSON_WRITER_H_INCLUDED 328 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/reader.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_READER_H_INCLUDED 7 | #define CPPTL_JSON_READER_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "../jsoncpp/features.h" 11 | #include "../jsoncpp/value.h" 12 | #endif // if !defined(JSON_IS_AMALGAMATION) 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // Disable warning C4251: : needs to have dll-interface to 20 | // be used by... 21 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 22 | #pragma warning(push) 23 | #pragma warning(disable : 4251) 24 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 25 | 26 | namespace Json { 27 | 28 | /** \brief Unserialize a JSON document into a 29 | *Value. 30 | * 31 | * \deprecated Use CharReader and CharReaderBuilder. 32 | */ 33 | class JSON_API Reader { 34 | public: 35 | typedef char Char; 36 | typedef const Char* Location; 37 | 38 | /** \brief An error tagged with where in the JSON text it was encountered. 39 | * 40 | * The offsets give the [start, limit) range of bytes within the text. Note 41 | * that this is bytes, not codepoints. 42 | * 43 | */ 44 | struct StructuredError { 45 | size_t offset_start; 46 | size_t offset_limit; 47 | std::string message; 48 | }; 49 | 50 | /** \brief Constructs a Reader allowing all features 51 | * for parsing. 52 | */ 53 | Reader(); 54 | 55 | /** \brief Constructs a Reader allowing the specified feature set 56 | * for parsing. 57 | */ 58 | Reader(const Features& features); 59 | 60 | /** \brief Read a Value from a JSON 61 | * document. 62 | * \param document UTF-8 encoded string containing the document to read. 63 | * \param root [out] Contains the root value of the document if it was 64 | * successfully parsed. 65 | * \param collectComments \c true to collect comment and allow writing them 66 | * back during 67 | * serialization, \c false to discard comments. 68 | * This parameter is ignored if 69 | * Features::allowComments_ 70 | * is \c false. 71 | * \return \c true if the document was successfully parsed, \c false if an 72 | * error occurred. 73 | */ 74 | bool 75 | parse(const std::string& document, Value& root, bool collectComments = true); 76 | 77 | /** \brief Read a Value from a JSON 78 | document. 79 | * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the 80 | document to read. 81 | * \param endDoc Pointer on the end of the UTF-8 encoded string of the 82 | document to read. 83 | * Must be >= beginDoc. 84 | * \param root [out] Contains the root value of the document if it was 85 | * successfully parsed. 86 | * \param collectComments \c true to collect comment and allow writing them 87 | back during 88 | * serialization, \c false to discard comments. 89 | * This parameter is ignored if 90 | Features::allowComments_ 91 | * is \c false. 92 | * \return \c true if the document was successfully parsed, \c false if an 93 | error occurred. 94 | */ 95 | bool parse(const char* beginDoc, 96 | const char* endDoc, 97 | Value& root, 98 | bool collectComments = true); 99 | 100 | /// \brief Parse from input stream. 101 | /// \see Json::operator>>(std::istream&, Json::Value&). 102 | bool parse(std::istream& is, Value& root, bool collectComments = true); 103 | 104 | /** \brief Returns a user friendly string that list errors in the parsed 105 | * document. 106 | * \return Formatted error message with the list of errors with their location 107 | * in 108 | * the parsed document. An empty string is returned if no error 109 | * occurred 110 | * during parsing. 111 | * \deprecated Use getFormattedErrorMessages() instead (typo fix). 112 | */ 113 | JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") 114 | std::string getFormatedErrorMessages() const; 115 | 116 | /** \brief Returns a user friendly string that list errors in the parsed 117 | * document. 118 | * \return Formatted error message with the list of errors with their location 119 | * in 120 | * the parsed document. An empty string is returned if no error 121 | * occurred 122 | * during parsing. 123 | */ 124 | std::string getFormattedErrorMessages() const; 125 | 126 | /** \brief Returns a vector of structured erros encounted while parsing. 127 | * \return A (possibly empty) vector of StructuredError objects. Currently 128 | * only one error can be returned, but the caller should tolerate 129 | * multiple 130 | * errors. This can occur if the parser recovers from a non-fatal 131 | * parse error and then encounters additional errors. 132 | */ 133 | std::vector getStructuredErrors() const; 134 | 135 | /** \brief Add a semantic error message. 136 | * \param value JSON Value location associated with the error 137 | * \param message The error message. 138 | * \return \c true if the error was successfully added, \c false if the 139 | * Value offset exceeds the document size. 140 | */ 141 | bool pushError(const Value& value, const std::string& message); 142 | 143 | /** \brief Add a semantic error message with extra context. 144 | * \param value JSON Value location associated with the error 145 | * \param message The error message. 146 | * \param extra Additional JSON Value location to contextualize the error 147 | * \return \c true if the error was successfully added, \c false if either 148 | * Value offset exceeds the document size. 149 | */ 150 | bool pushError(const Value& value, const std::string& message, const Value& extra); 151 | 152 | /** \brief Return whether there are any errors. 153 | * \return \c true if there are no errors to report \c false if 154 | * errors have occurred. 155 | */ 156 | bool good() const; 157 | 158 | private: 159 | enum TokenType { 160 | tokenEndOfStream = 0, 161 | tokenObjectBegin, 162 | tokenObjectEnd, 163 | tokenArrayBegin, 164 | tokenArrayEnd, 165 | tokenString, 166 | tokenNumber, 167 | tokenTrue, 168 | tokenFalse, 169 | tokenNull, 170 | tokenArraySeparator, 171 | tokenMemberSeparator, 172 | tokenComment, 173 | tokenError 174 | }; 175 | 176 | class Token { 177 | public: 178 | TokenType type_; 179 | Location start_; 180 | Location end_; 181 | }; 182 | 183 | class ErrorInfo { 184 | public: 185 | Token token_; 186 | std::string message_; 187 | Location extra_; 188 | }; 189 | 190 | typedef std::deque Errors; 191 | 192 | bool readToken(Token& token); 193 | void skipSpaces(); 194 | bool match(Location pattern, int patternLength); 195 | bool readComment(); 196 | bool readCStyleComment(); 197 | bool readCppStyleComment(); 198 | bool readString(); 199 | void readNumber(); 200 | bool readValue(); 201 | bool readObject(Token& token); 202 | bool readArray(Token& token); 203 | bool decodeNumber(Token& token); 204 | bool decodeNumber(Token& token, Value& decoded); 205 | bool decodeString(Token& token); 206 | bool decodeString(Token& token, std::string& decoded); 207 | bool decodeDouble(Token& token); 208 | bool decodeDouble(Token& token, Value& decoded); 209 | bool decodeUnicodeCodePoint(Token& token, 210 | Location& current, 211 | Location end, 212 | unsigned int& unicode); 213 | bool decodeUnicodeEscapeSequence(Token& token, 214 | Location& current, 215 | Location end, 216 | unsigned int& unicode); 217 | bool addError(const std::string& message, Token& token, Location extra = 0); 218 | bool recoverFromError(TokenType skipUntilToken); 219 | bool addErrorAndRecover(const std::string& message, 220 | Token& token, 221 | TokenType skipUntilToken); 222 | void skipUntilSpace(); 223 | Value& currentValue(); 224 | Char getNextChar(); 225 | void 226 | getLocationLineAndColumn(Location location, int& line, int& column) const; 227 | std::string getLocationLineAndColumn(Location location) const; 228 | void addComment(Location begin, Location end, CommentPlacement placement); 229 | void skipCommentTokens(Token& token); 230 | 231 | typedef std::stack Nodes; 232 | Nodes nodes_; 233 | Errors errors_; 234 | std::string document_; 235 | Location begin_; 236 | Location end_; 237 | Location current_; 238 | Location lastValueEnd_; 239 | Value* lastValue_; 240 | std::string commentsBefore_; 241 | Features features_; 242 | bool collectComments_; 243 | }; // Reader 244 | 245 | /** Interface for reading JSON from a char array. 246 | */ 247 | class JSON_API CharReader { 248 | public: 249 | virtual ~CharReader() {} 250 | /** \brief Read a Value from a JSON 251 | document. 252 | * The document must be a UTF-8 encoded string containing the document to read. 253 | * 254 | * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the 255 | document to read. 256 | * \param endDoc Pointer on the end of the UTF-8 encoded string of the 257 | document to read. 258 | * Must be >= beginDoc. 259 | * \param root [out] Contains the root value of the document if it was 260 | * successfully parsed. 261 | * \param errs [out] Formatted error messages (if not NULL) 262 | * a user friendly string that lists errors in the parsed 263 | * document. 264 | * \return \c true if the document was successfully parsed, \c false if an 265 | error occurred. 266 | */ 267 | virtual bool parse( 268 | char const* beginDoc, char const* endDoc, 269 | Value* root, std::string* errs) = 0; 270 | 271 | class Factory { 272 | public: 273 | virtual ~Factory() {} 274 | /** \brief Allocate a CharReader via operator new(). 275 | * \throw std::exception if something goes wrong (e.g. invalid settings) 276 | */ 277 | virtual CharReader* newCharReader() const = 0; 278 | }; // Factory 279 | }; // CharReader 280 | 281 | /** \brief Build a CharReader implementation. 282 | 283 | Usage: 284 | \code 285 | using namespace Json; 286 | CharReaderBuilder builder; 287 | builder["collectComments"] = false; 288 | Value value; 289 | std::string errs; 290 | bool ok = parseFromStream(builder, std::cin, &value, &errs); 291 | \endcode 292 | */ 293 | class JSON_API CharReaderBuilder : public CharReader::Factory { 294 | public: 295 | // Note: We use a Json::Value so that we can add data-members to this class 296 | // without a major version bump. 297 | /** Configuration of this builder. 298 | These are case-sensitive. 299 | Available settings (case-sensitive): 300 | - `"collectComments": false or true` 301 | - true to collect comment and allow writing them 302 | back during serialization, false to discard comments. 303 | This parameter is ignored if allowComments is false. 304 | - `"allowComments": false or true` 305 | - true if comments are allowed. 306 | - `"strictRoot": false or true` 307 | - true if root must be either an array or an object value 308 | - `"allowDroppedNullPlaceholders": false or true` 309 | - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) 310 | - `"allowNumericKeys": false or true` 311 | - true if numeric object keys are allowed. 312 | - `"allowSingleQuotes": false or true` 313 | - true if '' are allowed for strings (both keys and values) 314 | - `"stackLimit": integer` 315 | - Exceeding stackLimit (recursive depth of `readValue()`) will 316 | cause an exception. 317 | - This is a security issue (seg-faults caused by deeply nested JSON), 318 | so the default is low. 319 | - `"failIfExtra": false or true` 320 | - If true, `parse()` returns false when extra non-whitespace trails 321 | the JSON value in the input string. 322 | - `"rejectDupKeys": false or true` 323 | - If true, `parse()` returns false when a key is duplicated within an object. 324 | 325 | You can examine 'settings_` yourself 326 | to see the defaults. You can also write and read them just like any 327 | JSON Value. 328 | \sa setDefaults() 329 | */ 330 | Json::Value settings_; 331 | 332 | CharReaderBuilder(); 333 | virtual ~CharReaderBuilder(); 334 | 335 | virtual CharReader* newCharReader() const; 336 | 337 | /** \return true if 'settings' are legal and consistent; 338 | * otherwise, indicate bad settings via 'invalid'. 339 | */ 340 | bool validate(Json::Value* invalid) const; 341 | 342 | /** A simple way to update a specific setting. 343 | */ 344 | Value& operator[](std::string key); 345 | 346 | /** Called by ctor, but you can use this to reset settings_. 347 | * \pre 'settings' != NULL (but Json::null is fine) 348 | * \remark Defaults: 349 | * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults 350 | */ 351 | static void setDefaults(Json::Value* settings); 352 | /** Same as old Features::strictMode(). 353 | * \pre 'settings' != NULL (but Json::null is fine) 354 | * \remark Defaults: 355 | * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode 356 | */ 357 | static void strictMode(Json::Value* settings); 358 | }; 359 | 360 | /** Consume entire stream and use its begin/end. 361 | * Someday we might have a real StreamReader, but for now this 362 | * is convenient. 363 | */ 364 | bool JSON_API parseFromStream( 365 | CharReader::Factory const&, 366 | std::istream&, 367 | Value* root, std::string* errs); 368 | 369 | /** \brief Read from 'sin' into 'root'. 370 | 371 | Always keep comments from the input JSON. 372 | 373 | This can be used to read a file into a particular sub-object. 374 | For example: 375 | \code 376 | Json::Value root; 377 | cin >> root["dir"]["file"]; 378 | cout << root; 379 | \endcode 380 | Result: 381 | \verbatim 382 | { 383 | "dir": { 384 | "file": { 385 | // The input stream JSON would be nested here. 386 | } 387 | } 388 | } 389 | \endverbatim 390 | \throw std::exception on parse error. 391 | \see Json::operator<<() 392 | */ 393 | JSON_API std::istream& operator>>(std::istream&, Value&); 394 | 395 | } // namespace Json 396 | 397 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 398 | #pragma warning(pop) 399 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 400 | 401 | #endif // CPPTL_JSON_READER_H_INCLUDED 402 | -------------------------------------------------------------------------------- /src/source/avl-tree.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2005-2008, Simon Howard 4 | 5 | Permission to use, copy, modify, and/or distribute this software 6 | for any purpose with or without fee is hereby granted, provided 7 | that the above copyright notice and this permission notice appear 8 | in all copies. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 | AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 14 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 16 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 17 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | 19 | */ 20 | 21 | #include 22 | #include "avl-tree.h" 23 | #include "tinybuf_memory.h" 24 | 25 | /* malloc() / free() testing */ 26 | 27 | #ifdef ALLOC_TESTING 28 | #include "alloc-testing.h" 29 | #endif 30 | 31 | /* AVL Tree (balanced binary search tree) */ 32 | 33 | struct _AVLTreeNode { 34 | AVLTreeNode *children[2]; 35 | AVLTreeNode *parent; 36 | AVLTreeKey key; 37 | AVLTreeValue value; 38 | AVLTreeFreeKeyFunc key_free; 39 | AVLTreeFreeValueFunc value_free; 40 | int height; 41 | }; 42 | 43 | 44 | struct _AVLTree { 45 | AVLTreeNode *root_node; 46 | AVLTreeCompareFunc compare_func; 47 | unsigned int num_nodes; 48 | }; 49 | 50 | static inline void free_node_key_value(AVLTreeNode *node){ 51 | if (node->key_free && node->key){ 52 | node->key_free(node->key); 53 | node->key = NULL; 54 | node->key_free = NULL; 55 | } 56 | 57 | if (node->value_free && node->value){ 58 | node->value_free(node->value); 59 | node->value = NULL; 60 | node->value_free = NULL; 61 | } 62 | } 63 | 64 | static inline void free_node(AVLTreeNode *node){ 65 | if(!node){ 66 | return; 67 | } 68 | free_node_key_value(node); 69 | tinybuf_free(node); 70 | } 71 | 72 | 73 | AVLTree *avl_tree_new(AVLTreeCompareFunc compare_func) 74 | { 75 | AVLTree *new_tree; 76 | 77 | new_tree = (AVLTree *) tinybuf_malloc(sizeof(AVLTree)); 78 | 79 | if (new_tree == NULL) { 80 | return NULL; 81 | } 82 | 83 | new_tree->root_node = NULL; 84 | new_tree->compare_func = compare_func; 85 | new_tree->num_nodes = 0; 86 | 87 | return new_tree; 88 | } 89 | 90 | static void avl_tree_free_subtree(AVLTree *tree, AVLTreeNode *node) 91 | { 92 | if (node == NULL) { 93 | return; 94 | } 95 | 96 | avl_tree_free_subtree(tree, node->children[AVL_TREE_NODE_LEFT]); 97 | avl_tree_free_subtree(tree, node->children[AVL_TREE_NODE_RIGHT]); 98 | 99 | free_node(node); 100 | } 101 | 102 | void avl_tree_free(AVLTree *tree) 103 | { 104 | /* Destroy all nodes */ 105 | 106 | avl_tree_free_subtree(tree, tree->root_node); 107 | 108 | /* Free back the main tree data structure */ 109 | 110 | tinybuf_free(tree); 111 | } 112 | 113 | int avl_tree_subtree_height(AVLTreeNode *node) 114 | { 115 | if (node == NULL) { 116 | return 0; 117 | } else { 118 | return node->height; 119 | } 120 | } 121 | 122 | /* Update the "height" variable of a node, from the heights of its 123 | * children. This does not update the height variable of any parent 124 | * nodes. */ 125 | 126 | static inline void avl_tree_update_height(AVLTreeNode *node) 127 | { 128 | AVLTreeNode *left_subtree; 129 | AVLTreeNode *right_subtree; 130 | int left_height, right_height; 131 | 132 | left_subtree = node->children[AVL_TREE_NODE_LEFT]; 133 | right_subtree = node->children[AVL_TREE_NODE_RIGHT]; 134 | left_height = avl_tree_subtree_height(left_subtree); 135 | right_height = avl_tree_subtree_height(right_subtree); 136 | 137 | if (left_height > right_height) { 138 | node->height = left_height + 1; 139 | } else { 140 | node->height = right_height + 1; 141 | } 142 | } 143 | 144 | /* Find what side a node is relative to its parent */ 145 | 146 | static AVLTreeNodeSide inline avl_tree_node_parent_side(AVLTreeNode *node) 147 | { 148 | if (node->parent->children[AVL_TREE_NODE_LEFT] == node) { 149 | return AVL_TREE_NODE_LEFT; 150 | } else { 151 | return AVL_TREE_NODE_RIGHT; 152 | } 153 | } 154 | 155 | /* Replace node1 with node2 at its parent. */ 156 | 157 | static void inline avl_tree_node_replace(AVLTree *tree, AVLTreeNode *node1, 158 | AVLTreeNode *node2) 159 | { 160 | int side; 161 | 162 | /* Set the node's parent pointer. */ 163 | 164 | if (node2 != NULL) { 165 | node2->parent = node1->parent; 166 | } 167 | 168 | /* The root node? */ 169 | 170 | if (node1->parent == NULL) { 171 | tree->root_node = node2; 172 | } else { 173 | side = avl_tree_node_parent_side(node1); 174 | node1->parent->children[side] = node2; 175 | 176 | avl_tree_update_height(node1->parent); 177 | } 178 | } 179 | 180 | /* Rotate a section of the tree. 'node' is the node at the top 181 | * of the section to be rotated. 'direction' is the direction in 182 | * which to rotate the tree: left or right, as shown in the following 183 | * diagram: 184 | * 185 | * Left rotation: Right rotation: 186 | * 187 | * B D 188 | * / \ / \ 189 | * A D B E 190 | * / \ / \ 191 | * C E A C 192 | 193 | * is rotated to: is rotated to: 194 | * 195 | * D B 196 | * / \ / \ 197 | * B E A D 198 | * / \ / \ 199 | * A C C E 200 | */ 201 | 202 | static inline AVLTreeNode *avl_tree_rotate(AVLTree *tree, AVLTreeNode *node, 203 | AVLTreeNodeSide direction) 204 | { 205 | AVLTreeNode *new_root; 206 | 207 | /* The child of this node will take its place: 208 | for a left rotation, it is the right child, and vice versa. */ 209 | 210 | new_root = node->children[1-direction]; 211 | 212 | /* Make new_root the root, update parent pointers. */ 213 | 214 | avl_tree_node_replace(tree, node, new_root); 215 | 216 | /* Rearrange pointers */ 217 | 218 | node->children[1-direction] = new_root->children[direction]; 219 | new_root->children[direction] = node; 220 | 221 | /* Update parent references */ 222 | 223 | node->parent = new_root; 224 | 225 | if (node->children[1-direction] != NULL) { 226 | node->children[1-direction]->parent = node; 227 | } 228 | 229 | /* Update heights of the affected nodes */ 230 | 231 | avl_tree_update_height(new_root); 232 | avl_tree_update_height(node); 233 | 234 | return new_root; 235 | } 236 | 237 | 238 | /* Balance a particular tree node. 239 | * 240 | * Returns the root node of the new subtree which is replacing the 241 | * old one. */ 242 | 243 | static inline AVLTreeNode *avl_tree_node_balance(AVLTree *tree, AVLTreeNode *node) 244 | { 245 | AVLTreeNode *left_subtree; 246 | AVLTreeNode *right_subtree; 247 | AVLTreeNode *child; 248 | int diff; 249 | 250 | left_subtree = node->children[AVL_TREE_NODE_LEFT]; 251 | right_subtree = node->children[AVL_TREE_NODE_RIGHT]; 252 | 253 | /* Check the heights of the child trees. If there is an unbalance 254 | * (difference between left and right > 2), then rotate nodes 255 | * around to fix it */ 256 | 257 | diff = avl_tree_subtree_height(right_subtree) 258 | - avl_tree_subtree_height(left_subtree); 259 | 260 | if (diff >= 2) { 261 | 262 | /* Biased toward the right side too much. */ 263 | 264 | child = right_subtree; 265 | 266 | if (avl_tree_subtree_height(child->children[AVL_TREE_NODE_RIGHT]) 267 | < avl_tree_subtree_height(child->children[AVL_TREE_NODE_LEFT])) { 268 | 269 | /* If the right child is biased toward the left 270 | * side, it must be rotated right first (double 271 | * rotation) */ 272 | 273 | avl_tree_rotate(tree, right_subtree, 274 | AVL_TREE_NODE_RIGHT); 275 | } 276 | 277 | /* Perform a left rotation. After this, the right child will 278 | * take the place of this node. Update the node pointer. */ 279 | 280 | node = avl_tree_rotate(tree, node, AVL_TREE_NODE_LEFT); 281 | 282 | } else if (diff <= -2) { 283 | 284 | /* Biased toward the left side too much. */ 285 | 286 | child = node->children[AVL_TREE_NODE_LEFT]; 287 | 288 | if (avl_tree_subtree_height(child->children[AVL_TREE_NODE_LEFT]) 289 | < avl_tree_subtree_height(child->children[AVL_TREE_NODE_RIGHT])) { 290 | 291 | /* If the left child is biased toward the right 292 | * side, it must be rotated right left (double 293 | * rotation) */ 294 | 295 | avl_tree_rotate(tree, left_subtree, 296 | AVL_TREE_NODE_LEFT); 297 | } 298 | 299 | /* Perform a right rotation. After this, the left child will 300 | * take the place of this node. Update the node pointer. */ 301 | 302 | node = avl_tree_rotate(tree, node, AVL_TREE_NODE_RIGHT); 303 | } 304 | 305 | /* Update the height of this node */ 306 | 307 | avl_tree_update_height(node); 308 | 309 | return node; 310 | } 311 | 312 | /* Walk up the tree from the given node, performing any needed rotations */ 313 | 314 | static inline void avl_tree_balance_to_root(AVLTree *tree, AVLTreeNode *node) 315 | { 316 | AVLTreeNode *rover; 317 | 318 | rover = node; 319 | 320 | while (rover != NULL) { 321 | 322 | /* Balance this node if necessary */ 323 | 324 | rover = avl_tree_node_balance(tree, rover); 325 | 326 | /* Go to this node's parent */ 327 | 328 | rover = rover->parent; 329 | } 330 | } 331 | 332 | AVLTreeNode *avl_tree_insert(AVLTree *tree, AVLTreeKey key, AVLTreeValue value, 333 | AVLTreeFreeKeyFunc freeKey, 334 | AVLTreeFreeValueFunc freeValue) 335 | { 336 | AVLTreeNode **rover; 337 | AVLTreeNode *new_node; 338 | AVLTreeNode *previous_node; 339 | 340 | /* Walk down the tree until we reach a NULL pointer */ 341 | 342 | rover = &tree->root_node; 343 | previous_node = NULL; 344 | 345 | while (*rover != NULL) { 346 | previous_node = *rover; 347 | int ret = tree->compare_func(key, (*rover)->key); 348 | if (ret < 0) { 349 | rover = &((*rover)->children[AVL_TREE_NODE_LEFT]); 350 | } else if(ret > 0){ 351 | rover = &((*rover)->children[AVL_TREE_NODE_RIGHT]); 352 | } else { 353 | free_node_key_value(*rover); 354 | new_node = *rover; 355 | new_node->key = key; 356 | new_node->key_free = freeKey; 357 | new_node->value_free = freeValue; 358 | new_node->value = value; 359 | return new_node; 360 | } 361 | } 362 | 363 | /* Create a new node. Use the last node visited as the parent link. */ 364 | 365 | new_node = (AVLTreeNode *) tinybuf_malloc(sizeof(AVLTreeNode)); 366 | 367 | if (new_node == NULL) { 368 | return NULL; 369 | } 370 | 371 | new_node->children[AVL_TREE_NODE_LEFT] = NULL; 372 | new_node->children[AVL_TREE_NODE_RIGHT] = NULL; 373 | new_node->parent = previous_node; 374 | new_node->key = key; 375 | new_node->key_free = freeKey; 376 | new_node->value_free = freeValue; 377 | new_node->value = value; 378 | new_node->height = 1; 379 | 380 | /* Insert at the NULL pointer that was reached */ 381 | 382 | *rover = new_node; 383 | 384 | /* Rebalance the tree, starting from the previous node. */ 385 | 386 | avl_tree_balance_to_root(tree, previous_node); 387 | 388 | /* Keep track of the number of entries */ 389 | 390 | ++tree->num_nodes; 391 | 392 | return new_node; 393 | } 394 | 395 | /* Find the nearest node to the given node, to replace it. 396 | * The node returned is unlinked from the tree. 397 | * Returns NULL if the node has no children. */ 398 | 399 | static inline AVLTreeNode *avl_tree_node_get_replacement(AVLTree *tree, 400 | AVLTreeNode *node) 401 | { 402 | AVLTreeNode *left_subtree; 403 | AVLTreeNode *right_subtree; 404 | AVLTreeNode *result; 405 | AVLTreeNode *child; 406 | int left_height, right_height; 407 | int side; 408 | 409 | left_subtree = node->children[AVL_TREE_NODE_LEFT]; 410 | right_subtree = node->children[AVL_TREE_NODE_RIGHT]; 411 | 412 | /* No children? */ 413 | 414 | if (left_subtree == NULL && right_subtree == NULL) { 415 | return NULL; 416 | } 417 | 418 | /* Pick a node from whichever subtree is taller. This helps to 419 | * keep the tree balanced. */ 420 | 421 | left_height = avl_tree_subtree_height(left_subtree); 422 | right_height = avl_tree_subtree_height(right_subtree); 423 | 424 | if (left_height < right_height) { 425 | side = AVL_TREE_NODE_RIGHT; 426 | } else { 427 | side = AVL_TREE_NODE_LEFT; 428 | } 429 | 430 | /* Search down the tree, back towards the center. */ 431 | 432 | result = node->children[side]; 433 | 434 | while (result->children[1-side] != NULL) { 435 | result = result->children[1-side]; 436 | } 437 | 438 | /* Unlink the result node, and hook in its remaining child 439 | * (if it has one) to replace it. */ 440 | 441 | child = result->children[side]; 442 | avl_tree_node_replace(tree, result, child); 443 | 444 | /* Update the subtree height for the result node's old parent. */ 445 | 446 | avl_tree_update_height(result->parent); 447 | 448 | return result; 449 | } 450 | 451 | /* Remove a node from a tree */ 452 | 453 | void avl_tree_remove_node(AVLTree *tree, AVLTreeNode *node) 454 | { 455 | AVLTreeNode *swap_node; 456 | AVLTreeNode *balance_startpoint; 457 | int i; 458 | 459 | /* The node to be removed must be swapped with an "adjacent" 460 | * node, ie. one which has the closest key to this one. Find 461 | * a node to swap with. */ 462 | 463 | swap_node = avl_tree_node_get_replacement(tree, node); 464 | 465 | if (swap_node == NULL) { 466 | 467 | /* This is a leaf node and has no children, therefore 468 | * it can be immediately removed. */ 469 | 470 | /* Unlink this node from its parent. */ 471 | 472 | avl_tree_node_replace(tree, node, NULL); 473 | 474 | /* Start rebalancing from the parent of the original node */ 475 | 476 | balance_startpoint = node->parent; 477 | 478 | } else { 479 | /* We will start rebalancing from the old parent of the 480 | * swap node. Sometimes, the old parent is the node we 481 | * are removing, in which case we must start rebalancing 482 | * from the swap node. */ 483 | 484 | if (swap_node->parent == node) { 485 | balance_startpoint = swap_node; 486 | } else { 487 | balance_startpoint = swap_node->parent; 488 | } 489 | 490 | /* Copy references in the node into the swap node */ 491 | 492 | for (i=0; i<2; ++i) { 493 | swap_node->children[i] = node->children[i]; 494 | 495 | if (swap_node->children[i] != NULL) { 496 | swap_node->children[i]->parent = swap_node; 497 | } 498 | } 499 | 500 | swap_node->height = node->height; 501 | 502 | /* Link the parent's reference to this node */ 503 | 504 | avl_tree_node_replace(tree, node, swap_node); 505 | } 506 | 507 | /* Destroy the node */ 508 | 509 | free_node(node); 510 | 511 | /* Keep track of the number of nodes */ 512 | 513 | --tree->num_nodes; 514 | 515 | /* Rebalance the tree */ 516 | 517 | avl_tree_balance_to_root(tree, balance_startpoint); 518 | } 519 | 520 | /* Remove a node by key */ 521 | 522 | int avl_tree_remove(AVLTree *tree, AVLTreeKey key) 523 | { 524 | AVLTreeNode *node; 525 | 526 | /* Find the node to remove */ 527 | 528 | node = avl_tree_lookup_node(tree, key); 529 | 530 | if (node == NULL) { 531 | /* Not found in tree */ 532 | 533 | return 0; 534 | } 535 | 536 | /* Remove the node */ 537 | 538 | avl_tree_remove_node(tree, node); 539 | 540 | return 1; 541 | } 542 | 543 | AVLTreeNode *avl_tree_lookup_node(AVLTree *tree, AVLTreeKey key) 544 | { 545 | AVLTreeNode *node; 546 | int diff; 547 | 548 | /* Search down the tree and attempt to find the node which 549 | * has the specified key */ 550 | 551 | node = tree->root_node; 552 | 553 | while (node != NULL) { 554 | 555 | diff = tree->compare_func(key, node->key); 556 | 557 | if (diff == 0) { 558 | 559 | /* Keys are equal: return this node */ 560 | 561 | return node; 562 | 563 | } else if (diff < 0) { 564 | node = node->children[AVL_TREE_NODE_LEFT]; 565 | } else { 566 | node = node->children[AVL_TREE_NODE_RIGHT]; 567 | } 568 | } 569 | 570 | /* Not found */ 571 | 572 | return NULL; 573 | } 574 | 575 | AVLTreeValue avl_tree_lookup(AVLTree *tree, AVLTreeKey key) 576 | { 577 | AVLTreeNode *node; 578 | 579 | /* Find the node */ 580 | 581 | node = avl_tree_lookup_node(tree, key); 582 | 583 | if (node == NULL) { 584 | return AVL_TREE_NULL; 585 | } else { 586 | return node->value; 587 | } 588 | } 589 | 590 | AVLTreeNode *avl_tree_root_node(AVLTree *tree) 591 | { 592 | return tree->root_node; 593 | } 594 | 595 | AVLTreeKey avl_tree_node_key(AVLTreeNode *node) 596 | { 597 | return node->key; 598 | } 599 | 600 | AVLTreeValue avl_tree_node_value(AVLTreeNode *node) 601 | { 602 | return node->value; 603 | } 604 | 605 | AVLTreeNode *avl_tree_node_child(AVLTreeNode *node, AVLTreeNodeSide side) 606 | { 607 | if (side == AVL_TREE_NODE_LEFT || side == AVL_TREE_NODE_RIGHT) { 608 | return node->children[side]; 609 | } else { 610 | return NULL; 611 | } 612 | } 613 | 614 | AVLTreeNode *avl_tree_node_parent(AVLTreeNode *node) 615 | { 616 | return node->parent; 617 | } 618 | 619 | unsigned int avl_tree_num_entries(AVLTree *tree) 620 | { 621 | if(!tree){ 622 | return 0; 623 | } 624 | return tree->num_nodes; 625 | } 626 | 627 | static void avl_tree_to_array_add_subtree(AVLTreeNode *subtree, 628 | AVLTreeValue *array, 629 | int *index) 630 | { 631 | if (subtree == NULL) { 632 | return; 633 | } 634 | 635 | /* Add left subtree first */ 636 | 637 | avl_tree_to_array_add_subtree(subtree->children[AVL_TREE_NODE_LEFT], 638 | array, index); 639 | 640 | /* Add this node */ 641 | 642 | array[*index] = subtree->key; 643 | ++*index; 644 | 645 | /* Finally add right subtree */ 646 | 647 | avl_tree_to_array_add_subtree(subtree->children[AVL_TREE_NODE_RIGHT], 648 | array, index); 649 | } 650 | 651 | AVLTreeKey *avl_tree_to_array(AVLTree *tree) 652 | { 653 | AVLTreeValue *array; 654 | int index; 655 | 656 | /* Allocate the array */ 657 | 658 | array = tinybuf_malloc(sizeof(AVLTreeValue) * tree->num_nodes); 659 | 660 | if (array == NULL) { 661 | return NULL; 662 | } 663 | 664 | index = 0; 665 | 666 | /* Add all keys */ 667 | 668 | avl_tree_to_array_add_subtree(tree->root_node, array, &index); 669 | 670 | return array; 671 | } 672 | 673 | static void avl_tree_to_array_add_subtree_node(AVLTreeNode *subtree, 674 | AVLTreeNode **array, 675 | int *index) 676 | { 677 | if (subtree == NULL) { 678 | return; 679 | } 680 | 681 | /* Add left subtree first */ 682 | 683 | avl_tree_to_array_add_subtree_node(subtree->children[AVL_TREE_NODE_LEFT],array, index); 684 | 685 | /* Add this node */ 686 | 687 | array[*index] = subtree; 688 | ++*index; 689 | 690 | /* Finally add right subtree */ 691 | 692 | avl_tree_to_array_add_subtree_node(subtree->children[AVL_TREE_NODE_RIGHT],array, index); 693 | } 694 | 695 | 696 | AVLTreeNode **avl_tree_to_array_node(AVLTree *tree){ 697 | AVLTreeNode **array; 698 | int index; 699 | 700 | /* Allocate the array */ 701 | 702 | array = tinybuf_malloc(sizeof(AVLTreeNode*) * tree->num_nodes); 703 | 704 | if (array == NULL) { 705 | return NULL; 706 | } 707 | 708 | index = 0; 709 | 710 | /* Add all keys */ 711 | 712 | avl_tree_to_array_add_subtree_node(tree->root_node, array, &index); 713 | 714 | return array; 715 | } 716 | 717 | 718 | static AVLTreeNode *avl_tree_get_node_by_index_l(AVLTreeNode *node, 719 | int *pos, 720 | int index){ 721 | if (node == NULL) { 722 | return NULL; 723 | } 724 | 725 | AVLTreeNode *ret; 726 | ret = avl_tree_get_node_by_index_l(node->children[AVL_TREE_NODE_LEFT],pos,index); 727 | if(ret){ 728 | return ret; 729 | } 730 | 731 | if((*pos)++ == index){ 732 | return node; 733 | } 734 | 735 | return avl_tree_get_node_by_index_l(node->children[AVL_TREE_NODE_RIGHT],pos,index); 736 | 737 | } 738 | 739 | AVLTreeNode *avl_tree_get_node_by_index(AVLTree *tree , int index){ 740 | int pos = 0; 741 | return avl_tree_get_node_by_index_l(tree->root_node, &pos, index); 742 | } 743 | 744 | 745 | int avl_tree_for_each_node_l(AVLTreeNode *node,void *user_data, on_avl_tree_node cb){ 746 | if(!node){ 747 | return 0; 748 | } 749 | 750 | if(avl_tree_for_each_node_l(avl_tree_node_child(node,AVL_TREE_NODE_LEFT),user_data,cb)){ 751 | return 1; 752 | } 753 | 754 | if(cb(user_data,node)){ 755 | return 1; 756 | } 757 | 758 | return avl_tree_for_each_node_l(avl_tree_node_child(node,AVL_TREE_NODE_RIGHT),user_data,cb); 759 | } 760 | 761 | int avl_tree_for_each_node(AVLTree *tree,void *user_data, on_avl_tree_node cb){ 762 | if(!tree || !cb){ 763 | return 0; 764 | } 765 | return avl_tree_for_each_node_l(tree->root_node,user_data,cb); 766 | } -------------------------------------------------------------------------------- /src/source/tinybuf.c: -------------------------------------------------------------------------------- 1 | #include "tinybuf_private.h" 2 | #ifdef _WIN32 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | //1 支持变长数字格式并支持配置开启 2 支持KVPair通用格式 9 | //3 支持自描述结构和向前兼容支持 10 | typedef enum { 11 | serialize_null = 0, 12 | serialize_positive_int = 1, 13 | serialize_negtive_int = 2, 14 | serialize_bool_true = 3, 15 | serialize_bool_false = 4, 16 | serialize_double = 5, 17 | serialize_string = 6, 18 | serialize_map = 7, 19 | serialize_array = 8, 20 | } serialize_type; 21 | 22 | /** 23 | * 序列化整型 24 | * @param in 整型 25 | * @param out 序列化字节存放地址,最少预留10个字节 26 | * @return 序列化字节长度 27 | */ 28 | static inline int int_serialize(uint64_t in, uint8_t *out){ 29 | int index = 0; 30 | int i; 31 | for(i = 0; i <= (8 * sizeof(in)) / 7 ; ++i, ++index){ 32 | //取最低位7bit 33 | out[index] = in & 0x7F; 34 | //右移7位 35 | in >>= 7; 36 | if(!in){ 37 | //剩余字节为0,最高位bit为0,停止序列化 38 | break; 39 | } 40 | //后面还有字节,那么最高位bit为1 41 | out[index] |= 0x80; 42 | } 43 | //返回序列化后总字节数 44 | return ++index; 45 | } 46 | 47 | /** 48 | * 反序列化整型 49 | * @param in 输入字节流 50 | * @param in_size 输入字节数 51 | * @param out 序列化后的整型 52 | * @return 代表反序列化消耗的字节数 53 | */ 54 | static inline int int_deserialize(const uint8_t *in, int in_size, uint64_t *out){ 55 | if(in_size < 1){ 56 | return 0; 57 | } 58 | *out = 0; 59 | int index = 0; 60 | while (1){ 61 | uint8_t byte = in[index]; 62 | (*out) |= (byte & 0x7F) << ((index++) * 7); 63 | if((byte & 0x80) == 0){ 64 | //最高位为0,所以没有更多后续字节 65 | break; 66 | } 67 | //后续还有字节 68 | if(index >= in_size){ 69 | //字节不够,反序列失败 70 | return 0; 71 | } 72 | if(index * 7 > 56 ){ 73 | //7bit 最多左移动56位,最大支持64位有符号整形 74 | return -1; 75 | } 76 | } 77 | //序列号成功 78 | return index; 79 | } 80 | 81 | tinybuf_value *tinybuf_value_alloc(void){ 82 | tinybuf_value *ret = tinybuf_malloc(sizeof(tinybuf_value)); 83 | assert(ret); 84 | //置0 85 | memset(ret,0, sizeof(tinybuf_value)); 86 | ret->_type = tinybuf_null; 87 | return ret; 88 | } 89 | 90 | /** 91 | * 创建对象 92 | * @return 返回对象 93 | */ 94 | tinybuf_value *tinybuf_value_alloc_with_type(tinybuf_type type){ 95 | tinybuf_value *value = tinybuf_value_alloc(); 96 | value->_type = type; 97 | return value; 98 | } 99 | 100 | int tinybuf_value_free(tinybuf_value *value){ 101 | assert(value); 102 | //清空对象 103 | tinybuf_value_clear(value); 104 | //释放对象指针 105 | tinybuf_free(value); 106 | return 0; 107 | } 108 | 109 | int tinybuf_value_clear(tinybuf_value *value){ 110 | assert(value); 111 | switch (value->_type){ 112 | case tinybuf_string:{ 113 | if (value->_data._string) { 114 | //清空字符串 115 | buffer_free(value->_data._string); 116 | value->_data._string = NULL; 117 | } 118 | } 119 | break; 120 | 121 | case tinybuf_map: 122 | case tinybuf_array:{ 123 | if (value->_data._map_array) { 124 | //清空map或array 125 | avl_tree_free(value->_data._map_array); 126 | value->_data._map_array = NULL; 127 | } 128 | } 129 | break; 130 | 131 | default: 132 | break; 133 | } 134 | 135 | if(value->_type != tinybuf_null){ 136 | //清空所有 137 | memset(value,0, sizeof(tinybuf_value)); 138 | value->_type = tinybuf_null; 139 | } 140 | return 0; 141 | } 142 | 143 | int tinybuf_value_init_bool(tinybuf_value *value,int flag){ 144 | assert(value); 145 | tinybuf_value_clear(value); 146 | value->_type = tinybuf_bool; 147 | value->_data._bool = (flag != 0); 148 | return 0; 149 | } 150 | 151 | int tinybuf_value_init_int(tinybuf_value *value,int64_t int_val){ 152 | assert(value); 153 | tinybuf_value_clear(value); 154 | value->_type = tinybuf_int; 155 | value->_data._int = int_val; 156 | return 0; 157 | } 158 | 159 | int tinybuf_value_init_double(tinybuf_value *value, double db_val){ 160 | assert(value); 161 | tinybuf_value_clear(value); 162 | value->_type = tinybuf_double; 163 | value->_data._double = db_val; 164 | return 0; 165 | } 166 | 167 | int tinybuf_value_init_string2(tinybuf_value *value, buffer *buf){ 168 | assert(value); 169 | assert(buf); 170 | if(value->_type != tinybuf_string){ 171 | tinybuf_value_clear(value); 172 | } 173 | 174 | if(value->_data._string){ 175 | buffer_free( value->_data._string); 176 | } 177 | value->_type = tinybuf_string; 178 | value->_data._string = buf; 179 | return 0; 180 | } 181 | 182 | static inline int tinybuf_value_init_string_l(tinybuf_value *value, const char *str, int len, int use_strlen){ 183 | assert(value); 184 | assert(str); 185 | if(value->_type != tinybuf_string){ 186 | tinybuf_value_clear(value); 187 | } 188 | 189 | if(!value->_data._string){ 190 | value->_data._string = buffer_alloc(); 191 | assert(value->_data._string); 192 | } 193 | 194 | value->_type = tinybuf_string; 195 | 196 | if(len <= 0 && use_strlen){ 197 | len = strlen(str); 198 | } 199 | 200 | if(len > 0){ 201 | buffer_assign(value->_data._string,str,len); 202 | }else{ 203 | buffer_set_length(value->_data._string,0); 204 | } 205 | return 0; 206 | } 207 | 208 | int tinybuf_value_init_string(tinybuf_value *value,const char *str,int len){ 209 | return tinybuf_value_init_string_l(value, str, len, 1); 210 | } 211 | 212 | static int mapKeyCompare(AVLTreeKey key1, AVLTreeKey key2){ 213 | buffer *buf_key1 = (buffer*)key1; 214 | buffer *buf_key2 = (buffer*)key2; 215 | int buf_len1 = buffer_get_length_inline(buf_key1); 216 | int buf_len2 = buffer_get_length_inline(buf_key2); 217 | int min_len = buf_len1 < buf_len2 ? buf_len1 : buf_len2; 218 | int ret = memcmp(buffer_get_data_inline(buf_key1),buffer_get_data_inline(buf_key2),min_len); 219 | if(ret != 0){ 220 | return ret; 221 | } 222 | //两者前面字节部分相同,那么再比较字符串长度 223 | return buf_len1 - buf_len2; 224 | } 225 | 226 | static void mapFreeValueFunc(AVLTreeValue value){ 227 | tinybuf_value_free(value); 228 | } 229 | 230 | static void buffer_key_free(AVLTreeKey key){ 231 | buffer_free((buffer *)key); 232 | } 233 | 234 | int tinybuf_value_map_set2(tinybuf_value *parent,buffer *key,tinybuf_value *value){ 235 | assert(parent); 236 | assert(key); 237 | assert(value); 238 | if(parent->_type != tinybuf_map){ 239 | tinybuf_value_clear(parent); 240 | parent->_type = tinybuf_map; 241 | } 242 | 243 | if(!parent->_data._map_array){ 244 | parent->_data._map_array = avl_tree_new(mapKeyCompare); 245 | } 246 | avl_tree_insert(parent->_data._map_array,key,value,buffer_key_free,mapFreeValueFunc); 247 | return 0; 248 | } 249 | 250 | int tinybuf_value_map_set(tinybuf_value *parent,const char *key,tinybuf_value *value){ 251 | assert(key); 252 | buffer *key_buf = buffer_alloc(); 253 | assert(key_buf); 254 | buffer_assign(key_buf,key,0); 255 | return tinybuf_value_map_set2(parent,key_buf,value); 256 | } 257 | 258 | static int arrayKeyCompare(AVLTreeKey key1, AVLTreeKey key2){ 259 | return (int)(((intptr_t)key1) - ((intptr_t)key2)); 260 | } 261 | 262 | int tinybuf_value_array_append(tinybuf_value *parent,tinybuf_value *value){ 263 | assert(parent); 264 | assert(value); 265 | if(parent->_type != tinybuf_array){ 266 | tinybuf_value_clear(parent); 267 | parent->_type = tinybuf_array; 268 | } 269 | 270 | if(!parent->_data._map_array){ 271 | parent->_data._map_array = avl_tree_new(arrayKeyCompare); 272 | } 273 | int key = avl_tree_num_entries(parent->_data._map_array); 274 | avl_tree_insert(parent->_data._map_array, 275 | (AVLTreeKey)key, 276 | value, 277 | NULL, 278 | mapFreeValueFunc); 279 | return 0; 280 | } 281 | 282 | static inline int dump_int(uint64_t len,buffer *out){ 283 | int buf_len = buffer_get_length_inline(out); 284 | if(buffer_get_capacity_inline(out) - buf_len < 16){ 285 | //容量不够,追加容量 286 | buffer_add_capacity(out,16); 287 | } 288 | //直接序列化进去 289 | int add = int_serialize(len,(uint8_t*)buffer_get_data_inline(out) + buf_len); 290 | buffer_set_length(out,buf_len + add); 291 | return add; 292 | } 293 | 294 | static inline int dump_double(double db,buffer *out){ 295 | uint64_t encoded = 0; 296 | memcpy(&encoded, &db, 8); 297 | uint32_t val = htonl(encoded >> 32 ); 298 | buffer_append(out,(char *) &val, 4); 299 | val = htonl(encoded & 0xFFFFFFFF); 300 | buffer_append(out,(char *) &val, 4); 301 | return 8; 302 | } 303 | 304 | static inline uint32_t load_be32(const void *p){ 305 | uint32_t val; 306 | memcpy(&val, p, sizeof val); 307 | return ntohl(val); 308 | } 309 | 310 | static inline double read_double(uint8_t *ptr){ 311 | uint64_t val = ((uint64_t) load_be32(ptr) << 32) | load_be32(ptr + 4); 312 | double db = 0; 313 | memcpy(&db, &val, 8); 314 | return db; 315 | } 316 | 317 | 318 | static inline int dump_string(int len,const char *str,buffer *out){ 319 | int ret = dump_int(len,out); 320 | buffer_append(out,str,len); 321 | return ret + len; 322 | } 323 | 324 | static int avl_tree_for_each_node_dump_map(void *user_data,AVLTreeNode *node){ 325 | buffer *out = (buffer*)user_data; 326 | buffer *key = (buffer*)avl_tree_node_key(node); 327 | tinybuf_value *val = (tinybuf_value *)avl_tree_node_value(node); 328 | //写key 329 | dump_string(buffer_get_length_inline(key),buffer_get_data_inline(key),out); 330 | //写value 331 | tinybuf_value_serialize(val, out); 332 | //继续遍历 333 | return 0; 334 | } 335 | 336 | 337 | static int avl_tree_for_each_node_dump_array(void *user_data,AVLTreeNode *node){ 338 | buffer *out = (buffer*)user_data; 339 | //写value 340 | tinybuf_value_serialize(avl_tree_node_value(node), out); 341 | return 0; 342 | } 343 | 344 | int tinybuf_value_serialize(const tinybuf_value *value, buffer *out){ 345 | assert(value); 346 | assert(out); 347 | switch (value->_type){ 348 | case tinybuf_null:{ 349 | char type = serialize_null; 350 | //null类型 351 | buffer_append(out,&type,1); 352 | } 353 | break; 354 | 355 | case tinybuf_int:{ 356 | char type = value->_data._int > 0 ? serialize_positive_int : serialize_negtive_int; 357 | //正整数或负整数类型 358 | buffer_append(out,&type,1); 359 | //后面是int序列化字节 360 | dump_int(value->_data._int > 0 ? value->_data._int : -value->_data._int,out); 361 | } 362 | break; 363 | 364 | case tinybuf_bool:{ 365 | char type = value->_data._bool ? serialize_bool_true : serialize_bool_false; 366 | //bool类型 367 | buffer_append(out,&type,1); 368 | } 369 | break; 370 | 371 | case tinybuf_double:{ 372 | char type = serialize_double; 373 | //double类型 374 | buffer_append(out,&type,1); 375 | //double值序列化 376 | dump_double(value->_data._double,out); 377 | } 378 | break; 379 | 380 | case tinybuf_string:{ 381 | char type = serialize_string; 382 | //string或bytes类型 383 | buffer_append(out,&type,1); 384 | int len = buffer_get_length_inline(value->_data._string); 385 | if(len){ 386 | dump_string(len,buffer_get_data_inline(value->_data._string),out); 387 | }else{ 388 | dump_int(0,out); 389 | } 390 | } 391 | break; 392 | 393 | case tinybuf_map:{ 394 | char type = serialize_map; 395 | //map类型 396 | buffer_append(out,&type,1); 397 | int map_size = avl_tree_num_entries(value->_data._map_array); 398 | //map size 399 | dump_int(map_size,out); 400 | avl_tree_for_each_node(value->_data._map_array,out,avl_tree_for_each_node_dump_map); 401 | } 402 | break; 403 | 404 | 405 | case tinybuf_array:{ 406 | char type = serialize_array; 407 | //array类型 408 | buffer_append(out,&type,1); 409 | int array_size = avl_tree_num_entries(value->_data._map_array); 410 | //array size 411 | dump_int(array_size,out); 412 | //遍历node并序列化 413 | avl_tree_for_each_node(value->_data._map_array,out,avl_tree_for_each_node_dump_array); 414 | } 415 | break; 416 | 417 | default: 418 | //不可达 419 | assert(0); 420 | break; 421 | } 422 | 423 | return 0; 424 | } 425 | int tinybuf_value_deserialize(const char *ptr, int size, tinybuf_value *out){ 426 | assert(out); 427 | assert(ptr); 428 | assert(out->_type == tinybuf_null); 429 | if(size < 1){ 430 | //数据不够 431 | return 0; 432 | } 433 | 434 | serialize_type type = ptr[0]; 435 | //剩余字节数 436 | --size; 437 | //指针偏移量 438 | ++ptr; 439 | //消耗的字节数 440 | switch (type){ 441 | //null类型 442 | case serialize_null:{ 443 | tinybuf_value_clear(out); 444 | //消费了一个字节 445 | return 1; 446 | } 447 | 448 | //int类型 449 | case serialize_negtive_int: 450 | case serialize_positive_int:{ 451 | uint64_t int_val; 452 | int len = int_deserialize((uint8_t*)ptr,size,&int_val); 453 | if(len <= 0){ 454 | //字节不够,反序列化失败 455 | return len; 456 | } 457 | 458 | if(type == serialize_negtive_int){ 459 | //负整数,翻转之 460 | int_val = -int_val; 461 | } 462 | tinybuf_value_init_int(out,int_val); 463 | return 1 + len; 464 | } 465 | 466 | //bool类型 467 | case serialize_bool_false: 468 | case serialize_bool_true:{ 469 | tinybuf_value_init_bool(out,type == serialize_bool_true); 470 | //消费了一个字节 471 | return 1; 472 | } 473 | 474 | case serialize_double:{ 475 | if(size < 8){ 476 | //数据不够 477 | return 0; 478 | } 479 | tinybuf_value_init_double(out,read_double((uint8_t*)ptr)); 480 | return 9; 481 | } 482 | 483 | case serialize_string:{ 484 | //字节长度 485 | uint64_t bytes_len; 486 | int len = int_deserialize((uint8_t*)ptr,size,&bytes_len); 487 | if(len <= 0){ 488 | //字节不够,反序列化失败 489 | return len; 490 | } 491 | 492 | //跳过字节长度 493 | ptr += len; 494 | size -= len; 495 | 496 | if(size < bytes_len){ 497 | //剩余字节不够 498 | return 0; 499 | } 500 | 501 | //赋值为string 502 | tinybuf_value_init_string_l(out, ptr, bytes_len, 0); 503 | 504 | //消耗总字节数 505 | return 1 + len + bytes_len; 506 | } 507 | 508 | case serialize_map:{ 509 | int consumed = 0; 510 | uint64_t map_size; 511 | //获取map_size 512 | int len = int_deserialize((uint8_t*)ptr,size,&map_size); 513 | if(len <= 0){ 514 | //字节不够,反序列化失败 515 | return len; 516 | } 517 | 518 | //跳过map size字段 519 | ptr += len; 520 | size -= len; 521 | //消耗的字节总数 522 | consumed = 1 + len; 523 | 524 | out->_type = tinybuf_map; 525 | int i; 526 | for(i = 0; i < map_size ; ++i){ 527 | uint64_t key_len; 528 | //获取key string长度 529 | len = int_deserialize((uint8_t*)ptr,size,&key_len); 530 | if(len <= 0){ 531 | //字节不够,反序列化失败 532 | //清空掉未解析完毕的map 533 | tinybuf_value_clear(out); 534 | return len; 535 | } 536 | 537 | //跳过key string长度部分 538 | ptr += len; 539 | size -= len; 540 | consumed += len; 541 | 542 | if(size < key_len){ 543 | //剩余字节不够 544 | //清空掉未解析完毕的map 545 | tinybuf_value_clear(out); 546 | return 0; 547 | } 548 | 549 | char *key_ptr = (char *)ptr; 550 | 551 | //跳过string内容部分 552 | ptr += key_len; 553 | size -= key_len; 554 | consumed += key_len; 555 | 556 | //解析value部分 557 | tinybuf_value *value = tinybuf_value_alloc(); 558 | int value_len = tinybuf_value_deserialize(ptr,size,value); 559 | if(value_len <= 0){ 560 | //数据不够解析value部分 561 | tinybuf_value_free(value); 562 | //清空掉未解析完毕的map 563 | tinybuf_value_clear(out); 564 | return value_len; 565 | } 566 | 567 | { 568 | //解析出key,value,保存到map 569 | buffer *key = buffer_alloc(); 570 | buffer_assign(key,key_ptr,key_len); 571 | tinybuf_value_map_set2(out,key,value); 572 | } 573 | 574 | //重新计算偏移量 575 | ptr += value_len; 576 | size -= value_len; 577 | consumed += value_len; 578 | } 579 | //消耗的总字节数 580 | return consumed; 581 | } 582 | 583 | case serialize_array:{ 584 | int consumed = 0; 585 | uint64_t array_size; 586 | //获取array_size 587 | int len = int_deserialize((uint8_t*)ptr,size,&array_size); 588 | if(len <= 0){ 589 | //字节不够,反序列化失败 590 | return len; 591 | } 592 | 593 | //跳过array_size字段 594 | ptr += len; 595 | size -= len; 596 | //消耗的字节总数 597 | consumed = 1 + len; 598 | 599 | out->_type = tinybuf_array; 600 | 601 | int i; 602 | for(i = 0; i < array_size ; ++i){ 603 | //解析value部分 604 | tinybuf_value *value = tinybuf_value_alloc(); 605 | int value_len = tinybuf_value_deserialize(ptr,size,value); 606 | if(value_len <= 0){ 607 | //数据不够解析value部分 608 | tinybuf_value_free(value); 609 | //清空掉未解析完毕的array 610 | tinybuf_value_clear(out); 611 | return value_len; 612 | } 613 | //解析出value,保存到array 614 | tinybuf_value_array_append(out,value); 615 | //重新计算偏移量 616 | ptr += value_len; 617 | size -= value_len; 618 | consumed += value_len; 619 | } 620 | //消耗的总字节数 621 | return consumed; 622 | } 623 | default: 624 | //解析失败 625 | return -1; 626 | } 627 | } 628 | 629 | static int avl_tree_for_each_node_is_same(void *user_data,AVLTreeNode *node){ 630 | AVLTree *tree2 = (AVLTree*)user_data; 631 | AVLTreeKey key = avl_tree_node_key(node); 632 | tinybuf_value *child1 = (tinybuf_value *)avl_tree_node_value(node); 633 | tinybuf_value *child2 = avl_tree_lookup(tree2,key); 634 | if(!child2){ 635 | //不存在相应的key 636 | return 1; 637 | } 638 | if(!tinybuf_value_is_same(child1,child2)){ 639 | //相同key下,value不一致 640 | return 1; 641 | } 642 | 643 | //继续遍历 644 | return 0; 645 | } 646 | 647 | int tinybuf_value_is_same(const tinybuf_value *value1,const tinybuf_value *value2){ 648 | assert(value1); 649 | assert(value2); 650 | if(value1 == value2){ 651 | //是同一个对象 652 | return 1; 653 | } 654 | if(value1->_type != value2->_type){ 655 | //对象类型不同 656 | return 0; 657 | } 658 | 659 | switch (value1->_type) { 660 | case tinybuf_null: 661 | return 1; 662 | case tinybuf_int: 663 | return value1->_data._int == value2->_data._int; 664 | case tinybuf_bool: 665 | return value1->_data._bool == value2->_data._bool; 666 | case tinybuf_double: { 667 | return value1->_data._double == value2->_data._double; 668 | } 669 | case tinybuf_string:{ 670 | int len1 = buffer_get_length_inline(value1->_data._string); 671 | int len2 = buffer_get_length_inline(value2->_data._string); 672 | if(len1 != len2){ 673 | //长度不一样 674 | return 0; 675 | } 676 | if(!len1){ 677 | //都是空 678 | return 1; 679 | } 680 | return buffer_is_same(value1->_data._string,value2->_data._string); 681 | } 682 | 683 | case tinybuf_array: 684 | case tinybuf_map:{ 685 | int map_size1 = avl_tree_num_entries(value1->_data._map_array); 686 | int map_size2 = avl_tree_num_entries(value2->_data._map_array); 687 | if(map_size1 != map_size2){ 688 | //元素个数不一致 689 | return 0; 690 | } 691 | if(!map_size1){ 692 | //都是空 693 | return 1; 694 | } 695 | return avl_tree_for_each_node(value1->_data._map_array,value2->_data._map_array,avl_tree_for_each_node_is_same) == 0; 696 | } 697 | 698 | 699 | default: 700 | assert(0); 701 | return 0; 702 | } 703 | } 704 | 705 | static int avl_tree_for_each_node_clone_map(void *user_data,AVLTreeNode *node){ 706 | tinybuf_value *ret = (tinybuf_value*)user_data; 707 | buffer *key = (buffer*)avl_tree_node_key(node); 708 | tinybuf_value *val = (tinybuf_value *)avl_tree_node_value(node); 709 | 710 | buffer *key_clone = buffer_alloc(); 711 | buffer_append_buffer(key_clone, key); 712 | tinybuf_value_map_set2(ret, key_clone, tinybuf_value_clone(val)); 713 | 714 | //继续遍历 715 | return 0; 716 | } 717 | 718 | static int avl_tree_for_each_node_clone_array(void *user_data,AVLTreeNode *node){ 719 | tinybuf_value_array_append((tinybuf_value *)user_data,tinybuf_value_clone(avl_tree_node_value(node))); 720 | //继续遍历 721 | return 0; 722 | } 723 | 724 | 725 | tinybuf_value *tinybuf_value_clone(const tinybuf_value *value){ 726 | tinybuf_value *ret = tinybuf_value_alloc_with_type(value->_type); 727 | switch (value->_type) { 728 | case tinybuf_null: 729 | case tinybuf_int: 730 | case tinybuf_bool: 731 | case tinybuf_double: { 732 | memcpy(ret, value, sizeof(tinybuf_value)); 733 | return ret; 734 | } 735 | case tinybuf_string: 736 | if (buffer_get_length_inline(value->_data._string)) { 737 | ret->_data._string = buffer_alloc(); 738 | assert(ret->_data._string); 739 | buffer_append_buffer(ret->_data._string, value->_data._string); 740 | } 741 | return ret; 742 | 743 | case tinybuf_map:{ 744 | avl_tree_for_each_node(value->_data._map_array,ret,avl_tree_for_each_node_clone_map); 745 | return ret; 746 | } 747 | 748 | case tinybuf_array:{ 749 | avl_tree_for_each_node(value->_data._map_array,ret,avl_tree_for_each_node_clone_array); 750 | return ret; 751 | } 752 | default: 753 | assert(0); 754 | return ret; 755 | } 756 | } 757 | 758 | /////////////////////////////读接口////////////////////////////////// 759 | 760 | 761 | tinybuf_type tinybuf_value_get_type(const tinybuf_value *value){ 762 | if (!value){ 763 | return tinybuf_null; 764 | } 765 | return value->_type; 766 | } 767 | 768 | int64_t tinybuf_value_get_int(const tinybuf_value *value){ 769 | if (!value || value->_type != tinybuf_int){ 770 | return 0; 771 | } 772 | return value->_data._int; 773 | } 774 | 775 | double tinybuf_value_get_double(const tinybuf_value *value){ 776 | if (!value || value->_type != tinybuf_double){ 777 | return 0; 778 | } 779 | return value->_data._double; 780 | } 781 | 782 | int tinybuf_value_get_bool(const tinybuf_value *value){ 783 | if (!value || value->_type != tinybuf_bool){ 784 | return 0; 785 | } 786 | return value->_data._bool; 787 | } 788 | 789 | buffer* tinybuf_value_get_string(const tinybuf_value *value){ 790 | if (!value || value->_type != tinybuf_string){ 791 | return 0; 792 | } 793 | return value->_data._string; 794 | } 795 | 796 | int tinybuf_value_get_child_size(const tinybuf_value *value){ 797 | if (!value || (value->_type != tinybuf_map && value->_type != tinybuf_array)){ 798 | return 0; 799 | } 800 | return avl_tree_num_entries(value->_data._map_array); 801 | } 802 | 803 | const tinybuf_value* tinybuf_value_get_array_child(const tinybuf_value *value,int index){ 804 | if(!value || value->_type != tinybuf_array || !value->_data._map_array){ 805 | return NULL; 806 | } 807 | return (tinybuf_value*)avl_tree_lookup(value->_data._map_array,(AVLTreeKey)index); 808 | } 809 | 810 | 811 | const tinybuf_value* tinybuf_value_get_map_child(const tinybuf_value *value,const char *key){ 812 | return tinybuf_value_get_map_child2(value,key,strlen(key)); 813 | } 814 | 815 | const tinybuf_value* tinybuf_value_get_map_child2(const tinybuf_value *value,const char *key, int key_len){ 816 | if(!value || !key || value->_type != tinybuf_map || !value->_data._map_array){ 817 | return NULL; 818 | } 819 | 820 | buffer buf; 821 | buf._data = (char *)key; 822 | buf._len = key_len; 823 | buf._capacity = buf._len + 1; 824 | 825 | return (tinybuf_value*)avl_tree_lookup(value->_data._map_array,&buf); 826 | } 827 | 828 | 829 | const tinybuf_value* tinybuf_value_get_map_child_and_key(const tinybuf_value *value, int index,buffer **key){ 830 | if(!value || value->_type != tinybuf_map || !value->_data._map_array){ 831 | return NULL; 832 | } 833 | 834 | AVLTreeNode *node = avl_tree_get_node_by_index(value->_data._map_array,index); 835 | if(!node){ 836 | return NULL; 837 | } 838 | 839 | if(key){ 840 | *key = (buffer *)avl_tree_node_key(node); 841 | } 842 | 843 | return (tinybuf_value*)avl_tree_node_value(node); 844 | } 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | -------------------------------------------------------------------------------- /3rdpart/jsoncpp/value.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_H_INCLUDED 7 | #define CPPTL_JSON_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "forwards.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | #include 13 | #include 14 | #include 15 | 16 | #ifndef JSON_USE_CPPTL_SMALLMAP 17 | #include 18 | #else 19 | #include 20 | #endif 21 | #ifdef JSON_USE_CPPTL 22 | #include 23 | #endif 24 | 25 | // Disable warning C4251: : needs to have dll-interface to 26 | // be used by... 27 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 28 | #pragma warning(push) 29 | #pragma warning(disable : 4251) 30 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 31 | 32 | /** \brief JSON (JavaScript Object Notation). 33 | */ 34 | namespace Json { 35 | 36 | /** Base class for all exceptions we throw. 37 | * 38 | * We use nothing but these internally. Of course, STL can throw others. 39 | */ 40 | class JSON_API Exception : public std::exception { 41 | public: 42 | Exception(std::string const& msg); 43 | virtual ~Exception() throw(); 44 | virtual char const* what() const throw(); 45 | protected: 46 | std::string const msg_; 47 | }; 48 | 49 | /** Exceptions which the user cannot easily avoid. 50 | * 51 | * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input 52 | * 53 | * \remark derived from Json::Exception 54 | */ 55 | class JSON_API RuntimeError : public Exception { 56 | public: 57 | RuntimeError(std::string const& msg); 58 | }; 59 | 60 | /** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. 61 | * 62 | * These are precondition-violations (user bugs) and internal errors (our bugs). 63 | * 64 | * \remark derived from Json::Exception 65 | */ 66 | class JSON_API LogicError : public Exception { 67 | public: 68 | LogicError(std::string const& msg); 69 | }; 70 | 71 | /// used internally 72 | void throwRuntimeError(std::string const& msg); 73 | /// used internally 74 | void throwLogicError(std::string const& msg); 75 | 76 | /** \brief Type of the value held by a Value object. 77 | */ 78 | enum ValueType { 79 | nullValue = 0, ///< 'null' value 80 | intValue, ///< signed integer value 81 | uintValue, ///< unsigned integer value 82 | realValue, ///< double value 83 | stringValue, ///< UTF-8 string value 84 | booleanValue, ///< bool value 85 | arrayValue, ///< array value (ordered list) 86 | objectValue ///< object value (collection of name/value pairs). 87 | }; 88 | 89 | enum CommentPlacement { 90 | commentBefore = 0, ///< a comment placed on the line before a value 91 | commentAfterOnSameLine, ///< a comment just after a value on the same line 92 | commentAfter, ///< a comment on the line after a value (only make sense for 93 | /// root value) 94 | numberOfCommentPlacement 95 | }; 96 | 97 | //# ifdef JSON_USE_CPPTL 98 | // typedef CppTL::AnyEnumerator EnumMemberNames; 99 | // typedef CppTL::AnyEnumerator EnumValues; 100 | //# endif 101 | 102 | /** \brief Lightweight wrapper to tag static string. 103 | * 104 | * Value constructor and objectValue member assignement takes advantage of the 105 | * StaticString and avoid the cost of string duplication when storing the 106 | * string or the member name. 107 | * 108 | * Example of usage: 109 | * \code 110 | * Json::Value aValue( StaticString("some text") ); 111 | * Json::Value object; 112 | * static const StaticString code("code"); 113 | * object[code] = 1234; 114 | * \endcode 115 | */ 116 | class JSON_API StaticString { 117 | public: 118 | explicit StaticString(const char* czstring) : c_str_(czstring) {} 119 | 120 | operator const char*() const { return c_str_; } 121 | 122 | const char* c_str() const { return c_str_; } 123 | 124 | private: 125 | const char* c_str_; 126 | }; 127 | 128 | /** \brief Represents a JSON value. 129 | * 130 | * This class is a discriminated union wrapper that can represents a: 131 | * - signed integer [range: Value::minInt - Value::maxInt] 132 | * - unsigned integer (range: 0 - Value::maxUInt) 133 | * - double 134 | * - UTF-8 string 135 | * - boolean 136 | * - 'null' 137 | * - an ordered list of Value 138 | * - collection of name/value pairs (javascript object) 139 | * 140 | * The type of the held value is represented by a #ValueType and 141 | * can be obtained using type(). 142 | * 143 | * Values of an #objectValue or #arrayValue can be accessed using operator[]() 144 | * methods. 145 | * Non-const methods will automatically create the a #nullValue element 146 | * if it does not exist. 147 | * The sequence of an #arrayValue will be automatically resized and initialized 148 | * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. 149 | * 150 | * The get() methods can be used to obtain default value in the case the 151 | * required element does not exist. 152 | * 153 | * It is possible to iterate over the list of a #objectValue values using 154 | * the getMemberNames() method. 155 | * 156 | * \note #Value string-length fit in size_t, but keys must be < 2^30. 157 | * (The reason is an implementation detail.) A #CharReader will raise an 158 | * exception if a bound is exceeded to avoid security holes in your app, 159 | * but the Value API does *not* check bounds. That is the responsibility 160 | * of the caller. 161 | */ 162 | class JSON_API Value { 163 | friend class ValueIteratorBase; 164 | public: 165 | typedef std::vector Members; 166 | typedef ValueIterator iterator; 167 | typedef ValueConstIterator const_iterator; 168 | typedef Json::UInt UInt; 169 | typedef Json::Int Int; 170 | #if defined(JSON_HAS_INT64) 171 | typedef Json::UInt64 UInt64; 172 | typedef Json::Int64 Int64; 173 | #endif // defined(JSON_HAS_INT64) 174 | typedef Json::LargestInt LargestInt; 175 | typedef Json::LargestUInt LargestUInt; 176 | typedef Json::ArrayIndex ArrayIndex; 177 | 178 | static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value(). 179 | static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null 180 | /// Minimum signed integer value that can be stored in a Json::Value. 181 | static const LargestInt minLargestInt; 182 | /// Maximum signed integer value that can be stored in a Json::Value. 183 | static const LargestInt maxLargestInt; 184 | /// Maximum unsigned integer value that can be stored in a Json::Value. 185 | static const LargestUInt maxLargestUInt; 186 | 187 | /// Minimum signed int value that can be stored in a Json::Value. 188 | static const Int minInt; 189 | /// Maximum signed int value that can be stored in a Json::Value. 190 | static const Int maxInt; 191 | /// Maximum unsigned int value that can be stored in a Json::Value. 192 | static const UInt maxUInt; 193 | 194 | #if defined(JSON_HAS_INT64) 195 | /// Minimum signed 64 bits int value that can be stored in a Json::Value. 196 | static const Int64 minInt64; 197 | /// Maximum signed 64 bits int value that can be stored in a Json::Value. 198 | static const Int64 maxInt64; 199 | /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. 200 | static const UInt64 maxUInt64; 201 | #endif // defined(JSON_HAS_INT64) 202 | 203 | private: 204 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 205 | class CZString { 206 | public: 207 | enum DuplicationPolicy { 208 | noDuplication = 0, 209 | duplicate, 210 | duplicateOnCopy 211 | }; 212 | CZString(ArrayIndex index); 213 | CZString(char const* str, unsigned length, DuplicationPolicy allocate); 214 | CZString(CZString const& other); 215 | ~CZString(); 216 | CZString& operator=(CZString other); 217 | bool operator<(CZString const& other) const; 218 | bool operator==(CZString const& other) const; 219 | ArrayIndex index() const; 220 | //const char* c_str() const; ///< \deprecated 221 | char const* data() const; 222 | unsigned length() const; 223 | bool isStaticString() const; 224 | 225 | private: 226 | void swap(CZString& other); 227 | 228 | struct StringStorage { 229 | unsigned policy_: 2; 230 | unsigned length_: 30; // 1GB max 231 | }; 232 | 233 | char const* cstr_; // actually, a prefixed string, unless policy is noDup 234 | union { 235 | ArrayIndex index_; 236 | StringStorage storage_; 237 | }; 238 | }; 239 | 240 | public: 241 | #ifndef JSON_USE_CPPTL_SMALLMAP 242 | typedef std::map ObjectValues; 243 | #else 244 | typedef CppTL::SmallMap ObjectValues; 245 | #endif // ifndef JSON_USE_CPPTL_SMALLMAP 246 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 247 | 248 | public: 249 | /** \brief Create a default Value of the given type. 250 | 251 | This is a very useful constructor. 252 | To create an empty array, pass arrayValue. 253 | To create an empty object, pass objectValue. 254 | Another Value can then be set to this one by assignment. 255 | This is useful since clear() and resize() will not alter types. 256 | 257 | Examples: 258 | \code 259 | Json::Value null_value; // null 260 | Json::Value arr_value(Json::arrayValue); // [] 261 | Json::Value obj_value(Json::objectValue); // {} 262 | \endcode 263 | */ 264 | Value(ValueType type = nullValue); 265 | Value(Int value); 266 | Value(UInt value); 267 | #if defined(JSON_HAS_INT64) 268 | Value(Int64 value); 269 | Value(UInt64 value); 270 | #endif // if defined(JSON_HAS_INT64) 271 | Value(double value); 272 | Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) 273 | Value(const char* begin, const char* end); ///< Copy all, incl zeroes. 274 | /** \brief Constructs a value from a static string. 275 | 276 | * Like other value string constructor but do not duplicate the string for 277 | * internal storage. The given string must remain alive after the call to this 278 | * constructor. 279 | * \note This works only for null-terminated strings. (We cannot change the 280 | * size of this class, so we have nowhere to store the length, 281 | * which might be computed later for various operations.) 282 | * 283 | * Example of usage: 284 | * \code 285 | * static StaticString foo("some text"); 286 | * Json::Value aValue(foo); 287 | * \endcode 288 | */ 289 | Value(const StaticString& value); 290 | Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too. 291 | #ifdef JSON_USE_CPPTL 292 | Value(const CppTL::ConstString& value); 293 | #endif 294 | Value(bool value); 295 | /// Deep copy. 296 | Value(const Value& other); 297 | ~Value(); 298 | 299 | /// Deep copy, then swap(other). 300 | /// \note Over-write existing comments. To preserve comments, use #swapPayload(). 301 | Value& operator=(Value other); 302 | /// Swap everything. 303 | void swap(Value& other); 304 | /// Swap values but leave comments and source offsets in place. 305 | void swapPayload(Value& other); 306 | 307 | ValueType type() const; 308 | 309 | /// Compare payload only, not comments etc. 310 | bool operator<(const Value& other) const; 311 | bool operator<=(const Value& other) const; 312 | bool operator>=(const Value& other) const; 313 | bool operator>(const Value& other) const; 314 | bool operator==(const Value& other) const; 315 | bool operator!=(const Value& other) const; 316 | int compare(const Value& other) const; 317 | 318 | const char* asCString() const; ///< Embedded zeroes could cause you trouble! 319 | std::string asString() const; ///< Embedded zeroes are possible. 320 | /** Get raw char* of string-value. 321 | * \return false if !string. (Seg-fault if str or end are NULL.) 322 | */ 323 | bool getString( 324 | char const** begin, char const** end) const; 325 | #ifdef JSON_USE_CPPTL 326 | CppTL::ConstString asConstString() const; 327 | #endif 328 | Int asInt() const; 329 | UInt asUInt() const; 330 | #if defined(JSON_HAS_INT64) 331 | Int64 asInt64() const; 332 | UInt64 asUInt64() const; 333 | #endif // if defined(JSON_HAS_INT64) 334 | LargestInt asLargestInt() const; 335 | LargestUInt asLargestUInt() const; 336 | float asFloat() const; 337 | double asDouble() const; 338 | bool asBool() const; 339 | 340 | bool isNull() const; 341 | bool isBool() const; 342 | bool isInt() const; 343 | bool isInt64() const; 344 | bool isUInt() const; 345 | bool isUInt64() const; 346 | bool isIntegral() const; 347 | bool isDouble() const; 348 | bool isNumeric() const; 349 | bool isString() const; 350 | bool isArray() const; 351 | bool isObject() const; 352 | 353 | bool isConvertibleTo(ValueType other) const; 354 | 355 | /// Number of values in array or object 356 | ArrayIndex size() const; 357 | 358 | /// \brief Return true if empty array, empty object, or null; 359 | /// otherwise, false. 360 | bool empty() const; 361 | 362 | /// Return isNull() 363 | bool operator!() const; 364 | 365 | /// Remove all object members and array elements. 366 | /// \pre type() is arrayValue, objectValue, or nullValue 367 | /// \post type() is unchanged 368 | void clear(); 369 | 370 | /// Resize the array to size elements. 371 | /// New elements are initialized to null. 372 | /// May only be called on nullValue or arrayValue. 373 | /// \pre type() is arrayValue or nullValue 374 | /// \post type() is arrayValue 375 | void resize(ArrayIndex size); 376 | 377 | /// Access an array element (zero based index ). 378 | /// If the array contains less than index element, then null value are 379 | /// inserted 380 | /// in the array so that its size is index+1. 381 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 382 | /// this from the operator[] which takes a string.) 383 | Value& operator[](ArrayIndex index); 384 | 385 | /// Access an array element (zero based index ). 386 | /// If the array contains less than index element, then null value are 387 | /// inserted 388 | /// in the array so that its size is index+1. 389 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 390 | /// this from the operator[] which takes a string.) 391 | Value& operator[](int index); 392 | 393 | /// Access an array element (zero based index ) 394 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 395 | /// this from the operator[] which takes a string.) 396 | const Value& operator[](ArrayIndex index) const; 397 | 398 | /// Access an array element (zero based index ) 399 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 400 | /// this from the operator[] which takes a string.) 401 | const Value& operator[](int index) const; 402 | 403 | /// If the array contains at least index+1 elements, returns the element 404 | /// value, 405 | /// otherwise returns defaultValue. 406 | Value get(ArrayIndex index, const Value& defaultValue) const; 407 | /// Return true if index < size(). 408 | bool isValidIndex(ArrayIndex index) const; 409 | /// \brief Append value to array at the end. 410 | /// 411 | /// Equivalent to jsonvalue[jsonvalue.size()] = value; 412 | Value& append(const Value& value); 413 | 414 | /// Access an object value by name, create a null member if it does not exist. 415 | /// \note Because of our implementation, keys are limited to 2^30 -1 chars. 416 | /// Exceeding that will cause an exception. 417 | Value& operator[](const char* key); 418 | /// Access an object value by name, returns null if there is no member with 419 | /// that name. 420 | const Value& operator[](const char* key) const; 421 | /// Access an object value by name, create a null member if it does not exist. 422 | /// \param key may contain embedded nulls. 423 | Value& operator[](const std::string& key); 424 | /// Access an object value by name, returns null if there is no member with 425 | /// that name. 426 | /// \param key may contain embedded nulls. 427 | const Value& operator[](const std::string& key) const; 428 | /** \brief Access an object value by name, create a null member if it does not 429 | exist. 430 | 431 | * If the object has no entry for that name, then the member name used to store 432 | * the new entry is not duplicated. 433 | * Example of use: 434 | * \code 435 | * Json::Value object; 436 | * static const StaticString code("code"); 437 | * object[code] = 1234; 438 | * \endcode 439 | */ 440 | Value& operator[](const StaticString& key); 441 | #ifdef JSON_USE_CPPTL 442 | /// Access an object value by name, create a null member if it does not exist. 443 | Value& operator[](const CppTL::ConstString& key); 444 | /// Access an object value by name, returns null if there is no member with 445 | /// that name. 446 | const Value& operator[](const CppTL::ConstString& key) const; 447 | #endif 448 | /// Return the member named key if it exist, defaultValue otherwise. 449 | /// \note deep copy 450 | Value get(const char* key, const Value& defaultValue) const; 451 | /// Return the member named key if it exist, defaultValue otherwise. 452 | /// \note deep copy 453 | /// \note key may contain embedded nulls. 454 | Value get(const char* begin, const char* end, const Value& defaultValue) const; 455 | /// Return the member named key if it exist, defaultValue otherwise. 456 | /// \note deep copy 457 | /// \param key may contain embedded nulls. 458 | Value get(const std::string& key, const Value& defaultValue) const; 459 | #ifdef JSON_USE_CPPTL 460 | /// Return the member named key if it exist, defaultValue otherwise. 461 | /// \note deep copy 462 | Value get(const CppTL::ConstString& key, const Value& defaultValue) const; 463 | #endif 464 | /// Most general and efficient version of isMember()const, get()const, 465 | /// and operator[]const 466 | /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 467 | Value const* find(char const* begin, char const* end) const; 468 | /// Most general and efficient version of object-mutators. 469 | /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 470 | /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. 471 | Value const* demand(char const* begin, char const* end); 472 | /// \brief Remove and return the named member. 473 | /// 474 | /// Do nothing if it did not exist. 475 | /// \return the removed Value, or null. 476 | /// \pre type() is objectValue or nullValue 477 | /// \post type() is unchanged 478 | /// \deprecated 479 | Value removeMember(const char* key); 480 | /// Same as removeMember(const char*) 481 | /// \param key may contain embedded nulls. 482 | /// \deprecated 483 | Value removeMember(const std::string& key); 484 | /// Same as removeMember(const char* begin, const char* end, Value* removed), 485 | /// but 'key' is null-terminated. 486 | bool removeMember(const char* key, Value* removed); 487 | /** \brief Remove the named map member. 488 | 489 | Update 'removed' iff removed. 490 | \param key may contain embedded nulls. 491 | \return true iff removed (no exceptions) 492 | */ 493 | bool removeMember(std::string const& key, Value* removed); 494 | /// Same as removeMember(std::string const& key, Value* removed) 495 | bool removeMember(const char* begin, const char* end, Value* removed); 496 | /** \brief Remove the indexed array element. 497 | 498 | O(n) expensive operations. 499 | Update 'removed' iff removed. 500 | \return true iff removed (no exceptions) 501 | */ 502 | bool removeIndex(ArrayIndex i, Value* removed); 503 | 504 | /// Return true if the object has a member named key. 505 | /// \note 'key' must be null-terminated. 506 | bool isMember(const char* key) const; 507 | /// Return true if the object has a member named key. 508 | /// \param key may contain embedded nulls. 509 | bool isMember(const std::string& key) const; 510 | /// Same as isMember(std::string const& key)const 511 | bool isMember(const char* begin, const char* end) const; 512 | #ifdef JSON_USE_CPPTL 513 | /// Return true if the object has a member named key. 514 | bool isMember(const CppTL::ConstString& key) const; 515 | #endif 516 | 517 | /// \brief Return a list of the member names. 518 | /// 519 | /// If null, return an empty list. 520 | /// \pre type() is objectValue or nullValue 521 | /// \post if type() was nullValue, it remains nullValue 522 | Members getMemberNames() const; 523 | 524 | //# ifdef JSON_USE_CPPTL 525 | // EnumMemberNames enumMemberNames() const; 526 | // EnumValues enumValues() const; 527 | //# endif 528 | 529 | /// \deprecated Always pass len. 530 | JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.") 531 | void setComment(const char* comment, CommentPlacement placement); 532 | /// Comments must be //... or /* ... */ 533 | void setComment(const char* comment, size_t len, CommentPlacement placement); 534 | /// Comments must be //... or /* ... */ 535 | void setComment(const std::string& comment, CommentPlacement placement); 536 | bool hasComment(CommentPlacement placement) const; 537 | /// Include delimiters and embedded newlines. 538 | std::string getComment(CommentPlacement placement) const; 539 | 540 | std::string toStyledString() const; 541 | 542 | const_iterator begin() const; 543 | const_iterator end() const; 544 | 545 | iterator begin(); 546 | iterator end(); 547 | 548 | // Accessors for the [start, limit) range of bytes within the JSON text from 549 | // which this value was parsed, if any. 550 | void setOffsetStart(size_t start); 551 | void setOffsetLimit(size_t limit); 552 | size_t getOffsetStart() const; 553 | size_t getOffsetLimit() const; 554 | 555 | private: 556 | void initBasic(ValueType type, bool allocated = false); 557 | 558 | Value& resolveReference(const char* key); 559 | Value& resolveReference(const char* key, const char* end); 560 | 561 | struct CommentInfo { 562 | CommentInfo(); 563 | ~CommentInfo(); 564 | 565 | void setComment(const char* text, size_t len); 566 | 567 | char* comment_; 568 | }; 569 | 570 | // struct MemberNamesTransform 571 | //{ 572 | // typedef const char *result_type; 573 | // const char *operator()( const CZString &name ) const 574 | // { 575 | // return name.c_str(); 576 | // } 577 | //}; 578 | 579 | union ValueHolder { 580 | LargestInt int_; 581 | LargestUInt uint_; 582 | double real_; 583 | bool bool_; 584 | char* string_; // actually ptr to unsigned, followed by str, unless !allocated_ 585 | ObjectValues* map_; 586 | } value_; 587 | ValueType type_ : 8; 588 | unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. 589 | // If not allocated_, string_ must be null-terminated. 590 | CommentInfo* comments_; 591 | 592 | // [start, limit) byte offsets in the source JSON text from which this Value 593 | // was extracted. 594 | size_t start_; 595 | size_t limit_; 596 | }; 597 | 598 | /** \brief Experimental and untested: represents an element of the "path" to 599 | * access a node. 600 | */ 601 | class JSON_API PathArgument { 602 | public: 603 | friend class Path; 604 | 605 | PathArgument(); 606 | PathArgument(ArrayIndex index); 607 | PathArgument(const char* key); 608 | PathArgument(const std::string& key); 609 | 610 | private: 611 | enum Kind { 612 | kindNone = 0, 613 | kindIndex, 614 | kindKey 615 | }; 616 | std::string key_; 617 | ArrayIndex index_; 618 | Kind kind_; 619 | }; 620 | 621 | /** \brief Experimental and untested: represents a "path" to access a node. 622 | * 623 | * Syntax: 624 | * - "." => root node 625 | * - ".[n]" => elements at index 'n' of root node (an array value) 626 | * - ".name" => member named 'name' of root node (an object value) 627 | * - ".name1.name2.name3" 628 | * - ".[0][1][2].name1[3]" 629 | * - ".%" => member name is provided as parameter 630 | * - ".[%]" => index is provied as parameter 631 | */ 632 | class JSON_API Path { 633 | public: 634 | Path(const std::string& path, 635 | const PathArgument& a1 = PathArgument(), 636 | const PathArgument& a2 = PathArgument(), 637 | const PathArgument& a3 = PathArgument(), 638 | const PathArgument& a4 = PathArgument(), 639 | const PathArgument& a5 = PathArgument()); 640 | 641 | const Value& resolve(const Value& root) const; 642 | Value resolve(const Value& root, const Value& defaultValue) const; 643 | /// Creates the "path" to access the specified node and returns a reference on 644 | /// the node. 645 | Value& make(Value& root) const; 646 | 647 | private: 648 | typedef std::vector InArgs; 649 | typedef std::vector Args; 650 | 651 | void makePath(const std::string& path, const InArgs& in); 652 | void addPathInArg(const std::string& path, 653 | const InArgs& in, 654 | InArgs::const_iterator& itInArg, 655 | PathArgument::Kind kind); 656 | void invalidPath(const std::string& path, int location); 657 | 658 | Args args_; 659 | }; 660 | 661 | /** \brief base class for Value iterators. 662 | * 663 | */ 664 | class JSON_API ValueIteratorBase { 665 | public: 666 | typedef std::bidirectional_iterator_tag iterator_category; 667 | typedef unsigned int size_t; 668 | typedef int difference_type; 669 | typedef ValueIteratorBase SelfType; 670 | 671 | bool operator==(const SelfType& other) const { return isEqual(other); } 672 | 673 | bool operator!=(const SelfType& other) const { return !isEqual(other); } 674 | 675 | difference_type operator-(const SelfType& other) const { 676 | return other.computeDistance(*this); 677 | } 678 | 679 | /// Return either the index or the member name of the referenced value as a 680 | /// Value. 681 | Value key() const; 682 | 683 | /// Return the index of the referenced Value, or -1 if it is not an arrayValue. 684 | UInt index() const; 685 | 686 | /// Return the member name of the referenced Value, or "" if it is not an 687 | /// objectValue. 688 | /// \note Avoid `c_str()` on result, as embedded zeroes are possible. 689 | std::string name() const; 690 | 691 | /// Return the member name of the referenced Value. "" if it is not an 692 | /// objectValue. 693 | /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls. 694 | JSONCPP_DEPRECATED("Use `key = name();` instead.") 695 | char const* memberName() const; 696 | /// Return the member name of the referenced Value, or NULL if it is not an 697 | /// objectValue. 698 | /// \note Better version than memberName(). Allows embedded nulls. 699 | char const* memberName(char const** end) const; 700 | 701 | protected: 702 | Value& deref() const; 703 | 704 | void increment(); 705 | 706 | void decrement(); 707 | 708 | difference_type computeDistance(const SelfType& other) const; 709 | 710 | bool isEqual(const SelfType& other) const; 711 | 712 | void copy(const SelfType& other); 713 | 714 | private: 715 | Value::ObjectValues::iterator current_; 716 | // Indicates that iterator is for a null value. 717 | bool isNull_; 718 | 719 | public: 720 | // For some reason, BORLAND needs these at the end, rather 721 | // than earlier. No idea why. 722 | ValueIteratorBase(); 723 | explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); 724 | }; 725 | 726 | /** \brief const iterator for object and array value. 727 | * 728 | */ 729 | class JSON_API ValueConstIterator : public ValueIteratorBase { 730 | friend class Value; 731 | 732 | public: 733 | typedef const Value value_type; 734 | //typedef unsigned int size_t; 735 | //typedef int difference_type; 736 | typedef const Value& reference; 737 | typedef const Value* pointer; 738 | typedef ValueConstIterator SelfType; 739 | 740 | ValueConstIterator(); 741 | 742 | private: 743 | /*! \internal Use by Value to create an iterator. 744 | */ 745 | explicit ValueConstIterator(const Value::ObjectValues::iterator& current); 746 | public: 747 | SelfType& operator=(const ValueIteratorBase& other); 748 | 749 | SelfType operator++(int) { 750 | SelfType temp(*this); 751 | ++*this; 752 | return temp; 753 | } 754 | 755 | SelfType operator--(int) { 756 | SelfType temp(*this); 757 | --*this; 758 | return temp; 759 | } 760 | 761 | SelfType& operator--() { 762 | decrement(); 763 | return *this; 764 | } 765 | 766 | SelfType& operator++() { 767 | increment(); 768 | return *this; 769 | } 770 | 771 | reference operator*() const { return deref(); } 772 | 773 | pointer operator->() const { return &deref(); } 774 | }; 775 | 776 | /** \brief Iterator for object and array value. 777 | */ 778 | class JSON_API ValueIterator : public ValueIteratorBase { 779 | friend class Value; 780 | 781 | public: 782 | typedef Value value_type; 783 | typedef unsigned int size_t; 784 | typedef int difference_type; 785 | typedef Value& reference; 786 | typedef Value* pointer; 787 | typedef ValueIterator SelfType; 788 | 789 | ValueIterator(); 790 | ValueIterator(const ValueConstIterator& other); 791 | ValueIterator(const ValueIterator& other); 792 | 793 | private: 794 | /*! \internal Use by Value to create an iterator. 795 | */ 796 | explicit ValueIterator(const Value::ObjectValues::iterator& current); 797 | public: 798 | SelfType& operator=(const SelfType& other); 799 | 800 | SelfType operator++(int) { 801 | SelfType temp(*this); 802 | ++*this; 803 | return temp; 804 | } 805 | 806 | SelfType operator--(int) { 807 | SelfType temp(*this); 808 | --*this; 809 | return temp; 810 | } 811 | 812 | SelfType& operator--() { 813 | decrement(); 814 | return *this; 815 | } 816 | 817 | SelfType& operator++() { 818 | increment(); 819 | return *this; 820 | } 821 | 822 | reference operator*() const { return deref(); } 823 | 824 | pointer operator->() const { return &deref(); } 825 | }; 826 | 827 | } // namespace Json 828 | 829 | 830 | namespace std { 831 | /// Specialize std::swap() for Json::Value. 832 | template<> 833 | inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } 834 | } 835 | 836 | 837 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 838 | #pragma warning(pop) 839 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 840 | 841 | #endif // CPPTL_JSON_H_INCLUDED 842 | -------------------------------------------------------------------------------- /src/source/tinybuf_json.c: -------------------------------------------------------------------------------- 1 | #include "tinybuf_private.h" 2 | 3 | //////////////////////////////////////json序列化////////////////////////////////////// 4 | //预留的空格 5 | static char s_blank[] = " "; 6 | static void add_blank(buffer *out,int blank){ 7 | if(!blank){ 8 | return; 9 | } 10 | if(blank > sizeof(s_blank)){ 11 | char *blanks = tinybuf_malloc(blank); 12 | memset(blanks,' ',blank); 13 | buffer_append(out,blanks,blank); 14 | tinybuf_free(blanks); 15 | }else{ 16 | buffer_append(out,s_blank,blank); 17 | } 18 | } 19 | 20 | static inline char to_char(uint8_t ch){ 21 | if(ch < 10){ 22 | return '0' + ch; 23 | } 24 | if (ch < 16){ 25 | return 'A' + (ch - 10); 26 | } 27 | assert(0); 28 | return '0'; 29 | } 30 | 31 | static inline int dump_binary(buffer *out,uint8_t ch){ 32 | buffer_push_inline(out,to_char(ch >> 4)); 33 | buffer_push_inline(out,to_char(ch & 0x0F)); 34 | return 2; 35 | } 36 | 37 | static inline int isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } 38 | 39 | static inline void json_encode_string(buffer *out, uint8_t *in, int len){ 40 | if(len <= 0){ 41 | len = strlen((char *)in); 42 | } 43 | int i; 44 | for(i = 0 ; i < len ; ++i){ 45 | char ch = in[i]; 46 | switch (ch){ 47 | case '\"': 48 | buffer_append(out,"\\\"",2); 49 | break; 50 | case '\\': 51 | buffer_append(out,"\\\\",2); 52 | break; 53 | case '\b': 54 | buffer_append(out,"\\b",2); 55 | break; 56 | case '\f': 57 | buffer_append(out,"\\f",2); 58 | break; 59 | case '\n': 60 | buffer_append(out,"\\n",2); 61 | break; 62 | case '\r': 63 | buffer_append(out,"\\r",2); 64 | break; 65 | case '\t': 66 | buffer_append(out,"\\t",2); 67 | break; 68 | default:{ 69 | if ((isControlCharacter(ch)) || (ch == 0)) { 70 | buffer_append(out,"\\u00",4); 71 | dump_binary(out,ch); 72 | } else { 73 | buffer_append(out,&ch,1); 74 | } 75 | } 76 | break; 77 | } 78 | } 79 | } 80 | 81 | static inline void dump_double(double value,buffer *out){ 82 | // Allocate a buffer that is more than large enough to store the 16 digits of 83 | // precision requested below. 84 | char buffer[32]; 85 | int len = -1; 86 | 87 | // Print into the buffer. We need not request the alternative representation 88 | // that always has a decimal point because JSON doesn't distingish the 89 | // concepts of reals and integers. 90 | #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with 91 | // visual studio 2005 to 92 | // avoid warning. 93 | #if defined(WINCE) 94 | len = _snprintf(buffer, sizeof(buffer), "%.17g", value); 95 | #else 96 | len = sprintf_s(buffer, sizeof(buffer), "%.17g", value); 97 | #endif 98 | #else 99 | if (isfinite(value)) { 100 | len = snprintf(buffer, sizeof(buffer), "%.17g", value); 101 | } else { 102 | // IEEE standard states that NaN values will not compare to themselves 103 | if (value != value) { 104 | len = snprintf(buffer, sizeof(buffer), "null"); 105 | } else if (value < 0) { 106 | len = snprintf(buffer, sizeof(buffer), "-1e+9999"); 107 | } else { 108 | len = snprintf(buffer, sizeof(buffer), "1e+9999"); 109 | } 110 | // For those, we do not need to call fixNumLoc, but it is fast. 111 | } 112 | #endif 113 | assert(len >= 0); 114 | buffer_append(out,buffer,len); 115 | } 116 | 117 | typedef struct{ 118 | buffer *out; 119 | int i; 120 | int size; 121 | int compact; 122 | int level; 123 | } for_each_context; 124 | 125 | static int tinybuf_value_serialize_as_json_level(int level,int compact, const tinybuf_value *value, buffer *out); 126 | 127 | static int avl_tree_for_each_node_dump_array(void *user_data,AVLTreeNode *node){ 128 | for_each_context *context = (for_each_context *)user_data; 129 | tinybuf_value *val = (tinybuf_value *)avl_tree_node_value(node); 130 | if(val->_type != tinybuf_map && val->_type != tinybuf_array && !context->compact){ 131 | add_blank(context->out,4 * context->level + 4); 132 | } 133 | //写value 134 | tinybuf_value_serialize_as_json_level(context->level + 1,context->compact, val, context->out); 135 | if(context->i++ != context->size - 1){ 136 | buffer_push_inline(context->out,','); 137 | } 138 | if(!context->compact) { 139 | buffer_append(context->out, "\r\n", 2); 140 | } 141 | 142 | //继续遍历 143 | return 0; 144 | } 145 | 146 | static int avl_tree_for_each_node_dump_map(void *user_data,AVLTreeNode *node){ 147 | for_each_context *context = (for_each_context *)user_data; 148 | buffer *key = (buffer*)avl_tree_node_key(node); 149 | tinybuf_value *val = (tinybuf_value *)avl_tree_node_value(node); 150 | if(!context->compact) { 151 | add_blank(context->out, 4 * context->level + 4); 152 | } 153 | buffer_append(context->out,"\"",1); 154 | json_encode_string(context->out, (uint8_t *) buffer_get_data_inline(key), buffer_get_length_inline(key)); 155 | if(!context->compact){ 156 | buffer_append(context->out,"\" : ",4); 157 | }else{ 158 | buffer_append(context->out,"\":",2); 159 | } 160 | if((val->_type == tinybuf_map || val->_type == tinybuf_array) && !context->compact){ 161 | buffer_append(context->out,"\r\n",2); 162 | } 163 | //写value 164 | tinybuf_value_serialize_as_json_level(context->level + 1,context->compact, val, context->out); 165 | 166 | if(context->i++ != context->size - 1){ 167 | buffer_push_inline(context->out,','); 168 | } 169 | if(!context->compact){ 170 | buffer_append(context->out,"\r\n",2); 171 | } 172 | 173 | //继续遍历 174 | return 0; 175 | } 176 | 177 | enum { 178 | /// Constant that specify the size of the buffer that must be passed to 179 | /// uintToString. 180 | uintToStringBufferSize = 3 * sizeof(int64_t) + 1 181 | }; 182 | 183 | 184 | // Defines a char buffer for use with uintToString(). 185 | typedef char UIntToStringBuffer[uintToStringBufferSize]; 186 | 187 | /** Converts an unsigned integer to string. 188 | * @param value Unsigned interger to convert to string 189 | * @param current Input/Output string buffer. 190 | * Must have at least uintToStringBufferSize chars free. 191 | */ 192 | static inline void uintToString(int64_t value, char** current) { 193 | *--(*current) = 0; 194 | do { 195 | *--(*current) = (signed char)(value % 10U + (unsigned)('0')); 196 | value /= 10; 197 | } while (value != 0); 198 | } 199 | 200 | static inline int dump_int(buffer *out,int64_t value){ 201 | UIntToStringBuffer buffer; 202 | char* current = buffer + sizeof(buffer); 203 | if (value < 0) { 204 | uintToString(-value, ¤t); 205 | *--current = '-'; 206 | } else { 207 | uintToString(value, ¤t); 208 | } 209 | buffer_append(out,current,0); 210 | return 0; 211 | } 212 | static int tinybuf_value_serialize_as_json_level(int level,int compact, const tinybuf_value *value, buffer *out){ 213 | assert(value); 214 | assert(out); 215 | switch (value->_type){ 216 | case tinybuf_null:{ 217 | buffer_append(out,"null",4); 218 | } 219 | break; 220 | 221 | case tinybuf_int:{ 222 | dump_int(out,value->_data._int); 223 | } 224 | break; 225 | 226 | case tinybuf_bool:{ 227 | buffer_append(out,value->_data._bool ? "true" : "false",0); 228 | } 229 | break; 230 | 231 | case tinybuf_double:{ 232 | dump_double(value->_data._double,out); 233 | } 234 | break; 235 | 236 | case tinybuf_string:{ 237 | buffer_append(out,"\"",1); 238 | int len = buffer_get_length_inline(value->_data._string); 239 | if(len){ 240 | json_encode_string(out, (uint8_t *) buffer_get_data_inline(value->_data._string),len); 241 | } 242 | buffer_append(out,"\"",1); 243 | } 244 | break; 245 | 246 | case tinybuf_map:{ 247 | if(!compact){ 248 | add_blank(out,4 * level); 249 | buffer_append(out,"{\r\n",3); 250 | }else{ 251 | buffer_push_inline(out,'{'); 252 | } 253 | 254 | int map_size = avl_tree_num_entries(value->_data._map_array); 255 | if(map_size){ 256 | for_each_context context; 257 | context.size = map_size; 258 | context.compact = compact; 259 | context.i = 0; 260 | context.out = out; 261 | context.level = level; 262 | avl_tree_for_each_node(value->_data._map_array,&context,avl_tree_for_each_node_dump_map); 263 | } 264 | 265 | if(!compact) { 266 | add_blank(out, 4 * level); 267 | } 268 | buffer_append(out,"}",1); 269 | } 270 | break; 271 | 272 | 273 | case tinybuf_array:{ 274 | if(!compact) { 275 | add_blank(out, 4 * level); 276 | buffer_append(out, "[\r\n", 3); 277 | }else{ 278 | buffer_push_inline(out,'['); 279 | } 280 | 281 | int array_size = avl_tree_num_entries(value->_data._map_array); 282 | if(array_size){ 283 | for_each_context context; 284 | context.size = array_size; 285 | context.compact = compact; 286 | context.i = 0; 287 | context.out = out; 288 | context.level = level; 289 | avl_tree_for_each_node(value->_data._map_array,&context,avl_tree_for_each_node_dump_array); 290 | } 291 | 292 | if(!compact){ 293 | add_blank(out,4 * level); 294 | } 295 | buffer_append(out,"]",1); 296 | } 297 | break; 298 | 299 | default: 300 | //不可达 301 | assert(0); 302 | break; 303 | } 304 | 305 | return 0; 306 | } 307 | 308 | int tinybuf_value_serialize_as_json(const tinybuf_value *value, buffer *out,int compact){ 309 | return tinybuf_value_serialize_as_json_level(0,compact,value, out); 310 | } 311 | 312 | 313 | //////////////////////////////////////json解析相关////////////////////////////////////// 314 | /** 315 | * 判断是否为空字符 316 | * @param ch 字符 317 | * @return 1代表是空字符 318 | */ 319 | static inline int is_blank(uint8_t ch){ 320 | switch (ch){ 321 | case ' ': 322 | case '\t': 323 | case '\n': 324 | case '\r': 325 | return 1; 326 | default: 327 | return 0; 328 | } 329 | } 330 | 331 | 332 | /** 333 | * 查找相应的字符 334 | * @param ptr json字符串 335 | * @param size json字符串长度 336 | * @param str 查找字符集 337 | * @return 如果大于0,则代表找到了相关字节并返回消耗的字节数,0代表未找到,-1代表出现非法字符 338 | */ 339 | static inline int tinybuf_json_skip_for_simpe(const char *ptr, int size,const char *str,int show_waring){ 340 | int i , j; 341 | int str_len = strlen(str); 342 | for(i = 0 ; i < size ; ++i){ 343 | uint8_t ch = ((uint8_t *)ptr)[i]; 344 | 345 | if(is_blank(ch)){ 346 | //空白忽略之 347 | continue; 348 | } 349 | 350 | for(j = 0; j < str_len ; ++j){ 351 | if(ch == str[j]){ 352 | //消耗了这么多字节 353 | return i + 1; 354 | } 355 | } 356 | 357 | if(show_waring){ 358 | LOGW("搜索%s时发现非法字符:%c",str,ch); 359 | } 360 | //非法字符 361 | return -1; 362 | } 363 | 364 | //全部都是空白,未找到 365 | return 0; 366 | } 367 | 368 | /** 369 | * 查找相应的字符 370 | * @param ptr json字符串 371 | * @param size json字符串长度 372 | * @param str 查找字符集 373 | * @return 如果大于0,则代表找到了相关字节并返回消耗的字节数,0代表未找到,-1代表出现非法字符 374 | */ 375 | static inline int tinybuf_json_skip_for(const char *ptr, int size,const char *str,int show_waring){ 376 | const char *str_ptr = str; 377 | char flags[0xFF] = {0}; 378 | while(*str_ptr){ 379 | flags[*(str_ptr++)] = 1; 380 | } 381 | 382 | int i; 383 | for(i = 0 ; i < size ; ++i){ 384 | uint8_t ch = ((uint8_t *)ptr)[i]; 385 | 386 | if(is_blank(ch)){ 387 | //空白忽略之 388 | continue; 389 | } 390 | 391 | if(flags[ch]){ 392 | //消耗了这么多字节 393 | return i + 1; 394 | } 395 | 396 | if(show_waring){ 397 | LOGW("搜索%s时发现非法字符:%c",str,ch); 398 | } 399 | //非法字符 400 | return -1; 401 | } 402 | 403 | //全部都是空白,未找到 404 | return 0; 405 | } 406 | 407 | static char s_flags[0xFF] = {0}; 408 | static char s_flags_ok = 0; 409 | 410 | static inline int tinybuf_json_skip_for_complex(const char *ptr, int size,const char *str,int show_waring){ 411 | if(!s_flags_ok){ 412 | const char *str_ptr = str; 413 | while(*str_ptr){ 414 | s_flags[*(str_ptr++)] = 1; 415 | } 416 | s_flags_ok = 1; 417 | } 418 | 419 | 420 | int i; 421 | for(i = 0 ; i < size ; ++i){ 422 | uint8_t ch = ((uint8_t *)ptr)[i]; 423 | 424 | if(is_blank(ch)){ 425 | //空白忽略之 426 | continue; 427 | } 428 | 429 | if(s_flags[ch]){ 430 | //消耗了这么多字节 431 | return i + 1; 432 | } 433 | 434 | if(show_waring){ 435 | LOGW("搜索%s时发现非法字符:%c",str,ch); 436 | } 437 | //非法字符 438 | return -1; 439 | } 440 | 441 | //全部都是空白,未找到 442 | return 0; 443 | } 444 | 445 | /** 446 | * 解析Unicode字符 447 | * @param start json字符串 448 | * @param unicode unicode值 449 | * @return 0代表成功,-1代表失败 450 | */ 451 | static int decodeUnicodeEscapeSequence(const char *start,unsigned int* unicode){ 452 | *unicode = 0; 453 | int index; 454 | for ( index = 0; index < 4; ++index) { 455 | char c = *(start++); 456 | //左移动4位 457 | (*unicode) <<= 4; 458 | if (c >= '0' && c <= '9') 459 | (*unicode) += c - '0'; 460 | else if (c >= 'a' && c <= 'f') 461 | (*unicode) += c - 'a' + 10; 462 | else if (c >= 'A' && c <= 'F') 463 | (*unicode) += c - 'A' + 10; 464 | else{ 465 | //出现非法字符 466 | LOGW("Unicode中出现非法字符:%c",c); 467 | return -1; 468 | } 469 | } 470 | return 0; 471 | } 472 | 473 | /** 474 | * Unicode转utf-8 475 | * @param cp unicode字符 476 | * @param out utf-8字符串 477 | */ 478 | static inline void codePointToUTF8(unsigned int cp,buffer *out) { 479 | // based on description from http://en.wikipedia.org/wiki/UTF-8 480 | if (cp <= 0x7f) { 481 | buffer_push_inline(out,(char)cp); 482 | } else if (cp <= 0x7FF) { 483 | buffer_push_inline(out,(char)(0xC0 | (0x1f & (cp >> 6)))); 484 | buffer_push_inline(out,(char)(0x80 | (0x3f & cp))); 485 | } else if (cp <= 0xFFFF) { 486 | buffer_push_inline(out,(char)(0xE0 | (0xf & (cp >> 12)))); 487 | buffer_push_inline(out,(char)(0x80 | (0x3f & (cp >> 6)))); 488 | buffer_push_inline(out,(char)(0x80 | (0x3f & cp))); 489 | } else if (cp <= 0x10FFFF) { 490 | buffer_push_inline(out,(char)(0xF0 | (0x7 & (cp >> 18)))); 491 | buffer_push_inline(out,(char)(0x80 | (0x3f & (cp >> 12)))); 492 | buffer_push_inline(out,(char)(0x80 | (0x3f & (cp >> 6)))); 493 | buffer_push_inline(out,(char)(0x80 | (0x3f & cp))); 494 | } 495 | } 496 | 497 | /** 498 | * 读取两个字节的Unicode 499 | * @param ptr json字符串 500 | * @param size json字符串长度 501 | * @param unicode Unicode值 502 | * @return 消耗的字节数 503 | */ 504 | static inline int tinybuf_load_unicode_once(const char *ptr, int size,unsigned int *unicode){ 505 | if(size < 6){ 506 | //字节不够 507 | return 0; 508 | } 509 | if(ptr[0] != '\\' || ptr[1] != 'u'){ 510 | //非法字符 511 | LOGW("非法Unicode起始字符:%c%c",ptr[0],ptr[1]); 512 | return -1; 513 | } 514 | 515 | return -1 == decodeUnicodeEscapeSequence(ptr + 2,unicode) ? -1 : 6; 516 | } 517 | 518 | /** 519 | * 加载Unicode字符串 520 | * @param ptr json字符串 521 | * @param size json字符串长度 522 | * @param out 还原后的字符串保存长度 523 | * @return 消耗的字节数 524 | */ 525 | static inline int tinybuf_load_unicode(const char *ptr, int size,buffer *out){ 526 | unsigned int unicode; 527 | int ret1 = tinybuf_load_unicode_once(ptr,size,&unicode); 528 | if(ret1 <= 0){ 529 | //字节不够或解析失败 530 | return ret1; 531 | } 532 | if (unicode >= 0xD800 && unicode <= 0xDBFF) { 533 | // surrogate pairs 534 | unsigned int surrogatePair; 535 | int ret2 = tinybuf_load_unicode_once(ptr + ret1,size - ret1,&surrogatePair); 536 | if(ret2 <= 0){ 537 | //字节不够或解析失败 538 | return ret2; 539 | } 540 | unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); 541 | ret1 += ret2; 542 | } 543 | 544 | codePointToUTF8(unicode,out); 545 | return ret1; 546 | } 547 | 548 | /** 549 | * 加载字符串 550 | * @param ptr json字符串 551 | * @param size json字符串长度 552 | * @param out 转义后的字符串 553 | * @return 消耗的字节数 554 | */ 555 | static inline int tinybuf_json_load_for_string(const char *ptr, int size,buffer *out){ 556 | int consumed = tinybuf_json_skip_for_simpe(ptr,size,"\"",1); 557 | if(consumed <= 0){ 558 | //出现非法字符或未找到 559 | return consumed; 560 | } 561 | 562 | //是否开始转义 563 | int escaped_start = 0; 564 | int i; 565 | for(i = consumed; i < size ; ++i){ 566 | uint8_t c = ((uint8_t*)ptr)[i]; 567 | if(escaped_start){ 568 | //开始转义了 569 | switch (c){ 570 | case 'u': { 571 | //上个字节是转义字符,那个是\u加4个字节的二进制 572 | int offset = tinybuf_load_unicode(ptr + i - 1, size - i - 1, out); 573 | if (offset <= 0) { 574 | //加载Unicode失败回滚数据 575 | return offset; 576 | } 577 | i += (offset - 2); 578 | } 579 | break; 580 | 581 | case '\"': 582 | case '\\': 583 | buffer_push_inline(out,c); 584 | break; 585 | 586 | case 'b': 587 | buffer_push_inline(out,'\b'); 588 | break; 589 | 590 | case 'f': 591 | buffer_push_inline(out,'\f'); 592 | break; 593 | 594 | case 'n': 595 | buffer_push_inline(out,'\n'); 596 | break; 597 | 598 | case 'r': 599 | buffer_push_inline(out,'\r'); 600 | break; 601 | 602 | case 't': 603 | buffer_push_inline(out,'\t'); 604 | break; 605 | 606 | default: 607 | //转义字符后面出现非法字符 608 | LOGW("转义字符后面出现非法字符:%c",c); 609 | return -1; 610 | } 611 | 612 | //转义结束 613 | escaped_start = 0; 614 | continue; 615 | } 616 | 617 | switch (c){ 618 | case '\"': 619 | //这是个引号,字符串结束了 620 | return i + 1; 621 | 622 | case '\\': 623 | //开始转义 624 | escaped_start = 1; 625 | break; 626 | 627 | case '\b': 628 | case '\f': 629 | case '\n': 630 | case '\r': 631 | case '\t': 632 | //这些字符在string中必须转义 633 | LOGD("string中发现未转义的字符:%c",c); 634 | return -1; 635 | default: 636 | if (isControlCharacter(c) || c == 0) { 637 | //这些字符必须转义 638 | LOGD("string中发现未转义的字符:%c",c); 639 | return -1; 640 | } 641 | buffer_push_inline(out,c); 642 | break; 643 | } 644 | } 645 | 646 | //数据不够,回滚为0 647 | return 0; 648 | } 649 | 650 | /** 651 | * 加载bool值 652 | * @param ptr json字符串 653 | * @param size json字符串长度 654 | * @param out bool值 655 | * @return 消耗的字节数 656 | */ 657 | static inline int tinybuf_json_load_for_bool(const char *ptr, int size,int *out){ 658 | switch (ptr[0]){ 659 | case 't': 660 | if(size < 4){ 661 | //数据不够 662 | return 0; 663 | } 664 | if(memcmp(ptr,"true",4) == 0){ 665 | *out = 1; 666 | return 4; 667 | } 668 | LOGW("判断bool true失败:%4s",ptr); 669 | return -1; 670 | 671 | case 'f': 672 | if(size < 5){ 673 | //数据不够 674 | return 0; 675 | } 676 | if(memcmp(ptr,"false",5) == 0){ 677 | *out = 0; 678 | return 5; 679 | } 680 | LOGW("判断bool false失败:%5s",ptr); 681 | return -1; 682 | 683 | default: 684 | return -1; 685 | } 686 | } 687 | 688 | /** 689 | * 加载null值 690 | * @param ptr json字符串 691 | * @param size json字符串长度 692 | * @return 消耗的字节数 693 | */ 694 | static inline int tinybuf_json_load_for_null(const char *ptr, int size){ 695 | switch (ptr[0]){ 696 | case 'n': 697 | if(size < 4){ 698 | //数据不够 699 | return 0; 700 | } 701 | if(memcmp(ptr,"null",4) == 0){ 702 | //解析成功 703 | return 4; 704 | } 705 | return -1; 706 | default: 707 | return -1; 708 | } 709 | } 710 | 711 | /** 712 | * 判断value类型 713 | * @param ptr json字符串 714 | * @param size json字符串长度 715 | * @param type value类型 716 | * @return 消耗的字节数 717 | */ 718 | static inline int tinybuf_json_load_for_value_type(const char *ptr, int size, tinybuf_type *type,int show_waring){ 719 | //搜索map/array/number/string/bool/null 720 | int consumed = tinybuf_json_skip_for_complex(ptr,size,"{[-0123456789\"ftn",show_waring); 721 | if(consumed <= 0){ 722 | //未找到或出现非法字符 723 | return consumed; 724 | } 725 | 726 | switch (ptr[consumed - 1]){ 727 | case '{': 728 | *type = tinybuf_map; 729 | break; 730 | 731 | case '[': 732 | *type = tinybuf_array; 733 | break; 734 | 735 | case '\"': 736 | *type = tinybuf_string; 737 | break; 738 | 739 | case 't': 740 | case 'f': 741 | *type = tinybuf_bool; 742 | break; 743 | 744 | case 'n': 745 | *type = tinybuf_null; 746 | break; 747 | 748 | case '-': 749 | case '0': 750 | case '1': 751 | case '2': 752 | case '3': 753 | case '4': 754 | case '5': 755 | case '6': 756 | case '7': 757 | case '8': 758 | case '9': 759 | //double和int都共享tinybuf_int类型 760 | *type = tinybuf_int; 761 | break; 762 | 763 | default: 764 | assert(0); 765 | return -1; 766 | } 767 | 768 | return consumed; 769 | } 770 | 771 | 772 | /** 773 | * 加载map 774 | * @param ptr json字符串 775 | * @param size json字符串大小 776 | * @param map 返回值 777 | * @return 消耗字节数 778 | */ 779 | static inline int tinybuf_json_load_for_map(const char *ptr, int size, tinybuf_value *map){ 780 | int total_consumed = 0; 781 | while (1) { 782 | //搜索string key或map结尾符 783 | int consumed = tinybuf_json_skip_for_simpe(ptr + total_consumed, size - total_consumed, "\"}",1); 784 | if (consumed <= 0) { 785 | //数据不够或找到非法字符 786 | return consumed; 787 | } 788 | 789 | //加上string key前面字节偏移量 790 | total_consumed += consumed - 1; 791 | 792 | if (ptr[total_consumed] == '}') { 793 | //这个是map结尾,说明map结束了 794 | return total_consumed + 1; 795 | } 796 | 797 | //这个是string key 798 | buffer *key = buffer_alloc(); 799 | 800 | //加载string类型的key 801 | consumed = tinybuf_json_load_for_string(ptr + total_consumed, size - total_consumed, key); 802 | if (consumed <= 0) { 803 | //未找到key,数据不够或出现非法字符 804 | buffer_free(key); 805 | return consumed; 806 | } 807 | 808 | //加上string key的偏移量 809 | total_consumed += consumed; 810 | 811 | //找到key了,下一步找冒号 812 | consumed = tinybuf_json_skip_for_simpe(ptr + total_consumed, size - total_consumed, ":",1); 813 | if (consumed <= 0) { 814 | //未找到冒号 815 | buffer_free(key); 816 | return consumed; 817 | } 818 | 819 | //加上冒号偏移量 820 | total_consumed += consumed; 821 | 822 | tinybuf_value *value = tinybuf_value_alloc(); 823 | consumed = tinybuf_value_deserialize_from_json(ptr + total_consumed, size - total_consumed, value); 824 | if (consumed <= 0) { 825 | //数据不够或出现非法字符 826 | buffer_free(key); 827 | tinybuf_value_free(value); 828 | return consumed; 829 | } 830 | 831 | //加上value的偏移量 832 | total_consumed += consumed; 833 | 834 | //保存key-value键值对 835 | tinybuf_value_map_set2(map, key, value); 836 | 837 | //搜索逗号或结尾符号 838 | consumed = tinybuf_json_skip_for_simpe(ptr + total_consumed, size - total_consumed, ",}",1); 839 | if (consumed <= 0) { 840 | //未找到了逗号和map结尾符号 841 | return consumed; 842 | } 843 | 844 | //加上偏移量 845 | total_consumed += consumed; 846 | if(ptr[total_consumed - 1] == '}'){ 847 | //找到map结尾 848 | return total_consumed; 849 | } 850 | 851 | //还有下一个对象 852 | } 853 | } 854 | 855 | static inline int tinybuf_value_deserialize_from_json_l(const char *ptr, int size, tinybuf_value *out,int show_waring); 856 | 857 | /** 858 | * 从json中加载array 859 | * @param ptr json字符串 860 | * @param size json字符串长度 861 | * @param array 数组 862 | * @return 消耗字节数 863 | */ 864 | static inline int tinybuf_json_load_for_array(const char *ptr, int size, tinybuf_value *array){ 865 | int total_consumed = 0; 866 | while (1) { 867 | //搜索子对象 868 | tinybuf_value *child = tinybuf_value_alloc(); 869 | int consumed = tinybuf_value_deserialize_from_json_l(ptr + total_consumed, size - total_consumed, child,0); 870 | if (consumed <= 0) { 871 | //未找到子对象 872 | if (consumed == -1) { 873 | //非法字符,那么尝试查找array的末尾 874 | consumed = tinybuf_json_skip_for_simpe(ptr + total_consumed, size - total_consumed, "]",1); 875 | if (consumed <= 0) { 876 | //数据不够或找到非法字符 877 | tinybuf_value_free(child); 878 | return consumed; 879 | } 880 | //找到arrary的末尾 881 | tinybuf_value_free(child); 882 | return total_consumed + consumed; 883 | } 884 | //数据不够 885 | tinybuf_value_free(child); 886 | return consumed; 887 | } 888 | 889 | //加上子对象的偏移量 890 | total_consumed += consumed; 891 | //保存子对象 892 | tinybuf_value_array_append(array, child); 893 | 894 | //查找逗号或array结尾符号 895 | consumed = tinybuf_json_skip_for_simpe(ptr + total_consumed, size - total_consumed, ",]",1); 896 | if (consumed <= 0) { 897 | //未找到了逗号和array结尾符号 898 | return consumed; 899 | } 900 | 901 | //加上偏移量 902 | total_consumed += consumed; 903 | if(ptr[total_consumed - 1] == ']'){ 904 | //找到array结尾 905 | return total_consumed; 906 | } 907 | //还有下一个对象 908 | } 909 | } 910 | 911 | static int scanf_int(const char *str,int str_len,int64_t *out){ 912 | int is_negtive = 0; 913 | *out = 0; 914 | int i; 915 | for(i = 0; i < str_len; ++i){ 916 | if(i == 0 && str[i] == '-'){ 917 | is_negtive = 1; 918 | continue; 919 | } 920 | char c = str[i]; 921 | if (c < '0' || c > '9'){ 922 | return -1; 923 | } 924 | *out = 10 * (*out) + (c - '0'); 925 | } 926 | if(is_negtive){ 927 | *out = -*out; 928 | } 929 | return 0; 930 | } 931 | 932 | /** 933 | * 加载double或int型数据 934 | * @param ptr json字符串 935 | * @param size json字符串长度 936 | * @param number 返回的数据对象 937 | * @return 消耗字节数 938 | */ 939 | static inline int tinybuf_json_load_for_number(const char *ptr, int size, tinybuf_value *number){ 940 | char *p = (char*)ptr; 941 | const char *end = ptr + size; 942 | int is_double = 0; 943 | 944 | char c = *(++p); // stopgap for already consumed character 945 | // integral part 946 | while (c >= '0' && c <= '9'){ 947 | c = p < end ? *(++p) : 0; 948 | } 949 | 950 | // fractional part 951 | if (c == '.') { 952 | is_double = 1; 953 | c = p < end ? *(++p) : 0; 954 | while (c >= '0' && c <= '9'){ 955 | c = p < end ? *(++p) : 0; 956 | } 957 | } 958 | // exponential part 959 | if (c == 'e' || c == 'E') { 960 | is_double = 1; 961 | c = p < end ? *(++p) : 0; 962 | if (c == '+' || c == '-') 963 | c = p < end ? *(++p) : 0; 964 | while (c >= '0' && c <= '9'){ 965 | c = p < end ? *(++p) : 0; 966 | } 967 | } 968 | 969 | 970 | if(!is_double){ 971 | //这是int 972 | int64_t int_val; 973 | if(-1 == scanf_int(ptr,p - ptr,&int_val)){ 974 | return -1; 975 | } 976 | tinybuf_value_init_int(number, int_val); 977 | return p - ptr; 978 | } 979 | 980 | //这是double 981 | //确保最后一个字节为'\0' 982 | buffer *buf = buffer_alloc(); 983 | buffer_assign(buf,ptr,p - ptr); 984 | tinybuf_value_init_double(number, atof(buffer_get_data_inline(buf))); 985 | buffer_free(buf); 986 | return p - ptr; 987 | } 988 | 989 | 990 | /** 991 | * 加载value部分 992 | * @param ptr json字符串 993 | * @param size json字符串长度 994 | * @param out vlue值输出 995 | * @return 消耗的字节数 996 | */ 997 | int tinybuf_value_deserialize_from_json(const char *ptr, int size, tinybuf_value *out){ 998 | return tinybuf_value_deserialize_from_json_l(ptr,size,out,1); 999 | } 1000 | 1001 | static int tinybuf_value_deserialize_from_json_l(const char *ptr, int size, tinybuf_value *out,int show_waring){ 1002 | assert(out->_type == tinybuf_null); 1003 | tinybuf_type type; 1004 | int total_consumed = tinybuf_json_load_for_value_type(ptr,size,&type,show_waring); 1005 | if(total_consumed <= 0){ 1006 | //数据不够或解析失败 1007 | return total_consumed; 1008 | } 1009 | 1010 | switch (type){ 1011 | case tinybuf_map: { 1012 | int consumed = tinybuf_json_load_for_map(ptr + total_consumed,size - total_consumed,out); 1013 | if(consumed <= 0){ 1014 | //数据不够或出现非法字符 1015 | tinybuf_value_clear(out); 1016 | return consumed; 1017 | } 1018 | //设置为map类型,防止空map时未设置类型 1019 | out->_type = tinybuf_map; 1020 | return total_consumed + consumed; 1021 | } 1022 | 1023 | case tinybuf_array: { 1024 | int consumed = tinybuf_json_load_for_array(ptr + total_consumed, size - total_consumed, out); 1025 | if (consumed <= 0) { 1026 | //数据不够或出现非法字符 1027 | tinybuf_value_clear(out); 1028 | return consumed; 1029 | } 1030 | //设置为array类型,防止空array时未设置类型 1031 | out->_type = tinybuf_array; 1032 | return total_consumed + consumed; 1033 | } 1034 | 1035 | case tinybuf_string: { 1036 | //string必须从双引号开始 1037 | total_consumed -= 1; 1038 | buffer *str = buffer_alloc(); 1039 | int consumed = tinybuf_json_load_for_string(ptr + total_consumed, size - total_consumed, str); 1040 | if (consumed <= 0) { 1041 | //数据不够或出现非法字符 1042 | buffer_free(str); 1043 | return consumed; 1044 | } 1045 | 1046 | tinybuf_value_init_string2(out,str); 1047 | return total_consumed + consumed; 1048 | } 1049 | 1050 | case tinybuf_bool: { 1051 | //bool必须从true或false第一个字节开始 1052 | total_consumed -= 1; 1053 | int flag; 1054 | int consumed = tinybuf_json_load_for_bool(ptr + total_consumed, size - total_consumed, &flag); 1055 | if (consumed <= 0) { 1056 | //数据不够或出现非法字符 1057 | return consumed; 1058 | } 1059 | //设置value 1060 | tinybuf_value_init_bool(out, flag); 1061 | return total_consumed + consumed; 1062 | 1063 | } 1064 | 1065 | case tinybuf_int: { 1066 | //number必须从第一个字节开始 1067 | total_consumed -= 1; 1068 | int consumed = tinybuf_json_load_for_number(ptr + total_consumed, size - total_consumed, out); 1069 | if (consumed <= 0) { 1070 | //数据不够或出现非法字符 1071 | return consumed; 1072 | } 1073 | return total_consumed + consumed; 1074 | } 1075 | 1076 | case tinybuf_null: { 1077 | //null必须从第一个字节开始 1078 | total_consumed -= 1; 1079 | int consumed = tinybuf_json_load_for_null(ptr + total_consumed, size - total_consumed); 1080 | if (consumed <= 0) { 1081 | //数据不够或出现非法字符 1082 | return consumed; 1083 | } 1084 | 1085 | //设置value为null 1086 | tinybuf_value_clear(out); 1087 | return total_consumed + consumed; 1088 | } 1089 | 1090 | default: 1091 | assert(0); 1092 | return -1; 1093 | } 1094 | } 1095 | 1096 | --------------------------------------------------------------------------------