Repository: qicosmos/Kapok Branch: master Commit: f4f3c7c5cb46 Files: 59 Total size: 669.9 KB Directory structure: gitextract_gg8ucus8/ ├── .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/ │ └── vcproject.vcxproj └── vcproject.sln ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitmodules ================================================ [submodule "fmt"] path = fmt url = https://github.com/fmtlib/fmt.git ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(kapok) add_definitions(-DFMT_HEADER_ONLY) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") if (CMAKE_BUILD_TYPE STREQUAL Debug) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_DEBUG") #add_definitions( # -D_DEBUG #) endif () find_package(Boost REQUIRED) include_directories(${Boost_INCLUDE_DIRS}) SET(EXTRA_LIBS ${EXTRA_LIBS} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) include_directories( ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/fmt ) set(SOURCE_FILES main.cpp test/panic.cpp test/primitive.cpp test/stl.cpp test/user.cpp ) install(DIRECTORY ${PROJECT_SOURCE_DIR}/kapok/ DESTINATION "include/kapok" FILES_MATCHING PATTERN "*.hpp") add_executable(kapok ${SOURCE_FILES}) target_link_libraries(kapok ${EXTRA_LIBS}) #install(FILES src/cloud_backup.ini DESTINATION "${PROJECT_BINARY_DIR}/") #################################### # test # enable_testing() # add_test(fundation_test_run fundation_test) # set_tests_properties (fundation_test_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") # add_test(get_object_summary_test_run get_object_summary_test) # set_tests_properties (get_object_summary_test_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") # add_test(list_object_summary_test_run list_object_summary_test) # set_tests_properties (list_object_summary_test_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") # add_test(test_backup_status_run test_backup_status) # set_tests_properties (test_backup_status_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") # add_test(test_kv_store_run test_kv_store) # set_tests_properties (test_kv_store_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") # add_test(test_kv_traverse_delete_run test_kv_traverse_delete) # set_tests_properties (test_kv_traverse_delete_run PROPERTIES PASS_REGULAR_EXPRESSION "0 failures are detected") # add_test(test_thread_pool_run test_thread_pool) # add_test(test_scribe_load_balance_run test_scribe_load_balance) include (InstallRequiredSystemLibraries) set (CPACK_PACKAGE_VERSION_MAJOR "1") set (CPACK_PACKAGE_VERSION_MINOR "0") SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "David Doria") include (CPack) ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # Kapok 现在请使用更好的序列化引擎iguana,比kapok更高效,本项目也不再维护,后面只维护iguana。 更好的序列化库,纯c++14开发,header-only,简洁高效。 Kapok---一个更好的序列化/反序列化库 可以很方便的将对象序列化和反序列化,序列化后的格式是标准的json格式。 wiki介绍:https://github.com/qicosmos/Kapok/wiki 社区:http://purecpp.cn/ Now there is a better serialization libray:https://github.com/qicosmos/iguana please replace kapok with iguana. ================================================ FILE: Test.hpp ================================================ #include "kapok/Kapok.hpp" void Performance() { kapok::Serializer sr; kapok::DeSerializer dr; auto tp = std::make_tuple(10, 12, string("test")); Timer t; for (size_t i = 0; i < 10000; i++) { sr.Serialize(tp, "tuple"); dr.Parse(sr.GetString()); std::tuple p; dr.Deserialize(p, "tuple"); } int64_t elapsed = t.elapsed(); std::cout << "kapok: " << elapsed <<"ms"<< std::endl; } ================================================ FILE: kapok/Common.hpp ================================================ #pragma once #include #include namespace kapok { template std::array split(const std::string& s, const char delimiter) { size_t start = 0; size_t end = s.find_first_of(delimiter); std::array output; size_t i = 0; while (end <= std::string::npos) { output[i++] = std::move(s.substr(start, end - start)); if (end == std::string::npos) break; start = end + 2; end = s.find_first_of(delimiter, start); } return output; } template static inline auto make(const std::array&ar, unsigned index, T const & t, T1& args) { return std::tuple_cat(t, std::make_tuple(std::pair(ar[index], args))); } template static inline auto make(const std::array&ar, unsigned index, T const & t, T1& first, Args&... args) { return make(ar, index + 1, std::tuple_cat(t, std::make_tuple(std::pair(ar[index], first))), args...); } #define VA_ARGS_NUM(...) std::tuple_size::value //#define META(...) auto Meta(){\ // auto ar = split(#__VA_ARGS__, ',');\ // return make(ar, 0, std::tuple<>(), __VA_ARGS__);\ //} /******************************************/ #define MARCO_EXPAND(...) __VA_ARGS__ #define APPLY_VARIADIC_MACRO(macro, ...) MARCO_EXPAND(macro(__VA_ARGS__)) #define ADD_REFERENCE(t) std::reference_wrapper(t) #define ADD_REFERENCE_CONST(t) std::reference_wrapper>(t) #define PAIR_OBJECT(t) std::make_pair(#t, ADD_REFERENCE(t)) #define PAIR_OBJECT_CONST(t) std::make_pair(#t, ADD_REFERENCE_CONST(t)) #define MAKE_TUPLE(...) auto Meta() { return std::make_tuple(__VA_ARGS__); } #define MAKE_TUPLE_CONST(...) auto Meta() const { return std::make_tuple(__VA_ARGS__); } /* arg list expand macro, now support 40 args */ #define MAKE_ARG_LIST_1(op, arg, ...) op(arg) #define MAKE_ARG_LIST_2(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_1(op, __VA_ARGS__)) #define MAKE_ARG_LIST_3(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_2(op, __VA_ARGS__)) #define MAKE_ARG_LIST_4(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_3(op, __VA_ARGS__)) #define MAKE_ARG_LIST_5(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_4(op, __VA_ARGS__)) #define MAKE_ARG_LIST_6(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_5(op, __VA_ARGS__)) #define MAKE_ARG_LIST_7(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_6(op, __VA_ARGS__)) #define MAKE_ARG_LIST_8(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_7(op, __VA_ARGS__)) #define MAKE_ARG_LIST_9(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_8(op, __VA_ARGS__)) #define MAKE_ARG_LIST_10(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_9(op, __VA_ARGS__)) #define MAKE_ARG_LIST_11(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_10(op, __VA_ARGS__)) #define MAKE_ARG_LIST_12(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_11(op, __VA_ARGS__)) #define MAKE_ARG_LIST_13(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_12(op, __VA_ARGS__)) #define MAKE_ARG_LIST_14(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_13(op, __VA_ARGS__)) #define MAKE_ARG_LIST_15(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_14(op, __VA_ARGS__)) #define MAKE_ARG_LIST_16(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_15(op, __VA_ARGS__)) #define MAKE_ARG_LIST_17(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_16(op, __VA_ARGS__)) #define MAKE_ARG_LIST_18(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_17(op, __VA_ARGS__)) #define MAKE_ARG_LIST_19(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_18(op, __VA_ARGS__)) #define MAKE_ARG_LIST_20(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_19(op, __VA_ARGS__)) #define MAKE_ARG_LIST_21(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_20(op, __VA_ARGS__)) #define MAKE_ARG_LIST_22(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_21(op, __VA_ARGS__)) #define MAKE_ARG_LIST_23(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_22(op, __VA_ARGS__)) #define MAKE_ARG_LIST_24(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_23(op, __VA_ARGS__)) #define MAKE_ARG_LIST_25(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_24(op, __VA_ARGS__)) #define MAKE_ARG_LIST_26(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_25(op, __VA_ARGS__)) #define MAKE_ARG_LIST_27(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_26(op, __VA_ARGS__)) #define MAKE_ARG_LIST_28(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_27(op, __VA_ARGS__)) #define MAKE_ARG_LIST_29(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_28(op, __VA_ARGS__)) #define MAKE_ARG_LIST_30(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_29(op, __VA_ARGS__)) #define MAKE_ARG_LIST_31(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_30(op, __VA_ARGS__)) #define MAKE_ARG_LIST_32(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_31(op, __VA_ARGS__)) #define MAKE_ARG_LIST_33(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_32(op, __VA_ARGS__)) #define MAKE_ARG_LIST_34(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_33(op, __VA_ARGS__)) #define MAKE_ARG_LIST_35(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_34(op, __VA_ARGS__)) #define MAKE_ARG_LIST_36(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_35(op, __VA_ARGS__)) #define MAKE_ARG_LIST_37(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_36(op, __VA_ARGS__)) #define MAKE_ARG_LIST_38(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_37(op, __VA_ARGS__)) #define MAKE_ARG_LIST_39(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_38(op, __VA_ARGS__)) #define MAKE_ARG_LIST_40(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_39(op, __VA_ARGS__)) /* emmbed marco, using EMMBED_TUPLE(5 , a, b, c, d, e) */ //note use MACRO_CONCAT like A##_##B direct may cause marco expand error #define MACRO_CONCAT(A, B) MACRO_CONCAT1(A, B) #define MACRO_CONCAT1(A, B) A##_##B #define MAKE_ARG_LIST(N, op, arg, ...) \ MACRO_CONCAT(MAKE_ARG_LIST, N)(op, arg, __VA_ARGS__) #define EMMBED_TUPLE(N, ...) \ MAKE_TUPLE(MAKE_ARG_LIST(N, PAIR_OBJECT, __VA_ARGS__)) \ MAKE_TUPLE_CONST(MAKE_ARG_LIST(N, PAIR_OBJECT_CONST, __VA_ARGS__)) #define RSEQ_N() \ 119,118,117,116,115,114,113,112,111,110,\ 109,108,107,106,105,104,103,102,101,100,\ 99,98,97,96,95,94,93,92,91,90, \ 89,88,87,86,85,84,83,82,81,80, \ 79,78,77,76,75,74,73,72,71,70, \ 69,68,67,66,65,64,63,62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ 39,38,37,36,35,34,33,32,31,30, \ 29,28,27,26,25,24,23,22,21,20, \ 19,18,17,16,15,14,13,12,11,10, \ 9,8,7,6,5,4,3,2,1,0 #define ARG_N( \ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63,_64,_65,_66,_67,_68,_69,_70, \ _71,_72,_73,_74,_75,_76,_77,_78,_79,_80, \ _81,_82,_83,_84,_85,_86,_87,_88,_89,_90, \ _91,_92,_93,_94,_95,_96,_97,_98,_99,_100, \ _101,_102,_103,_104,_105,_106,_107,_108,_109,_110, \ _111,_112,_113,_114,_115,_116,_117,_118,_119,N, ...) N #define GET_ARG_COUNT_INNER(...) MARCO_EXPAND(ARG_N(__VA_ARGS__)) #define GET_ARG_COUNT(...) GET_ARG_COUNT_INNER(__VA_ARGS__, RSEQ_N()) #define META(...) EMMBED_TUPLE(GET_ARG_COUNT(__VA_ARGS__), __VA_ARGS__) /******************************************/ class NonCopyable { public: NonCopyable(const NonCopyable&) = delete; NonCopyable& operator = (const NonCopyable&) = delete; NonCopyable() = default; }; } // namespace kapok ================================================ FILE: kapok/DeSerializer.hpp ================================================ #pragma once #include "JsonUtil.hpp" #include "traits.hpp" #include namespace kapok { class DeSerializer : NonCopyable { public: DeSerializer() = default; DeSerializer(const char* jsonText, std::size_t length) { Parse(jsonText, length); } DeSerializer(const std::string& jsonText) { Parse(jsonText); } ~DeSerializer() { } void Parse(const std::string& jsonText) { Parse(jsonText.c_str(), jsonText.length()); } void Parse(const char* jsonText, std::size_t length) { m_jsutil.Parse(jsonText, length); } rapidjson::Document& GetDocument() { return m_jsutil.GetDocument(); } template void Deserialize(T& t, const std::string& key, bool has_root = true) { Deserialize(t, key.c_str(), has_root); } template void Deserialize(T& t, const char* key, bool has_root = true) { rapidjson::Value& jsonval = GetRootValue(key, has_root); ReadObject(t, jsonval, std::true_type{}); } template void Deserialize(T& t, bool has_root = false) { rapidjson::Value& jsonval = GetRootValue(nullptr, has_root); ReadObject(t, jsonval, std::true_type{}); } template void Deserialize(T(&p)[N], const char* key) { ReadArray(p, key); } template void Deserialize(std::array& arr, const char* key) { ReadArray(arr, key); } private: rapidjson::Value& GetRootValue(const char* key, bool has_root = true) { rapidjson::Document& doc = m_jsutil.GetDocument(); if (!has_root) return doc; if (key == nullptr) { auto it = doc.MemberBegin(); return (rapidjson::Value&)it->value; } if (!doc.HasMember(key)) throw std::invalid_argument("the key is not exist"); return doc[key]; } template void ReadArray(T& t, const char* key) { rapidjson::Value& jsonval = GetRootValue(key); ReadArray(t, jsonval); } template void ReadArray(T& t, rapidjson::Value& jsonval) { size_t sz = jsonval.Size(); for (rapidjson::SizeType i = 0; i < sz; i++) { value_type value; ReadValue(value, jsonval[i], std::true_type{}); t[i] = value; } } template typename std::enable_if::value>::type ReadObject(T& t, rapidjson::Value& val, BeginObject bo) { ReadTuple(std::forward(t), val, bo); } template typename std::enable_if::value>::type ReadObject(T& t, rapidjson::Value& val, BeginObject) { ReadTuple(t.Meta(), val, std::false_type{}); } template auto ReadObject(T& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t>>::value> { using under_type = std::underlying_type_t>>; ReadObject(reinterpret_cast(t), val, std::true_type{}); } template auto ReadObject(T& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t::value> { if (!val.IsNull()) { std::remove_reference_t tmp; ReadObject(tmp, val, std::true_type{}); t = tmp; } } template void ReadObject(variant& v, rapidjson::Value& value, BeginObject) { if (!value.IsObject() || value.MemberCount() != 1) throw std::invalid_argument{ "Should be an object with one member" }; auto object = value.MemberBegin(); auto index = boost::lexical_cast( object->name.GetString(), object->name.GetStringLength()); LoadVariant(object->value, index, v); //LoadVariant(value, index, v); } template void ReadTuple(Tuple&& tp, rapidjson::Value& val, BeginObject bo) { const int size = std::tuple_size::value; for (rapidjson::SizeType j = 0; j < size; j++) { SetValueByIndex(j, tp, val, bo); } } template inline auto SetValueByIndex(size_t, Tuple&, rapidjson::Value&, BeginObject) -> std::enable_if_t<(k == std::tuple_size::value)> { throw std::invalid_argument("arg index out of range"); } template inline auto SetValueByIndex(size_t index, Tuple& tp, rapidjson::Value& val, BeginObject bo) -> std::enable_if_t<(k < std::tuple_size::value)> { if (k == index) { ReadValue(tp, val, bo); } else { SetValueByIndex(index, tp, val, bo); } } template auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::enable_if_t::value> { using U = typename std::decay::type; size_t sz = v.Size(); for (rapidjson::SizeType i = sz; i > 0; i--) { typename U::value_type value; ReadObject(value, v[i - 1], std::true_type{}); push(t, value, i-1); } } template auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::enable_if_t::value || is_container_adapter::value> { using U = typename std::decay::type; size_t sz = v.Size(); for (rapidjson::SizeType i = 0; i < sz; i++) { typename U::value_type value; ReadObject(value, v[i], std::true_type{}); push(t, value, i); } } template auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::enable_if_t::value || is_std_array::value> { using U = typename std::decay::type; size_t sz = v.Size(); for (rapidjson::SizeType i = 0; i < sz; i++) { typename U::value_type value; ReadObject(value, v[i], std::true_type{}); t[i] = value; } } template auto push(T& t, value_type& v, std::size_t index) -> std::enable_if_t::value&&!is_set::value&&!is_multiset::value&&!is_unordered_set::value> { t.push_back(v); } template auto push(T& t, value_type& v, std::size_t index) -> std::enable_if_t::value || is_multiset::value || is_unordered_set::value> { t.insert(v); } template auto push(T& t, value_type& v, std::size_t index) -> std::enable_if_t::value || std::is_array::value> { t[index] = v; } template auto push(T& t, value_type& v, std::size_t index) -> std::enable_if_t::value || is_stack::value> { t.push(v); } template auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::enable_if_t::value> { using U = typename std::decay::type; for (rapidjson::Value::ConstMemberIterator it = v.MemberBegin(); it != v.MemberEnd(); it++) { using key_type = typename U::key_type; using val_type = typename U::value_type::second_type; key_type key; val_type value; key = boost::lexical_cast(it->name.GetString()); ReadObject(value, (rapidjson::Value&)it->value, std::true_type {}); t.emplace(key, value); } } template auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::enable_if_t::value> { m_jsutil.ReadValue(std::forward(t), v); } template auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t::value> { ReadObject(t, val, std::false_type{}); } template auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t::value> { ReadObject(t, val, std::true_type{}); } template void ReadValue(variant& v, rapidjson::Value& val, BeginObject obj) { //ReadObject(t, val, std::true_type{}); ReadObject(v, val, std::true_type{}); } template auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t>>::value> { using under_type = std::underlying_type_t>>; ReadObject(std::forward(t), val, std::true_type{}); } template auto ReadObject(T&& t, rapidjson::Value& val, std::true_type bo) -> std::enable_if_t::value> { using pair_t = std::remove_cv_t>; using first_type = typename pair_t::first_type; using second_type = typename pair_t::second_type; //assert(val.MemberCount() == 1); if(val.MemberCount()!=1) throw std::invalid_argument("member count error"); auto itr = val.MemberBegin(); t.first = boost::lexical_cast(itr->name.GetString()); ReadObject(t.second, itr->value, bo); } template auto ReadObject(T&& t, rapidjson::Value& val, std::false_type bo) -> std::enable_if_t::value> { ReadObject(t.second, val, bo); } template auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t::value> { m_jsutil.ReadValue(std::forward(t), val); } template auto ReadValue(T&& t, rapidjson::Value& val, std::false_type bo) -> std::enable_if_t::value> { //assert(!val.IsArray()); if(val.IsArray()) throw std::invalid_argument("should not be array"); decltype(auto) tuple_elem = std::get(t); auto itr = val.FindMember(tuple_elem.first); if(itr==val.MemberEnd()) return; //assert(itr != val.MemberEnd()); ReadObject(tuple_elem, (rapidjson::Value&)(itr->value), bo); } template auto ReadValue(T&& t, rapidjson::Value& val, std::true_type bo) -> std::enable_if_t::value> { //assert(val.IsArray()); if (!val.IsArray()) throw std::invalid_argument("should be array"); ReadObject(std::get(t), val[N], bo); } // functions for variant private: template void LoadVariantImplFunc(rapidjson::Value& value, variant& v) { using index_type = boost::mpl::int_; using value_type = typename boost::mpl::at::types, index_type>::type; value_type temp; ReadObject(temp, value, std::true_type{}); v = temp; } template struct LoadVariantImpl { template void operator() (DeSerializer& dr, rapidjson::Value& value, size_t index, Variant& v) { if (Begin == index) { dr.LoadVariantImplFunc(value, v); return; } LoadVariantImpl{}(dr, value, index, v); } }; template struct LoadVariantImpl { template void operator() (DeSerializer& dr,rapidjson::Value& value, size_t index, Variant& v) { if (End == index) { dr.LoadVariantImplFunc(value, v); return; } throw std::invalid_argument{ "Wrong variant types." }; } }; template void LoadVariant(rapidjson::Value& value, size_t index, variant& v) { LoadVariantImpl<0, sizeof...(Args) - 1>{}(*this, value, index, v); } private: JsonUtil m_jsutil; }; } // namespace kapok ================================================ FILE: kapok/JsonUtil.hpp ================================================ #pragma once #include #include #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/document.h" #include "traits.hpp" #include "Common.hpp" namespace kapok { class JsonUtil : NonCopyable { typedef rapidjson::Writer JsonWriter; public: JsonUtil() : m_writer(m_buf) { } template void WriteJson(const char* key, T&& value) { m_writer.String(key); WriteValue(std::forward(value)); } template void WriteJson(const std::string& key, T&& value) { m_writer.String(key.c_str()); WriteValue(std::forward(value)); } void Reset() { m_writer.Reset(m_buf); m_buf.Clear(); } void StartObject() { m_writer.StartObject(); } void EndObject() { m_writer.EndObject(); } void StartArray() { m_writer.StartArray(); } void EndArray() { m_writer.EndArray(); } void WriteValue(const char* val) { if (val == nullptr) m_writer.Null(); else m_writer.String(val); } void ReadValue(char*& t, rapidjson::Value& val) { if (val.IsString()) t = (char*)val.GetString(); } void WriteValue(const std::string& val) { m_writer.String(val.c_str()); } void ReadValue(std::string& t, rapidjson::Value& val) { if(val.IsString()) t = val.GetString(); } void Parse(const char* json) { auto& r = m_doc.Parse<0>(json); if (r.HasParseError()) { throw std::invalid_argument("json string parse failed"); } } void Parse(const char* json, std::size_t length) { auto& r = m_doc.Parse<0>(json, length); if (r.HasParseError()) { throw std::invalid_argument("json string parse failed"); } } rapidjson::Document& GetDocument() { return m_doc; } void WriteValue(uint8_t val) { m_writer.Int(val); } void ReadValue(uint8_t& t, rapidjson::Value& val) { if (val.IsInt()) t = (uint8_t)val.GetInt(); } void WriteValue(int8_t val) { m_writer.Int(val); } void ReadValue(int8_t& t, rapidjson::Value& val) { if (val.IsInt()) t = (int8_t)val.GetInt(); } void WriteValue(int16_t val) { m_writer.Int(val); } void ReadValue(int16_t& t, rapidjson::Value& val) { if (val.IsInt()) t = (int16_t)val.GetInt(); } void WriteValue(uint16_t val) { m_writer.Int(val); } void ReadValue(uint16_t& t, rapidjson::Value& val) { if (val.IsInt()) t = (uint16_t)val.GetInt(); } void WriteValue(int val) { m_writer.Int(val); } void ReadValue(int& t, rapidjson::Value& val) { if (val.IsInt()) t = val.GetInt(); } void WriteValue(char val) { m_writer.Int(val); } void ReadValue(char& t, rapidjson::Value& val) { if(val.IsInt()) t = (char)val.GetInt(); } void WriteValue(uint32_t val) { m_writer.Uint(val); } void ReadValue(uint32_t& t, rapidjson::Value& val) { if (val.IsUint()) t = val.GetUint(); } void WriteValue(int64_t val) { m_writer.Int64(val); } void ReadValue(int64_t& t, rapidjson::Value& val) { if(val.IsInt64()) t = val.GetInt64(); } void WriteValue(uint64_t val) { m_writer.Uint64(val); } void ReadValue(uint64_t& t, rapidjson::Value& val) { if(val.IsUint64()) t = val.GetUint64(); } void WriteValue(double val) { m_writer.Double(val); } void ReadValue(double& t, rapidjson::Value& val) { if (val.IsNumber()) t = val.GetDouble(); } void WriteValue(float val) { m_writer.Double(static_cast(val)); } void ReadValue(float& t, rapidjson::Value& val) { if(val.IsNumber()) t = static_cast(val.GetDouble()); } template typename std::enable_if::value>::type WriteValue(T val) { m_writer.Bool(val); } //还要过滤智能指针的情况. template typename std::enable_if::value>::type WriteValue(T val) { //不支持动态指针的原因是反序列化的时候涉及到指针的内存管理,反序列化不应该考虑为对象分配内存. throw std::invalid_argument("not surpport dynamic pointer"); } void WriteNull() { m_writer.Null(); } void ReadValue(bool& t, rapidjson::Value& val) { if(val.IsBool()) t = val.GetBool(); } const char* GetJsonText() { return m_buf.GetString(); } private: rapidjson::StringBuffer m_buf; //json字符串的buf. JsonWriter m_writer; //json写入器. rapidjson::Document m_doc; }; } // namespace kapok ================================================ FILE: kapok/Kapok.hpp ================================================ #pragma once #include "Serializer.hpp" #include "DeSerializer.hpp" ================================================ FILE: kapok/Serializer.hpp ================================================ #pragma once #include #ifndef _MSC_VER #include #endif #include "traits.hpp" #include "Common.hpp" #include "JsonUtil.hpp" #include #include namespace kapok { class Serializer : NonCopyable { public: Serializer() { } ~Serializer() { } const char* GetString() { return m_jsutil.GetJsonText(); } //template //void Serialize(T const& t, const char* key = nullptr) //{ // m_jsutil.Reset(); // if (key == nullptr) // { // WriteObject(t, std::true_type{}); // } // else // { // SerializeImpl(t, key); // } //} template void Serialize(const T& t, const char* key = nullptr) { m_jsutil.Reset(); if (key == nullptr) { WriteObject(t, std::true_type{}); } else { SerializeImpl(t, key); } } private: template void SerializeImpl(T const& t, const char* key) { m_jsutil.StartObject(); m_jsutil.WriteValue(key); WriteObject(t, std::true_type{}); m_jsutil.EndObject(); } template const char* type_name() { #ifndef _MSC_VER return abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr); #else return typeid(T).name(); #endif } template const char* get_type_name() { const char* name = type_name(); return has_space(name) ? "temp" : type_name(); } bool has_space(const char* str) { const size_t len = strlen(str); for (size_t i = 0; i < len; i++) { if (str[i] == ' ') return true; } return false; } template std::enable_if_t::value> WriteObject(T const& t, BeginObjec bj) { if (static_cast(t)) { WriteObject(*t, bj); } else { WriteNull(); } } //template //typename std::enable_if::value>::type WriteObject(T&& t) //{ // m_jsutil.StartObject(); // WriteTuple(t.Meta()); // m_jsutil.EndObject(); //} // variant visitor template struct serialize_visitor : boost::static_visitor<> { explicit serialize_visitor(Serializer& s, int which) : s_(s) , which_(which - 1) { } template void operator() (T const& to_write) const { s_.BeginWriteKV(std::to_string(which_).c_str(), to_write); } void operator() (boost::blank) const { throw std::invalid_argument( "Cannot serialize an uninitialized Variant!" ); } Serializer& s_; int which_; }; template void WriteObject(variant const& v, BeginObj bj) { if (static_cast(v)) { //WriteObject(*t, bj); boost::apply_visitor(serialize_visitor{ *this, v.which() }, v); } else { WriteNull(); } } template typename std::enable_if::value>::type WriteObject(const T& t, BeginObjec) { m_jsutil.StartObject(); WriteTuple(((T&)t).Meta()); m_jsutil.EndObject(); } template typename std::enable_if::value>::type WriteObject(T const& t, BeginObjec) { m_jsutil.StartArray(); WriteTuple(t); m_jsutil.EndArray(); } template typename std::enable_if::value>::type WriteTuple(const Tuple& t) { } template typename std::enable_if::value>::type WriteTuple(const Tuple& t) { WriteObject(std::get(t), std::false_type{}); WriteTuple(t); } template typename std::enable_if::value>::type WriteObject(T const& t, BeginObjec) { WriteArray(t); } template auto WriteAdaptor(Adaptor&& adaptor, F get) { using adaptor_t = std::remove_cv_t>; adaptor_t temp = std::forward(adaptor); m_jsutil.StartArray(); while (!temp.empty()) { WriteObject(get(temp), std::false_type{}); temp.pop(); } m_jsutil.EndArray(); } template auto WriteObject(T&& t, BeginObject) -> std::enable_if_t::value> { WriteAdaptor(std::forward(t), [](auto const& adaptor) { return adaptor.front(); }); } template auto WriteObject(T&& t, BeginObject) -> std::enable_if_t::value || is_priority_queue::value> { WriteAdaptor(std::forward(t), [](auto const& adaptor) { return adaptor.top(); }); } template typename std::enable_if::value>::type WriteObject(T const& t, BeginObject) { m_jsutil.StartObject(); m_wr.clear(); for (auto const& pair : t) { m_wr << pair.first; WriteKV(m_wr.c_str(), pair.second); m_wr.clear(); } m_jsutil.EndObject(); } template typename std::enable_if::value>::type WriteObject(T const& t, std::true_type) { m_jsutil.StartObject(); m_wr << t.first; WriteKV(m_wr.c_str(), t.second); m_wr.clear(); m_jsutil.EndObject(); } template typename std::enable_if::value>::type WriteObject(T const& t, std::false_type) { m_wr.clear(); m_wr << t.first; WriteKV(m_wr.c_str(), t.second); m_wr.clear(); } template void WriteObject(std::array const& t, BeginObject) { WriteArray(t); } template void WriteObject(T const(&p)[N], BeginObject) { WriteArray(p); } template void WriteObject(char const(&p)[N], BeginObject bj) { WriteObject((const char*)p, bj); } //template //void WriteObject(char const(&p)[N], std::false_type) //{ // WriteObject((const char*)p, bj); //} template inline void WriteArray(Array const& v) { m_jsutil.StartArray(); for (auto const& i : v) { WriteObject(i, std::false_type{}); } m_jsutil.EndArray(); } template typename std::enable_if::value>::type WriteObject(T const& t, BeginObject) { m_jsutil.WriteValue(t); } template auto WriteObject(T const& val, BeginObject) ->std::enable_if_t>>::value> { using under_type = std::underlying_type_t< std::remove_reference_t>>; m_jsutil.WriteValue(static_cast(val)); } void WriteObject(const char* t, std::true_type) { m_jsutil.WriteValue(t); } void WriteObject(const char* t, std::false_type) { m_jsutil.WriteValue(t); } //template //typename std::enable_if::value>::type WriteValue(T&& t) //{ // WriteKV(boost::lexical_cast(t.first).c_str(), t.second); //} template void WriteKV(const char* k, V& v) { m_jsutil.WriteValue(k); WriteObject(v, std::true_type{}); } template void BeginWriteKV(const char* k, V& v) { m_jsutil.StartObject(); WriteKV(k, v); m_jsutil.EndObject(); } template typename std::enable_if::value>::type WriteValue(T const& t, BeginObject) { m_jsutil.WriteValue(std::forward(t)); } void WriteNull() { m_jsutil.WriteNull(); } private: JsonUtil m_jsutil; fmt::MemoryWriter m_wr; }; } // namespace kapok ================================================ FILE: kapok/traits.hpp ================================================ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include //using namespace std; namespace kapok { template struct variant : boost::variant { using base_type = boost::variant; using types = typename boost::mpl::remove::type; explicit operator bool() const { return this->which() != 0; } template variant& operator= (T&& t) { return static_cast( static_cast(*this) = std::forward(t)); } bool operator== (variant const& other) const { return static_cast(*this) == static_cast(other); } bool operator!= (variant const& other) const { return !(*this == other); } bool operator< (variant const& other) const { return static_cast(*this) < static_cast(other); } bool operator> (variant const& other) const { return other < *this; } bool operator>= (variant const& other) const { return !(*this < other); } bool operator<= (variant const& other) const { return !(other < *this); } }; namespace detail { template using decay_t = typename std::decay::type; //template std::false_type static check_tuple_size(...); //template std::true_type static check_tuple_size(decltype(std::tuple_size::value)*); template < template class U, typename T > struct is_instantiation_of : std::false_type {}; template < template class U, typename... Args > struct is_instantiation_of< U, U > : std::true_type {}; template struct is_tuple : is_instantiation_of { }; //has_begin_end template struct has_begin_end { private: template static auto Check(int) -> decltype(std::declval().begin(), std::declval().end(), std::true_type()); template static std::false_type Check(...); public: enum { value = std::is_same(0)), std::true_type>::value }; }; template struct has_const_iterator { private: template static std::true_type Check(typename C::const_iterator*); template static std::false_type Check(...); public: enum { value = std::is_same(0)), std::true_type>::value }; }; template struct has_mapped_type { private: template static std::true_type Check(typename C::mapped_type*); template static std::false_type Check(...); public: enum { value = std::is_same(0)), std::true_type>::value }; }; //#define HAS_XXX_TYPE(token) // template struct has_##token{ // private: // template static std::true_type Check(typename C::token##*); // template static std::false_type Check(...); // public: // enum // { // value = std::is_same(0)), std::true_type>::value // }; // }; // // HAS_XXX_TYPE(const_iterator) // HAS_XXX_TYPE(mapped_type) template struct is_poiner_extent : std::false_type{}; template struct is_poiner_extent> : std::true_type{}; template struct is_poiner_extent> : std::true_type{}; template struct is_poiner_extent> : std::true_type{}; //#define IS_SMART_POINTER(token) // template struct is_poiner_extent> : std::true_type{}; // // IS_SMART_POINTER(shared) // IS_SMART_POINTER(unique) // IS_SMART_POINTER(weak) } template struct is_std_array : std::false_type {}; template struct is_std_array> : std::true_type {}; template struct is_string : std::integral_constant, std::string>::value>{}; template struct is_container : public std::integral_constant>::value&&detail::has_begin_end>::value&&!is_string::value>{}; template 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>{}; template struct is_map_container : public std::integral_constant>::value&&detail::has_mapped_type>::value>{}; template struct is_normal_class : std::integral_constant>::value&&!is_string::value> {}; template struct is_basic_type : std::integral_constant>::value || is_string::value> {}; template struct is_smart_pointer : detail::is_poiner_extent>{}; template struct is_pointer_ext : std::integral_constant>::value || is_smart_pointer>::value>{}; template class Template> struct is_specialization_of : std::false_type {}; template