├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── Test.hpp ├── kapok ├── Common.hpp ├── DeSerializer.hpp ├── JsonUtil.hpp ├── Kapok.hpp ├── Serializer.hpp └── traits.hpp ├── main.cpp ├── rapidjson ├── allocators.h ├── document.h ├── encodedstream.h ├── encodings.h ├── error │ ├── en.h │ └── error.h ├── filereadstream.h ├── filestream.h ├── filewritestream.h ├── fwd.h ├── internal │ ├── biginteger.h │ ├── diyfp.h │ ├── dtoa.h │ ├── ieee754.h │ ├── itoa.h │ ├── meta.h │ ├── pow10.h │ ├── regex.h │ ├── stack.h │ ├── strfunc.h │ ├── strtod.h │ └── swap.h ├── istreamwrapper.h ├── memorybuffer.h ├── memorystream.h ├── msinttypes │ ├── inttypes.h │ └── stdint.h ├── ostreamwrapper.h ├── pointer.h ├── prettywriter.h ├── rapidjson.h ├── reader.h ├── schema.h ├── stream.h ├── stringbuffer.h └── writer.h ├── test ├── CMakeLists.txt ├── UnitTest.hpp ├── panic.cpp ├── primitive.cpp ├── stl.cpp └── user.cpp ├── test_kapok.hpp ├── test_performance.cpp ├── unit_test.hpp └── vcproject ├── vcproject.sln └── vcproject └── vcproject.vcxproj /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "fmt"] 2 | path = fmt 3 | url = https://github.com/fmtlib/fmt.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(kapok) 4 | add_definitions(-DFMT_HEADER_ONLY) 5 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") 7 | 8 | if (CMAKE_BUILD_TYPE STREQUAL Debug) 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_DEBUG") 10 | #add_definitions( 11 | # -D_DEBUG 12 | #) 13 | endif () 14 | 15 | find_package(Boost REQUIRED) 16 | include_directories(${Boost_INCLUDE_DIRS}) 17 | 18 | SET(EXTRA_LIBS ${EXTRA_LIBS} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) 19 | 20 | include_directories( 21 | ${PROJECT_SOURCE_DIR} 22 | ${CMAKE_CURRENT_SOURCE_DIR}/fmt 23 | ) 24 | 25 | set(SOURCE_FILES 26 | main.cpp 27 | test/panic.cpp 28 | test/primitive.cpp 29 | test/stl.cpp 30 | test/user.cpp 31 | ) 32 | 33 | install(DIRECTORY ${PROJECT_SOURCE_DIR}/kapok/ DESTINATION "include/kapok" FILES_MATCHING PATTERN "*.hpp") 34 | 35 | add_executable(kapok ${SOURCE_FILES}) 36 | target_link_libraries(kapok ${EXTRA_LIBS}) 37 | 38 | #install(FILES src/cloud_backup.ini DESTINATION "${PROJECT_BINARY_DIR}/") 39 | 40 | #################################### 41 | # test 42 | 43 | # enable_testing() 44 | # add_test(fundation_test_run fundation_test) 45 | # set_tests_properties (fundation_test_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") 46 | 47 | # add_test(get_object_summary_test_run get_object_summary_test) 48 | # set_tests_properties (get_object_summary_test_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") 49 | 50 | # add_test(list_object_summary_test_run list_object_summary_test) 51 | # set_tests_properties (list_object_summary_test_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") 52 | 53 | # add_test(test_backup_status_run test_backup_status) 54 | # set_tests_properties (test_backup_status_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") 55 | 56 | # add_test(test_kv_store_run test_kv_store) 57 | # set_tests_properties (test_kv_store_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") 58 | 59 | # add_test(test_kv_traverse_delete_run test_kv_traverse_delete) 60 | # set_tests_properties (test_kv_traverse_delete_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") 61 | 62 | # add_test(test_thread_pool_run test_thread_pool) 63 | 64 | # add_test(test_scribe_load_balance_run test_scribe_load_balance) 65 | 66 | 67 | include (InstallRequiredSystemLibraries) 68 | set (CPACK_PACKAGE_VERSION_MAJOR "1") 69 | set (CPACK_PACKAGE_VERSION_MINOR "0") 70 | SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "David Doria") 71 | include (CPack) 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kapok 2 | 现在请使用更好的序列化引擎iguana,比kapok更高效,本项目也不再维护,后面只维护iguana。 3 | 更好的序列化库,纯c++14开发,header-only,简洁高效。 4 | 5 | Kapok---一个更好的序列化/反序列化库 6 | 7 | 可以很方便的将对象序列化和反序列化,序列化后的格式是标准的json格式。 8 | 9 | wiki介绍:https://github.com/qicosmos/Kapok/wiki 10 | 社区:http://purecpp.cn/ 11 | 12 | 13 | Now there is a better serialization libray:https://github.com/qicosmos/iguana please replace kapok with iguana. 14 | -------------------------------------------------------------------------------- /Test.hpp: -------------------------------------------------------------------------------- 1 | #include "kapok/Kapok.hpp" 2 | 3 | void Performance() 4 | { 5 | kapok::Serializer sr; 6 | kapok::DeSerializer dr; 7 | 8 | auto tp = std::make_tuple(10, 12, string("test")); 9 | Timer t; 10 | for (size_t i = 0; i < 10000; i++) 11 | { 12 | sr.Serialize(tp, "tuple"); 13 | dr.Parse(sr.GetString()); 14 | std::tuple p; 15 | dr.Deserialize(p, "tuple"); 16 | } 17 | 18 | int64_t elapsed = t.elapsed(); 19 | std::cout << "kapok: " << elapsed <<"ms"<< std::endl; 20 | } 21 | -------------------------------------------------------------------------------- /kapok/Common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace kapok { 7 | template 8 | std::array split(const std::string& s, const char delimiter) 9 | { 10 | size_t start = 0; 11 | size_t end = s.find_first_of(delimiter); 12 | 13 | std::array output; 14 | 15 | size_t i = 0; 16 | while (end <= std::string::npos) 17 | { 18 | output[i++] = std::move(s.substr(start, end - start)); 19 | if (end == std::string::npos) 20 | break; 21 | 22 | start = end + 2; 23 | end = s.find_first_of(delimiter, start); 24 | } 25 | 26 | return output; 27 | } 28 | 29 | template 30 | static inline auto make(const std::array&ar, unsigned index, T const & t, T1& args) 31 | { 32 | return std::tuple_cat(t, std::make_tuple(std::pair(ar[index], args))); 33 | } 34 | 35 | template 36 | static inline auto make(const std::array&ar, unsigned index, T const & t, T1& first, Args&... args) 37 | { 38 | return make(ar, index + 1, std::tuple_cat(t, std::make_tuple(std::pair(ar[index], first))), args...); 39 | } 40 | 41 | #define VA_ARGS_NUM(...) std::tuple_size::value 42 | 43 | //#define META(...) auto Meta(){\ 44 | // auto ar = split(#__VA_ARGS__, ',');\ 45 | // return make(ar, 0, std::tuple<>(), __VA_ARGS__);\ 46 | //} 47 | 48 | /******************************************/ 49 | #define MARCO_EXPAND(...) __VA_ARGS__ 50 | #define APPLY_VARIADIC_MACRO(macro, ...) MARCO_EXPAND(macro(__VA_ARGS__)) 51 | 52 | #define ADD_REFERENCE(t) std::reference_wrapper(t) 53 | #define ADD_REFERENCE_CONST(t) std::reference_wrapper>(t) 54 | #define PAIR_OBJECT(t) std::make_pair(#t, ADD_REFERENCE(t)) 55 | #define PAIR_OBJECT_CONST(t) std::make_pair(#t, ADD_REFERENCE_CONST(t)) 56 | #define MAKE_TUPLE(...) auto Meta() { return std::make_tuple(__VA_ARGS__); } 57 | #define MAKE_TUPLE_CONST(...) auto Meta() const { return std::make_tuple(__VA_ARGS__); } 58 | 59 | /* arg list expand macro, now support 40 args */ 60 | #define MAKE_ARG_LIST_1(op, arg, ...) op(arg) 61 | #define MAKE_ARG_LIST_2(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_1(op, __VA_ARGS__)) 62 | #define MAKE_ARG_LIST_3(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_2(op, __VA_ARGS__)) 63 | #define MAKE_ARG_LIST_4(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_3(op, __VA_ARGS__)) 64 | #define MAKE_ARG_LIST_5(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_4(op, __VA_ARGS__)) 65 | #define MAKE_ARG_LIST_6(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_5(op, __VA_ARGS__)) 66 | #define MAKE_ARG_LIST_7(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_6(op, __VA_ARGS__)) 67 | #define MAKE_ARG_LIST_8(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_7(op, __VA_ARGS__)) 68 | #define MAKE_ARG_LIST_9(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_8(op, __VA_ARGS__)) 69 | #define MAKE_ARG_LIST_10(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_9(op, __VA_ARGS__)) 70 | #define MAKE_ARG_LIST_11(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_10(op, __VA_ARGS__)) 71 | #define MAKE_ARG_LIST_12(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_11(op, __VA_ARGS__)) 72 | #define MAKE_ARG_LIST_13(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_12(op, __VA_ARGS__)) 73 | #define MAKE_ARG_LIST_14(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_13(op, __VA_ARGS__)) 74 | #define MAKE_ARG_LIST_15(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_14(op, __VA_ARGS__)) 75 | #define MAKE_ARG_LIST_16(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_15(op, __VA_ARGS__)) 76 | #define MAKE_ARG_LIST_17(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_16(op, __VA_ARGS__)) 77 | #define MAKE_ARG_LIST_18(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_17(op, __VA_ARGS__)) 78 | #define MAKE_ARG_LIST_19(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_18(op, __VA_ARGS__)) 79 | #define MAKE_ARG_LIST_20(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_19(op, __VA_ARGS__)) 80 | #define MAKE_ARG_LIST_21(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_20(op, __VA_ARGS__)) 81 | #define MAKE_ARG_LIST_22(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_21(op, __VA_ARGS__)) 82 | #define MAKE_ARG_LIST_23(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_22(op, __VA_ARGS__)) 83 | #define MAKE_ARG_LIST_24(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_23(op, __VA_ARGS__)) 84 | #define MAKE_ARG_LIST_25(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_24(op, __VA_ARGS__)) 85 | #define MAKE_ARG_LIST_26(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_25(op, __VA_ARGS__)) 86 | #define MAKE_ARG_LIST_27(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_26(op, __VA_ARGS__)) 87 | #define MAKE_ARG_LIST_28(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_27(op, __VA_ARGS__)) 88 | #define MAKE_ARG_LIST_29(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_28(op, __VA_ARGS__)) 89 | #define MAKE_ARG_LIST_30(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_29(op, __VA_ARGS__)) 90 | #define MAKE_ARG_LIST_31(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_30(op, __VA_ARGS__)) 91 | #define MAKE_ARG_LIST_32(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_31(op, __VA_ARGS__)) 92 | #define MAKE_ARG_LIST_33(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_32(op, __VA_ARGS__)) 93 | #define MAKE_ARG_LIST_34(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_33(op, __VA_ARGS__)) 94 | #define MAKE_ARG_LIST_35(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_34(op, __VA_ARGS__)) 95 | #define MAKE_ARG_LIST_36(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_35(op, __VA_ARGS__)) 96 | #define MAKE_ARG_LIST_37(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_36(op, __VA_ARGS__)) 97 | #define MAKE_ARG_LIST_38(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_37(op, __VA_ARGS__)) 98 | #define MAKE_ARG_LIST_39(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_38(op, __VA_ARGS__)) 99 | #define MAKE_ARG_LIST_40(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_39(op, __VA_ARGS__)) 100 | 101 | /* emmbed marco, using EMMBED_TUPLE(5 , a, b, c, d, e) */ 102 | //note use MACRO_CONCAT like A##_##B direct may cause marco expand error 103 | #define MACRO_CONCAT(A, B) MACRO_CONCAT1(A, B) 104 | #define MACRO_CONCAT1(A, B) A##_##B 105 | 106 | #define MAKE_ARG_LIST(N, op, arg, ...) \ 107 | MACRO_CONCAT(MAKE_ARG_LIST, N)(op, arg, __VA_ARGS__) 108 | 109 | #define EMMBED_TUPLE(N, ...) \ 110 | MAKE_TUPLE(MAKE_ARG_LIST(N, PAIR_OBJECT, __VA_ARGS__)) \ 111 | MAKE_TUPLE_CONST(MAKE_ARG_LIST(N, PAIR_OBJECT_CONST, __VA_ARGS__)) 112 | 113 | #define RSEQ_N() \ 114 | 119,118,117,116,115,114,113,112,111,110,\ 115 | 109,108,107,106,105,104,103,102,101,100,\ 116 | 99,98,97,96,95,94,93,92,91,90, \ 117 | 89,88,87,86,85,84,83,82,81,80, \ 118 | 79,78,77,76,75,74,73,72,71,70, \ 119 | 69,68,67,66,65,64,63,62,61,60, \ 120 | 59,58,57,56,55,54,53,52,51,50, \ 121 | 49,48,47,46,45,44,43,42,41,40, \ 122 | 39,38,37,36,35,34,33,32,31,30, \ 123 | 29,28,27,26,25,24,23,22,21,20, \ 124 | 19,18,17,16,15,14,13,12,11,10, \ 125 | 9,8,7,6,5,4,3,2,1,0 126 | 127 | #define ARG_N( \ 128 | _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 129 | _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ 130 | _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ 131 | _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ 132 | _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ 133 | _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ 134 | _61,_62,_63,_64,_65,_66,_67,_68,_69,_70, \ 135 | _71,_72,_73,_74,_75,_76,_77,_78,_79,_80, \ 136 | _81,_82,_83,_84,_85,_86,_87,_88,_89,_90, \ 137 | _91,_92,_93,_94,_95,_96,_97,_98,_99,_100, \ 138 | _101,_102,_103,_104,_105,_106,_107,_108,_109,_110, \ 139 | _111,_112,_113,_114,_115,_116,_117,_118,_119,N, ...) N 140 | 141 | #define GET_ARG_COUNT_INNER(...) MARCO_EXPAND(ARG_N(__VA_ARGS__)) 142 | #define GET_ARG_COUNT(...) GET_ARG_COUNT_INNER(__VA_ARGS__, RSEQ_N()) 143 | 144 | #define META(...) EMMBED_TUPLE(GET_ARG_COUNT(__VA_ARGS__), __VA_ARGS__) 145 | /******************************************/ 146 | 147 | class NonCopyable 148 | { 149 | public: 150 | NonCopyable(const NonCopyable&) = delete; 151 | NonCopyable& operator = (const NonCopyable&) = delete; 152 | NonCopyable() = default; 153 | }; 154 | } // namespace kapok 155 | -------------------------------------------------------------------------------- /kapok/JsonUtil.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "rapidjson/writer.h" 5 | #include "rapidjson/stringbuffer.h" 6 | #include "rapidjson/document.h" 7 | 8 | #include "traits.hpp" 9 | #include "Common.hpp" 10 | 11 | namespace kapok { 12 | class JsonUtil : NonCopyable 13 | { 14 | typedef rapidjson::Writer JsonWriter; 15 | public: 16 | 17 | JsonUtil() : m_writer(m_buf) 18 | { 19 | } 20 | 21 | template 22 | void WriteJson(const char* key, T&& value) 23 | { 24 | m_writer.String(key); 25 | WriteValue(std::forward(value)); 26 | } 27 | 28 | template 29 | void WriteJson(const std::string& key, T&& value) 30 | { 31 | m_writer.String(key.c_str()); 32 | WriteValue(std::forward(value)); 33 | } 34 | 35 | void Reset() 36 | { 37 | m_writer.Reset(m_buf); 38 | m_buf.Clear(); 39 | } 40 | 41 | void StartObject() 42 | { 43 | m_writer.StartObject(); 44 | } 45 | 46 | void EndObject() 47 | { 48 | m_writer.EndObject(); 49 | } 50 | 51 | void StartArray() 52 | { 53 | m_writer.StartArray(); 54 | } 55 | 56 | void EndArray() 57 | { 58 | m_writer.EndArray(); 59 | } 60 | 61 | void WriteValue(const char* val) 62 | { 63 | if (val == nullptr) 64 | m_writer.Null(); 65 | else 66 | m_writer.String(val); 67 | } 68 | 69 | void ReadValue(char*& t, rapidjson::Value& val) 70 | { 71 | if (val.IsString()) 72 | t = (char*)val.GetString(); 73 | } 74 | 75 | void WriteValue(const std::string& val) 76 | { 77 | m_writer.String(val.c_str()); 78 | } 79 | 80 | void ReadValue(std::string& t, rapidjson::Value& val) 81 | { 82 | if(val.IsString()) 83 | t = val.GetString(); 84 | } 85 | 86 | void Parse(const char* json) 87 | { 88 | auto& r = m_doc.Parse<0>(json); 89 | if (r.HasParseError()) 90 | { 91 | throw std::invalid_argument("json string parse failed"); 92 | } 93 | } 94 | 95 | void Parse(const char* json, std::size_t length) 96 | { 97 | auto& r = m_doc.Parse<0>(json, length); 98 | if (r.HasParseError()) 99 | { 100 | throw std::invalid_argument("json string parse failed"); 101 | } 102 | } 103 | 104 | rapidjson::Document& GetDocument() 105 | { 106 | return m_doc; 107 | } 108 | 109 | void WriteValue(uint8_t val) 110 | { 111 | m_writer.Int(val); 112 | } 113 | 114 | void ReadValue(uint8_t& t, rapidjson::Value& val) 115 | { 116 | if (val.IsInt()) 117 | t = (uint8_t)val.GetInt(); 118 | } 119 | 120 | void WriteValue(int8_t val) 121 | { 122 | m_writer.Int(val); 123 | } 124 | 125 | void ReadValue(int8_t& t, rapidjson::Value& val) 126 | { 127 | if (val.IsInt()) 128 | t = (int8_t)val.GetInt(); 129 | } 130 | 131 | void WriteValue(int16_t val) 132 | { 133 | m_writer.Int(val); 134 | } 135 | 136 | void ReadValue(int16_t& t, rapidjson::Value& val) 137 | { 138 | if (val.IsInt()) 139 | t = (int16_t)val.GetInt(); 140 | } 141 | 142 | void WriteValue(uint16_t val) 143 | { 144 | m_writer.Int(val); 145 | } 146 | 147 | void ReadValue(uint16_t& t, rapidjson::Value& val) 148 | { 149 | if (val.IsInt()) 150 | t = (uint16_t)val.GetInt(); 151 | } 152 | 153 | void WriteValue(int val) 154 | { 155 | m_writer.Int(val); 156 | } 157 | 158 | void ReadValue(int& t, rapidjson::Value& val) 159 | { 160 | if (val.IsInt()) 161 | t = val.GetInt(); 162 | } 163 | 164 | void WriteValue(char val) 165 | { 166 | m_writer.Int(val); 167 | } 168 | 169 | void ReadValue(char& t, rapidjson::Value& val) 170 | { 171 | if(val.IsInt()) 172 | t = (char)val.GetInt(); 173 | } 174 | 175 | void WriteValue(uint32_t val) 176 | { 177 | m_writer.Uint(val); 178 | } 179 | 180 | void ReadValue(uint32_t& t, rapidjson::Value& val) 181 | { 182 | if (val.IsUint()) 183 | t = val.GetUint(); 184 | } 185 | 186 | void WriteValue(int64_t val) 187 | { 188 | m_writer.Int64(val); 189 | } 190 | 191 | void ReadValue(int64_t& t, rapidjson::Value& val) 192 | { 193 | if(val.IsInt64()) 194 | t = val.GetInt64(); 195 | } 196 | 197 | void WriteValue(uint64_t val) 198 | { 199 | m_writer.Uint64(val); 200 | } 201 | 202 | void ReadValue(uint64_t& t, rapidjson::Value& val) 203 | { 204 | if(val.IsUint64()) 205 | t = val.GetUint64(); 206 | } 207 | 208 | void WriteValue(double val) 209 | { 210 | m_writer.Double(val); 211 | } 212 | 213 | void ReadValue(double& t, rapidjson::Value& val) 214 | { 215 | if (val.IsNumber()) 216 | t = val.GetDouble(); 217 | } 218 | 219 | void WriteValue(float val) 220 | { 221 | m_writer.Double(static_cast(val)); 222 | } 223 | 224 | void ReadValue(float& t, rapidjson::Value& val) 225 | { 226 | if(val.IsNumber()) 227 | t = static_cast(val.GetDouble()); 228 | } 229 | 230 | template 231 | typename std::enable_if::value>::type WriteValue(T val) 232 | { 233 | m_writer.Bool(val); 234 | } 235 | 236 | //还要过滤智能指针的情况. 237 | template 238 | typename std::enable_if::value>::type WriteValue(T val) 239 | { 240 | //不支持动态指针的原因是反序列化的时候涉及到指针的内存管理,反序列化不应该考虑为对象分配内存. 241 | throw std::invalid_argument("not surpport dynamic pointer"); 242 | } 243 | 244 | void WriteNull() 245 | { 246 | m_writer.Null(); 247 | } 248 | 249 | void ReadValue(bool& t, rapidjson::Value& val) 250 | { 251 | if(val.IsBool()) 252 | t = val.GetBool(); 253 | } 254 | 255 | const char* GetJsonText() 256 | { 257 | return m_buf.GetString(); 258 | } 259 | 260 | private: 261 | rapidjson::StringBuffer m_buf; //json字符串的buf. 262 | JsonWriter m_writer; //json写入器. 263 | rapidjson::Document m_doc; 264 | }; 265 | } // namespace kapok 266 | 267 | -------------------------------------------------------------------------------- /kapok/Kapok.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Serializer.hpp" 3 | #include "DeSerializer.hpp" 4 | -------------------------------------------------------------------------------- /kapok/Serializer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #ifndef _MSC_VER 4 | #include 5 | #endif 6 | #include "traits.hpp" 7 | #include "Common.hpp" 8 | #include "JsonUtil.hpp" 9 | #include 10 | #include 11 | 12 | namespace kapok { 13 | class Serializer : NonCopyable 14 | { 15 | public: 16 | 17 | Serializer() 18 | { 19 | } 20 | 21 | ~Serializer() 22 | { 23 | } 24 | 25 | const char* GetString() 26 | { 27 | return m_jsutil.GetJsonText(); 28 | } 29 | 30 | //template 31 | //void Serialize(T const& t, const char* key = nullptr) 32 | //{ 33 | // m_jsutil.Reset(); 34 | // if (key == nullptr) 35 | // { 36 | // WriteObject(t, std::true_type{}); 37 | // } 38 | // else 39 | // { 40 | // SerializeImpl(t, key); 41 | // } 42 | //} 43 | 44 | template 45 | void Serialize(const T& t, const char* key = nullptr) 46 | { 47 | m_jsutil.Reset(); 48 | if (key == nullptr) 49 | { 50 | WriteObject(t, std::true_type{}); 51 | } 52 | else 53 | { 54 | SerializeImpl(t, key); 55 | } 56 | } 57 | 58 | private: 59 | template 60 | void SerializeImpl(T const& t, const char* key) 61 | { 62 | m_jsutil.StartObject(); 63 | m_jsutil.WriteValue(key); 64 | WriteObject(t, std::true_type{}); 65 | m_jsutil.EndObject(); 66 | } 67 | 68 | template 69 | const char* type_name() 70 | { 71 | #ifndef _MSC_VER 72 | return abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr); 73 | #else 74 | return typeid(T).name(); 75 | #endif 76 | } 77 | 78 | template 79 | const char* get_type_name() 80 | { 81 | const char* name = type_name(); 82 | return has_space(name) ? "temp" : type_name(); 83 | } 84 | 85 | bool has_space(const char* str) 86 | { 87 | const size_t len = strlen(str); 88 | for (size_t i = 0; i < len; i++) 89 | { 90 | if (str[i] == ' ') 91 | return true; 92 | } 93 | 94 | return false; 95 | } 96 | 97 | template 98 | std::enable_if_t::value> WriteObject(T const& t, BeginObjec bj) 99 | { 100 | if (static_cast(t)) 101 | { 102 | WriteObject(*t, bj); 103 | } 104 | else 105 | { 106 | WriteNull(); 107 | } 108 | } 109 | 110 | //template 111 | //typename std::enable_if::value>::type WriteObject(T&& t) 112 | //{ 113 | // m_jsutil.StartObject(); 114 | // WriteTuple(t.Meta()); 115 | // m_jsutil.EndObject(); 116 | //} 117 | 118 | // variant visitor 119 | template 120 | struct serialize_visitor : boost::static_visitor<> 121 | { 122 | explicit serialize_visitor(Serializer& s, int which) 123 | : s_(s) 124 | , which_(which - 1) 125 | { 126 | } 127 | 128 | template 129 | void operator() (T const& to_write) const 130 | { 131 | s_.BeginWriteKV(std::to_string(which_).c_str(), to_write); 132 | } 133 | 134 | void operator() (boost::blank) const 135 | { 136 | throw std::invalid_argument( "Cannot serialize an uninitialized Variant!" ); 137 | } 138 | 139 | Serializer& s_; 140 | int which_; 141 | }; 142 | 143 | template 144 | void WriteObject(variant const& v, BeginObj bj) 145 | { 146 | if (static_cast(v)) 147 | { 148 | //WriteObject(*t, bj); 149 | boost::apply_visitor(serialize_visitor{ *this, v.which() }, v); 150 | } 151 | else 152 | { 153 | WriteNull(); 154 | } 155 | } 156 | 157 | template 158 | typename std::enable_if::value>::type WriteObject(const T& t, BeginObjec) 159 | { 160 | m_jsutil.StartObject(); 161 | WriteTuple(((T&)t).Meta()); 162 | m_jsutil.EndObject(); 163 | } 164 | 165 | template 166 | typename std::enable_if::value>::type WriteObject(T const& t, BeginObjec) 167 | { 168 | m_jsutil.StartArray(); 169 | WriteTuple(t); 170 | m_jsutil.EndArray(); 171 | } 172 | 173 | template 174 | typename std::enable_if::value>::type WriteTuple(const Tuple& t) 175 | { 176 | } 177 | 178 | template 179 | typename std::enable_if::value>::type WriteTuple(const Tuple& t) 180 | { 181 | WriteObject(std::get(t), std::false_type{}); 182 | WriteTuple(t); 183 | } 184 | 185 | template 186 | typename std::enable_if::value>::type WriteObject(T const& t, BeginObjec) 187 | { 188 | WriteArray(t); 189 | } 190 | 191 | template 192 | auto WriteAdaptor(Adaptor&& adaptor, F get) 193 | { 194 | using adaptor_t = std::remove_cv_t>; 195 | adaptor_t temp = std::forward(adaptor); 196 | m_jsutil.StartArray(); 197 | while (!temp.empty()) 198 | { 199 | WriteObject(get(temp), std::false_type{}); 200 | temp.pop(); 201 | } 202 | m_jsutil.EndArray(); 203 | } 204 | 205 | template 206 | auto WriteObject(T&& t, BeginObject) -> std::enable_if_t::value> 207 | { 208 | WriteAdaptor(std::forward(t), [](auto const& adaptor) { return adaptor.front(); }); 209 | } 210 | 211 | template 212 | auto WriteObject(T&& t, BeginObject) -> std::enable_if_t::value || is_priority_queue::value> 213 | { 214 | WriteAdaptor(std::forward(t), [](auto const& adaptor) { return adaptor.top(); }); 215 | } 216 | 217 | template 218 | typename std::enable_if::value>::type WriteObject(T const& t, BeginObject) 219 | { 220 | m_jsutil.StartObject(); 221 | m_wr.clear(); 222 | for (auto const& pair : t) 223 | { 224 | m_wr << pair.first; 225 | WriteKV(m_wr.c_str(), pair.second); 226 | m_wr.clear(); 227 | } 228 | m_jsutil.EndObject(); 229 | } 230 | 231 | template 232 | typename std::enable_if::value>::type WriteObject(T const& t, std::true_type) 233 | { 234 | m_jsutil.StartObject(); 235 | m_wr << t.first; 236 | WriteKV(m_wr.c_str(), t.second); 237 | m_wr.clear(); 238 | m_jsutil.EndObject(); 239 | } 240 | 241 | template 242 | typename std::enable_if::value>::type WriteObject(T const& t, std::false_type) 243 | { 244 | m_wr.clear(); 245 | m_wr << t.first; 246 | WriteKV(m_wr.c_str(), t.second); 247 | m_wr.clear(); 248 | } 249 | 250 | template 251 | void WriteObject(std::array const& t, BeginObject) 252 | { 253 | WriteArray(t); 254 | } 255 | 256 | template 257 | void WriteObject(T const(&p)[N], BeginObject) 258 | { 259 | WriteArray(p); 260 | } 261 | 262 | template 263 | void WriteObject(char const(&p)[N], BeginObject bj) 264 | { 265 | WriteObject((const char*)p, bj); 266 | } 267 | 268 | //template 269 | //void WriteObject(char const(&p)[N], std::false_type) 270 | //{ 271 | // WriteObject((const char*)p, bj); 272 | //} 273 | 274 | template 275 | inline void WriteArray(Array const& v) 276 | { 277 | m_jsutil.StartArray(); 278 | for (auto const& i : v) 279 | { 280 | WriteObject(i, std::false_type{}); 281 | } 282 | m_jsutil.EndArray(); 283 | } 284 | 285 | template 286 | typename std::enable_if::value>::type WriteObject(T const& t, BeginObject) 287 | { 288 | m_jsutil.WriteValue(t); 289 | } 290 | 291 | template 292 | auto WriteObject(T const& val, BeginObject) ->std::enable_if_t>>::value> 294 | { 295 | using under_type = std::underlying_type_t< 296 | std::remove_reference_t>>; 297 | m_jsutil.WriteValue(static_cast(val)); 298 | } 299 | 300 | void WriteObject(const char* t, std::true_type) 301 | { 302 | m_jsutil.WriteValue(t); 303 | } 304 | 305 | void WriteObject(const char* t, std::false_type) 306 | { 307 | m_jsutil.WriteValue(t); 308 | } 309 | 310 | //template 311 | //typename std::enable_if::value>::type WriteValue(T&& t) 312 | //{ 313 | // WriteKV(boost::lexical_cast(t.first).c_str(), t.second); 314 | //} 315 | 316 | template 317 | void WriteKV(const char* k, V& v) 318 | { 319 | m_jsutil.WriteValue(k); 320 | WriteObject(v, std::true_type{}); 321 | } 322 | 323 | template 324 | void BeginWriteKV(const char* k, V& v) 325 | { 326 | m_jsutil.StartObject(); 327 | WriteKV(k, v); 328 | m_jsutil.EndObject(); 329 | } 330 | 331 | template 332 | typename std::enable_if::value>::type WriteValue(T const& t, BeginObject) 333 | { 334 | m_jsutil.WriteValue(std::forward(t)); 335 | } 336 | 337 | void WriteNull() 338 | { 339 | m_jsutil.WriteNull(); 340 | } 341 | 342 | private: 343 | JsonUtil m_jsutil; 344 | fmt::MemoryWriter m_wr; 345 | }; 346 | } // namespace kapok 347 | 348 | -------------------------------------------------------------------------------- /kapok/traits.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | //using namespace std; 16 | 17 | namespace kapok { 18 | template 19 | struct variant : boost::variant 20 | { 21 | using base_type = boost::variant; 22 | using types = typename boost::mpl::remove::type; 23 | 24 | explicit operator bool() const 25 | { 26 | return this->which() != 0; 27 | } 28 | 29 | template 30 | variant& operator= (T&& t) 31 | { 32 | return static_cast( 33 | static_cast(*this) = std::forward(t)); 34 | } 35 | 36 | bool operator== (variant const& other) const 37 | { 38 | return static_cast(*this) == static_cast(other); 39 | } 40 | 41 | bool operator!= (variant const& other) const 42 | { 43 | return !(*this == other); 44 | } 45 | 46 | bool operator< (variant const& other) const 47 | { 48 | return static_cast(*this) < static_cast(other); 49 | } 50 | 51 | bool operator> (variant const& other) const 52 | { 53 | return other < *this; 54 | } 55 | 56 | bool operator>= (variant const& other) const 57 | { 58 | return !(*this < other); 59 | } 60 | 61 | bool operator<= (variant const& other) const 62 | { 63 | return !(other < *this); 64 | } 65 | }; 66 | 67 | namespace detail 68 | { 69 | template 70 | using decay_t = typename std::decay::type; 71 | 72 | //template std::false_type static check_tuple_size(...); 73 | //template std::true_type static check_tuple_size(decltype(std::tuple_size::value)*); 74 | template < template class U, typename T > 75 | struct is_instantiation_of : std::false_type {}; 76 | 77 | template < template class U, typename... Args > 78 | struct is_instantiation_of< U, U > : std::true_type {}; 79 | 80 | template 81 | struct is_tuple : is_instantiation_of 82 | { 83 | }; 84 | 85 | //has_begin_end 86 | template 87 | struct has_begin_end 88 | { 89 | private: 90 | template static auto Check(int) -> decltype(std::declval().begin(), std::declval().end(), std::true_type()); 91 | template static std::false_type Check(...); 92 | 93 | public: 94 | enum 95 | { 96 | value = std::is_same(0)), std::true_type>::value 97 | }; 98 | }; 99 | 100 | template 101 | struct has_const_iterator 102 | { 103 | private: 104 | template static std::true_type Check(typename C::const_iterator*); 105 | template static std::false_type Check(...); 106 | public: 107 | enum 108 | { 109 | value = std::is_same(0)), std::true_type>::value 110 | }; 111 | }; 112 | 113 | template 114 | struct has_mapped_type 115 | { 116 | private: 117 | template static std::true_type Check(typename C::mapped_type*); 118 | template static std::false_type Check(...); 119 | public: 120 | enum 121 | { 122 | value = std::is_same(0)), std::true_type>::value 123 | }; 124 | }; 125 | 126 | //#define HAS_XXX_TYPE(token) 127 | // template struct has_##token{ 128 | // private: 129 | // template static std::true_type Check(typename C::token##*); 130 | // template static std::false_type Check(...); 131 | // public: 132 | // enum 133 | // { 134 | // value = std::is_same(0)), std::true_type>::value 135 | // }; 136 | // }; 137 | // 138 | // HAS_XXX_TYPE(const_iterator) 139 | // HAS_XXX_TYPE(mapped_type) 140 | 141 | template struct is_poiner_extent : std::false_type{}; 142 | template struct is_poiner_extent> : std::true_type{}; 143 | template struct is_poiner_extent> : std::true_type{}; 144 | template struct is_poiner_extent> : std::true_type{}; 145 | 146 | //#define IS_SMART_POINTER(token) 147 | // template struct is_poiner_extent> : std::true_type{}; 148 | // 149 | // IS_SMART_POINTER(shared) 150 | // IS_SMART_POINTER(unique) 151 | // IS_SMART_POINTER(weak) 152 | } 153 | 154 | template 155 | struct is_std_array : std::false_type {}; 156 | 157 | template 158 | struct is_std_array> : std::true_type {}; 159 | 160 | template 161 | struct is_string : std::integral_constant, std::string>::value>{}; 162 | 163 | template 164 | struct is_container : public std::integral_constant>::value&&detail::has_begin_end>::value&&!is_string::value>{}; 165 | 166 | template 167 | struct is_singlevalue_container : public std::integral_constant::value&&!std::is_array>::value&&!detail::is_tuple>::value && is_container>::value&&!detail::has_mapped_type>::value>{}; 168 | 169 | template 170 | struct is_map_container : public std::integral_constant>::value&&detail::has_mapped_type>::value>{}; 171 | 172 | template 173 | struct is_normal_class : std::integral_constant>::value&&!is_string::value> 174 | {}; 175 | 176 | template 177 | struct is_basic_type : std::integral_constant>::value || is_string::value> 178 | {}; 179 | 180 | template 181 | struct is_smart_pointer : detail::is_poiner_extent>{}; 182 | 183 | template 184 | struct is_pointer_ext : std::integral_constant>::value || is_smart_pointer>::value>{}; 185 | 186 | template class Template> 187 | struct is_specialization_of : std::false_type {}; 188 | 189 | template