Showing preview only (696K chars total). Download the full file or copy to clipboard to get everything.
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<int, int, string> p;
dr.Deserialize(p, "tuple");
}
int64_t elapsed = t.elapsed();
std::cout << "kapok: " << elapsed <<"ms"<< std::endl;
}
================================================
FILE: kapok/Common.hpp
================================================
#pragma once
#include <array>
#include <tuple>
namespace kapok {
template<unsigned N>
std::array<std::string, N> split(const std::string& s, const char delimiter)
{
size_t start = 0;
size_t end = s.find_first_of(delimiter);
std::array<std::string, N> 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 <size_t N, typename T, typename T1>
static inline auto make(const std::array<std::string, N>&ar, unsigned index, T const & t, T1& args)
{
return std::tuple_cat(t, std::make_tuple(std::pair<std::string, T1&>(ar[index], args)));
}
template <size_t N, typename T, typename T1, typename... Args>
static inline auto make(const std::array<std::string, N>&ar, unsigned index, T const & t, T1& first, Args&... args)
{
return make(ar, index + 1, std::tuple_cat(t, std::make_tuple(std::pair<std::string, T1&>(ar[index], first))), args...);
}
#define VA_ARGS_NUM(...) std::tuple_size<decltype(std::make_tuple(__VA_ARGS__))>::value
//#define META(...) auto Meta(){\
// auto ar = split<VA_ARGS_NUM(__VA_ARGS__)>(#__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<decltype(t)>(t)
#define ADD_REFERENCE_CONST(t) std::reference_wrapper<std::add_const_t<decltype(t)>>(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 <boost/lexical_cast.hpp>
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<typename T>
void Deserialize(T& t, const std::string& key, bool has_root = true)
{
Deserialize(t, key.c_str(), has_root);
}
template<typename T>
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<typename T>
void Deserialize(T& t, bool has_root = false)
{
rapidjson::Value& jsonval = GetRootValue(nullptr, has_root);
ReadObject(t, jsonval, std::true_type{});
}
template <typename T, size_t N>
void Deserialize(T(&p)[N], const char* key)
{
ReadArray<T>(p, key);
}
template<typename T, size_t N>
void Deserialize(std::array<T, N>& arr, const char* key)
{
ReadArray<T>(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<typename value_type, typename T>
void ReadArray(T& t, const char* key)
{
rapidjson::Value& jsonval = GetRootValue(key);
ReadArray<value_type>(t, jsonval);
}
template<typename value_type, typename T>
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 T, typename BeginObject>
typename std::enable_if<is_tuple<T>::value>::type ReadObject(T& t, rapidjson::Value& val, BeginObject bo)
{
ReadTuple(std::forward<T>(t), val, bo);
}
template<typename T, typename BeginObject>
typename std::enable_if<is_user_class<T>::value>::type ReadObject(T& t, rapidjson::Value& val, BeginObject)
{
ReadTuple(t.Meta(), val, std::false_type{});
}
template <typename T, typename BeginObject>
auto ReadObject(T& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t<std::is_enum<
std::remove_cv_t<std::remove_reference_t<T>>>::value>
{
using under_type = std::underlying_type_t<std::remove_cv_t<std::remove_reference_t<T>>>;
ReadObject(reinterpret_cast<under_type&>(t), val, std::true_type{});
}
template <typename T, typename BeginObject>
auto ReadObject(T& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t<is_optional<T>::value>
{
if (!val.IsNull())
{
std::remove_reference_t<decltype(*t)> tmp;
ReadObject(tmp, val, std::true_type{});
t = tmp;
}
}
template <typename BeginObject, typename ... Args>
void ReadObject(variant<Args...>& 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<size_t>(
object->name.GetString(), object->name.GetStringLength());
LoadVariant(object->value, index, v);
//LoadVariant(value, index, v);
}
template<typename Tuple, typename BeginObject>
void ReadTuple(Tuple&& tp, rapidjson::Value& val, BeginObject bo)
{
const int size = std::tuple_size<Tuple>::value;
for (rapidjson::SizeType j = 0; j < size; j++)
{
SetValueByIndex(j, tp, val, bo);
}
}
template<size_t k=0, typename Tuple, typename BeginObject>
inline auto SetValueByIndex(size_t, Tuple&, rapidjson::Value&, BeginObject) ->
std::enable_if_t<(k == std::tuple_size<Tuple>::value)>
{
throw std::invalid_argument("arg index out of range");
}
template<size_t k = 0, typename Tuple, typename BeginObject>
inline auto SetValueByIndex(size_t index, Tuple& tp, rapidjson::Value& val, BeginObject bo) ->
std::enable_if_t<(k < std::tuple_size<Tuple>::value)>
{
if (k == index)
{
ReadValue<k>(tp, val, bo);
}
else
{
SetValueByIndex<k + 1>(index, tp, val, bo);
}
}
template<typename T, typename BeginObject>
auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) ->
std::enable_if_t<is_stack<T>::value>
{
using U = typename std::decay<T>::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<typename T, typename BeginObject>
auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) ->
std::enable_if_t<is_singlevalue_container<T>::value || is_container_adapter<T>::value>
{
using U = typename std::decay<T>::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<typename T, typename BeginObject>
auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) ->
std::enable_if_t<std::is_array<T>::value || is_std_array<T>::value>
{
using U = typename std::decay<T>::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<typename T, typename value_type>
auto push(T& t, value_type& v, std::size_t index) ->
std::enable_if_t<is_singlevalue_container<T>::value&&!is_set<T>::value&&!is_multiset<T>::value&&!is_unordered_set<T>::value>
{
t.push_back(v);
}
template<typename T, typename value_type>
auto push(T& t, value_type& v, std::size_t index) ->
std::enable_if_t<is_set<T>::value || is_multiset<T>::value || is_unordered_set<T>::value>
{
t.insert(v);
}
template<typename T, typename value_type>
auto push(T& t, value_type& v, std::size_t index) ->
std::enable_if_t<is_std_array<T>::value || std::is_array<T>::value>
{
t[index] = v;
}
template<typename T, typename value_type>
auto push(T& t, value_type& v, std::size_t index) ->
std::enable_if_t<is_container_adapter<T>::value || is_stack<T>::value>
{
t.push(v);
}
template<typename T, typename BeginObject>
auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::enable_if_t<is_map_container<T>::value>
{
using U = typename std::decay<T>::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<key_type>(it->name.GetString());
ReadObject(value, (rapidjson::Value&)it->value, std::true_type {});
t.emplace(key, value);
}
}
template<typename T, typename BeginObject>
auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::enable_if_t<is_basic_type<T>::value>
{
m_jsutil.ReadValue(std::forward<T>(t), v);
}
template<size_t N=0, typename T, typename BeginObject>
auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t<is_user_class<T>::value>
{
ReadObject(t, val, std::false_type{});
}
template<size_t N = 0, typename T, typename BeginObject>
auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t<is_optional<T>::value>
{
ReadObject(t, val, std::true_type{});
}
template<size_t N = 0, typename BeginObject, typename ... Args>
void ReadValue(variant<Args...>& v, rapidjson::Value& val, BeginObject obj)
{
//ReadObject(t, val, std::true_type{});
ReadObject(v, val, std::true_type{});
}
template <size_t N = 0, typename T, typename BeginObject>
auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t<std::is_enum<
std::remove_cv_t<std::remove_reference_t<T>>>::value>
{
using under_type = std::underlying_type_t<std::remove_cv_t<std::remove_reference_t<T>>>;
ReadObject(std::forward<under_type>(t), val, std::true_type{});
}
template<size_t N = 0, typename T>
auto ReadObject(T&& t, rapidjson::Value& val, std::true_type bo) -> std::enable_if_t<is_pair<T>::value>
{
using pair_t = std::remove_cv_t<std::remove_reference_t<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<first_type>(itr->name.GetString());
ReadObject(t.second, itr->value, bo);
}
template<size_t N = 0, typename T>
auto ReadObject(T&& t, rapidjson::Value& val, std::false_type bo) -> std::enable_if_t<is_pair<T>::value>
{
ReadObject(t.second, val, bo);
}
template<size_t N = 0, typename T, typename BeginObject>
auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::enable_if_t<is_basic_type<T>::value>
{
m_jsutil.ReadValue(std::forward<T>(t), val);
}
template<size_t N = 0, typename T>
auto ReadValue(T&& t, rapidjson::Value& val, std::false_type bo) -> std::enable_if_t<is_tuple<T>::value>
{
//assert(!val.IsArray());
if(val.IsArray())
throw std::invalid_argument("should not be array");
decltype(auto) tuple_elem = std::get<N>(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<size_t N = 0, typename T>
auto ReadValue(T&& t, rapidjson::Value& val, std::true_type bo) -> std::enable_if_t<is_tuple<T>::value>
{
//assert(val.IsArray());
if (!val.IsArray())
throw std::invalid_argument("should be array");
ReadObject(std::get<N>(t), val[N], bo);
}
// functions for variant
private:
template <int Index, typename ... Args>
void LoadVariantImplFunc(rapidjson::Value& value, variant<Args...>& v)
{
using index_type = boost::mpl::int_<Index>;
using value_type = typename boost::mpl::at<typename variant<Args...>::types, index_type>::type;
value_type temp;
ReadObject(temp, value, std::true_type{});
v = temp;
}
template <int Begin, int End>
struct LoadVariantImpl
{
template <typename Variant>
void operator() (DeSerializer& dr, rapidjson::Value& value, size_t index, Variant& v)
{
if (Begin == index)
{
dr.LoadVariantImplFunc<Begin>(value, v);
return;
}
LoadVariantImpl<Begin + 1, End>{}(dr, value, index, v);
}
};
template <int End>
struct LoadVariantImpl<End, End>
{
template <typename Variant>
void operator() (DeSerializer& dr,rapidjson::Value& value, size_t index, Variant& v)
{
if (End == index)
{
dr.LoadVariantImplFunc<End>(value, v);
return;
}
throw std::invalid_argument{ "Wrong variant types." };
}
};
template <typename ... Args>
void LoadVariant(rapidjson::Value& value, size_t index, variant<Args...>& v)
{
LoadVariantImpl<0, sizeof...(Args) - 1>{}(*this, value, index, v);
}
private:
JsonUtil m_jsutil;
};
} // namespace kapok
================================================
FILE: kapok/JsonUtil.hpp
================================================
#pragma once
#include <string>
#include <cstdint>
#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<rapidjson::StringBuffer> JsonWriter;
public:
JsonUtil() : m_writer(m_buf)
{
}
template<typename T>
void WriteJson(const char* key, T&& value)
{
m_writer.String(key);
WriteValue(std::forward<T>(value));
}
template<typename T>
void WriteJson(const std::string& key, T&& value)
{
m_writer.String(key.c_str());
WriteValue(std::forward<T>(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<double>(val));
}
void ReadValue(float& t, rapidjson::Value& val)
{
if(val.IsNumber())
t = static_cast<float>(val.GetDouble());
}
template<typename T>
typename std::enable_if<std::is_same<T, bool>::value>::type WriteValue(T val)
{
m_writer.Bool(val);
}
//还要过滤智能指针的情况.
template<typename T>
typename std::enable_if<is_pointer_ext<T>::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 <typeinfo>
#ifndef _MSC_VER
#include <cxxabi.h>
#endif
#include "traits.hpp"
#include "Common.hpp"
#include "JsonUtil.hpp"
#include <boost/lexical_cast.hpp>
#include <fmt/format.h>
namespace kapok {
class Serializer : NonCopyable
{
public:
Serializer()
{
}
~Serializer()
{
}
const char* GetString()
{
return m_jsutil.GetJsonText();
}
//template<typename T>
//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<typename T>
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<typename T>
void SerializeImpl(T const& t, const char* key)
{
m_jsutil.StartObject();
m_jsutil.WriteValue(key);
WriteObject(t, std::true_type{});
m_jsutil.EndObject();
}
template<typename T>
const char* type_name()
{
#ifndef _MSC_VER
return abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
#else
return typeid(T).name();
#endif
}
template<typename T>
const char* get_type_name()
{
const char* name = type_name<T>();
return has_space(name) ? "temp" : type_name<T>();
}
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 <typename T, typename BeginObjec>
std::enable_if_t<is_optional<T>::value> WriteObject(T const& t, BeginObjec bj)
{
if (static_cast<bool>(t))
{
WriteObject(*t, bj);
}
else
{
WriteNull();
}
}
//template<typename T>
//typename std::enable_if<is_user_class<T>::value>::type WriteObject(T&& t)
//{
// m_jsutil.StartObject();
// WriteTuple(t.Meta());
// m_jsutil.EndObject();
//}
// variant visitor
template <typename BeginObj>
struct serialize_visitor : boost::static_visitor<>
{
explicit serialize_visitor(Serializer& s, int which)
: s_(s)
, which_(which - 1)
{
}
template <typename T>
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 <typename BeginObj, typename ... Args>
void WriteObject(variant<Args...> const& v, BeginObj bj)
{
if (static_cast<bool>(v))
{
//WriteObject(*t, bj);
boost::apply_visitor(serialize_visitor<BeginObj>{ *this, v.which() }, v);
}
else
{
WriteNull();
}
}
template<typename T, typename BeginObjec>
typename std::enable_if<is_user_class<T>::value>::type WriteObject(const T& t, BeginObjec)
{
m_jsutil.StartObject();
WriteTuple(((T&)t).Meta());
m_jsutil.EndObject();
}
template<typename T, typename BeginObjec>
typename std::enable_if<is_tuple<T>::value>::type WriteObject(T const& t, BeginObjec)
{
m_jsutil.StartArray();
WriteTuple(t);
m_jsutil.EndArray();
}
template<std::size_t I = 0, typename Tuple>
typename std::enable_if<I == std::tuple_size<Tuple>::value>::type WriteTuple(const Tuple& t)
{
}
template<std::size_t I = 0, typename Tuple>
typename std::enable_if<I < std::tuple_size<Tuple>::value>::type WriteTuple(const Tuple& t)
{
WriteObject(std::get<I>(t), std::false_type{});
WriteTuple<I + 1>(t);
}
template<typename T, typename BeginObjec>
typename std::enable_if<is_singlevalue_container<T>::value>::type WriteObject(T const& t, BeginObjec)
{
WriteArray(t);
}
template <typename Adaptor, typename F>
auto WriteAdaptor(Adaptor&& adaptor, F get)
{
using adaptor_t = std::remove_cv_t<std::remove_reference_t<Adaptor>>;
adaptor_t temp = std::forward<Adaptor>(adaptor);
m_jsutil.StartArray();
while (!temp.empty())
{
WriteObject(get(temp), std::false_type{});
temp.pop();
}
m_jsutil.EndArray();
}
template <typename T, typename BeginObject>
auto WriteObject(T&& t, BeginObject) -> std::enable_if_t<is_queue<T>::value>
{
WriteAdaptor(std::forward<T>(t), [](auto const& adaptor) { return adaptor.front(); });
}
template<typename T, typename BeginObject>
auto WriteObject(T&& t, BeginObject) -> std::enable_if_t<is_stack<T>::value || is_priority_queue<T>::value>
{
WriteAdaptor(std::forward<T>(t), [](auto const& adaptor) { return adaptor.top(); });
}
template<typename T, typename BeginObject>
typename std::enable_if<is_map_container<T>::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 T>
typename std::enable_if<is_pair<T>::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 T>
typename std::enable_if<is_pair<T>::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<typename T, size_t N, typename BeginObject>
void WriteObject(std::array<T, N> const& t, BeginObject)
{
WriteArray(t);
}
template <typename T, size_t N, typename BeginObject>
void WriteObject(T const(&p)[N], BeginObject)
{
WriteArray(p);
}
template <size_t N, typename BeginObject>
void WriteObject(char const(&p)[N], BeginObject bj)
{
WriteObject((const char*)p, bj);
}
//template <size_t N>
//void WriteObject(char const(&p)[N], std::false_type)
//{
// WriteObject((const char*)p, bj);
//}
template<typename Array>
inline void WriteArray(Array const& v)
{
m_jsutil.StartArray();
for (auto const& i : v)
{
WriteObject(i, std::false_type{});
}
m_jsutil.EndArray();
}
template<typename T, typename BeginObject>
typename std::enable_if<is_basic_type<T>::value>::type WriteObject(T const& t, BeginObject)
{
m_jsutil.WriteValue(t);
}
template <typename T, typename BeginObject>
auto WriteObject(T const& val, BeginObject) ->std::enable_if_t<std::is_enum<
std::remove_reference_t<std::remove_cv_t<T>>>::value>
{
using under_type = std::underlying_type_t<
std::remove_reference_t<std::remove_cv_t<T>>>;
m_jsutil.WriteValue(static_cast<under_type>(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 T>
//typename std::enable_if<is_normal_class<T>::value>::type WriteValue(T&& t)
//{
// WriteKV(boost::lexical_cast<std::string>(t.first).c_str(), t.second);
//}
template<typename V>
void WriteKV(const char* k, V& v)
{
m_jsutil.WriteValue(k);
WriteObject(v, std::true_type{});
}
template<typename V>
void BeginWriteKV(const char* k, V& v)
{
m_jsutil.StartObject();
WriteKV(k, v);
m_jsutil.EndObject();
}
template<typename T, typename BeginObject>
typename std::enable_if<is_basic_type<T>::value>::type WriteValue(T const& t, BeginObject)
{
m_jsutil.WriteValue(std::forward<T>(t));
}
void WriteNull()
{
m_jsutil.WriteNull();
}
private:
JsonUtil m_jsutil;
fmt::MemoryWriter m_wr;
};
} // namespace kapok
================================================
FILE: kapok/traits.hpp
================================================
#pragma once
#include <memory>
#include <type_traits>
#include <vector>
#include <array>
#include <queue>
#include <stack>
#include <set>
#include <unordered_set>
#include <boost/optional.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/remove.hpp>
//using namespace std;
namespace kapok {
template <typename ... Args>
struct variant : boost::variant<boost::blank, Args...>
{
using base_type = boost::variant<boost::blank, Args...>;
using types = typename boost::mpl::remove<typename base_type::types, boost::blank>::type;
explicit operator bool() const
{
return this->which() != 0;
}
template <typename T>
variant& operator= (T&& t)
{
return static_cast<variant&>(
static_cast<base_type&>(*this) = std::forward<T>(t));
}
bool operator== (variant const& other) const
{
return static_cast<base_type const&>(*this) == static_cast<base_type const&>(other);
}
bool operator!= (variant const& other) const
{
return !(*this == other);
}
bool operator< (variant const& other) const
{
return static_cast<base_type const&>(*this) < static_cast<base_type const&>(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<typename T>
using decay_t = typename std::decay<T>::type;
//template<typename T> std::false_type static check_tuple_size(...);
//template<typename T> std::true_type static check_tuple_size(decltype(std::tuple_size<T>::value)*);
template < template <typename...> class U, typename T >
struct is_instantiation_of : std::false_type {};
template < template <typename...> class U, typename... Args >
struct is_instantiation_of< U, U<Args...> > : std::true_type {};
template<typename T>
struct is_tuple : is_instantiation_of<std::tuple, T>
{
};
//has_begin_end
template<typename T>
struct has_begin_end
{
private:
template<typename U> static auto Check(int) -> decltype(std::declval<U>().begin(), std::declval<U>().end(), std::true_type());
template<typename U> static std::false_type Check(...);
public:
enum
{
value = std::is_same<decltype(Check<T>(0)), std::true_type>::value
};
};
template <typename T>
struct has_const_iterator
{
private:
template<typename C> static std::true_type Check(typename C::const_iterator*);
template<typename C> static std::false_type Check(...);
public:
enum
{
value = std::is_same<decltype(Check<T>(0)), std::true_type>::value
};
};
template <typename T>
struct has_mapped_type
{
private:
template<typename C> static std::true_type Check(typename C::mapped_type*);
template<typename C> static std::false_type Check(...);
public:
enum
{
value = std::is_same<decltype(Check<T>(0)), std::true_type>::value
};
};
//#define HAS_XXX_TYPE(token)
// template <typename T>struct has_##token{
// private:
// template<typename C> static std::true_type Check(typename C::token##*);
// template<typename C> static std::false_type Check(...);
// public:
// enum
// {
// value = std::is_same<decltype(Check<T>(0)), std::true_type>::value
// };
// };
//
// HAS_XXX_TYPE(const_iterator)
// HAS_XXX_TYPE(mapped_type)
template<typename T> struct is_poiner_extent : std::false_type{};
template<typename T> struct is_poiner_extent<std::shared_ptr<T>> : std::true_type{};
template<typename T> struct is_poiner_extent<std::unique_ptr<T>> : std::true_type{};
template<typename T> struct is_poiner_extent<std::weak_ptr<T>> : std::true_type{};
//#define IS_SMART_POINTER(token)
// template<typename T> struct is_poiner_extent<std::token##_ptr<T>> : std::true_type{};
//
// IS_SMART_POINTER(shared)
// IS_SMART_POINTER(unique)
// IS_SMART_POINTER(weak)
}
template <typename Arary>
struct is_std_array : std::false_type {};
template <typename T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {};
template<typename T>
struct is_string : std::integral_constant<bool, std::is_same<detail::decay_t<T>, std::string>::value>{};
template <typename T>
struct is_container : public std::integral_constant<bool, detail::has_const_iterator<detail::decay_t<T>>::value&&detail::has_begin_end<detail::decay_t<T>>::value&&!is_string<T>::value>{};
template <typename T>
struct is_singlevalue_container : public std::integral_constant<bool, !is_std_array<T>::value&&!std::is_array<detail::decay_t<T>>::value&&!detail::is_tuple<detail::decay_t<T>>::value && is_container<detail::decay_t<T>>::value&&!detail::has_mapped_type<detail::decay_t<T>>::value>{};
template <typename T>
struct is_map_container : public std::integral_constant<bool, is_container<detail::decay_t<T>>::value&&detail::has_mapped_type<detail::decay_t<T>>::value>{};
template<typename T>
struct is_normal_class : std::integral_constant<bool, std::is_class<detail::decay_t<T>>::value&&!is_string<T>::value>
{};
template<typename T>
struct is_basic_type : std::integral_constant<bool, std::is_arithmetic<detail::decay_t<T>>::value || is_string<T>::value>
{};
template<typename T>
struct is_smart_pointer : detail::is_poiner_extent<detail::decay_t<T>>{};
template<typename T>
struct is_pointer_ext : std::integral_constant<bool, std::is_pointer<detail::decay_t<T>>::value || is_smart_pointer<detail::decay_t<T>>::value>{};
template <typename T, template <typename...> class Template>
struct is_specialization_of : std::false_type {};
template <template <typename...> class Template, typename... Args>
struct is_specialization_of<Template<Args...>, Template> : std::true_type{};
template <typename T> struct is_optional : is_specialization_of<detail::decay_t<T>, boost::optional> {};
template <typename T> struct is_tuple : is_specialization_of<detail::decay_t<T>, std::tuple>{};
template <typename T> struct is_queue : is_specialization_of<detail::decay_t<T>, std::queue>{};
template <typename T> struct is_stack : is_specialization_of<detail::decay_t<T>, std::stack>{};
template <typename T> struct is_set : is_specialization_of<detail::decay_t<T>, std::set> {};
template <typename T> struct is_multiset : is_specialization_of<detail::decay_t<T>, std::multiset> {};
template <typename T> struct is_unordered_set : is_specialization_of<detail::decay_t<T>, std::unordered_set> {};
template <typename T> struct is_priority_queue : is_specialization_of<detail::decay_t<T>, std::priority_queue>{};
template <typename T> struct is_pair : is_specialization_of<detail::decay_t<T>, std::pair> {};
template <typename T> struct is_variant : is_specialization_of<detail::decay_t<T>, variant> {};
//#define IS_TEMPLATE_CLASS(token)
//template<typename T> struct is_##token : is_specialization_of<detail::decay_t<T>, std::token##>{};
//
//IS_TEMPLATE_CLASS(tuple)
//IS_TEMPLATE_CLASS(queue)
//IS_TEMPLATE_CLASS(stack)
//IS_TEMPLATE_CLASS(priority_queue)
template<typename T>
struct is_container_adapter : std::integral_constant<bool, is_queue<T>::value || is_priority_queue<T>::value>
{
};
template<typename T>
struct is_user_class : std::integral_constant<bool, is_normal_class<T>::value&&!is_container_adapter<T>::value
&&!is_stack<T>::value&&!is_container<T>::value&&!is_tuple<T>::value&&!is_pair<T>::value&&!is_optional<T>::value>
{};
} // namespace kapok
================================================
FILE: main.cpp
================================================
#include <array>
#include <vector>
#include <string>
#include <set>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <iostream>
#include "kapok/Kapok.hpp"
#include <boost/timer.hpp>
#include "test_kapok.hpp"
void test()
{
kapok::Serializer sr;
kapok::DeSerializer dr;
auto tp = std::make_tuple(10, 12, std::string("test"));
sr.Serialize(tp, "tuple");
dr.Parse(sr.GetString());
std::tuple<int, int, std::string> p;
dr.Deserialize(p, "tuple");
}
template<class T>
void test_array( T& arr)
{
using namespace kapok;
Serializer sr;
sr.Serialize(arr, "test");
std::cout << sr.GetString() << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
T de_arr;
dr.Deserialize(de_arr, "test");
}
template<class T>
void test_map( T& map)
{
using namespace kapok;
Serializer sr;
sr.Serialize(map, "test");
std::cout << sr.GetString() << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
T de_map;
dr.Deserialize(de_map, "test");
}
struct person
{
int age;
std::string name;
//META(age, name);
META(age, name);
};
template<class T>
void test_object(T& t)
{
using namespace kapok;
Serializer sr;
sr.Serialize(t, "test");
std::cout << sr.GetString() << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
T de_t;
dr.Deserialize(de_t, "test");
}
struct test_p
{
int a;
std::string b;
std::map<std::string, int> c;
person d;
META(a, b, c, d);
};
struct complex_t
{
int a;
std::string b;
std::map<std::string, person> c;
std::map<std::string, std::vector<person>> d;
std::vector<std::map<std::string, std::vector<person>>> e;
META(a, b, c, d, e);
};
struct complex_t1
{
int a;
std::map<std::string, std::array<person, 2>> d;
META(a, d);
};
void test_recurse1()
{
using namespace kapok;
complex_t1 cpl = { 1,{ { { "d",{ { { 20, "tom" },{ 20, "tom" } } } } } } };
Serializer sr;
sr.Serialize(cpl, "test");
std::string str = sr.GetString();
std::cout << str << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
complex_t1 de_t;
dr.Deserialize(de_t, "test");
}
void test_recurse()
{
using namespace kapok;
complex_t cpl = { 1,"b", {{"c", {20, "tom"}}}, /*{{"d", {{{20, "tom"},{ 20, "tom" } }}}}, */{ { { "d",{ { { 20, "tom" },{ 20, "tom" } } } } } } };
Serializer sr;
sr.Serialize(cpl, "test");
std::string str = sr.GetString();
std::cout << str << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
complex_t de_t;
dr.Deserialize(de_t, "test");
}
void test_new_meta()
{
using namespace kapok;
std::map<std::string, int> mp = { {"aa", 2} };
test_p p = { 20, "test", {{ "aa", 2 }}, {12, "td"} };
//person p = { 20, "test" };
Serializer sr;
sr.Serialize(p, "test");
std::string str = sr.GetString();
std::cout << str << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
test_p de_t;
dr.Deserialize(de_t, "test");
}
void test_performance()
{
using namespace kapok;
person p = { 20, "test" };
Serializer sr;
const int LEN = 1000000;
boost::timer timer;
for (size_t i = 0; i < LEN; i++)
{
sr.Serialize(p, "test");
}
std::cout << timer.elapsed() << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
timer.restart();
for (size_t i = 0; i < LEN; i++)
{
person de_t;
dr.Deserialize(de_t, "test");
}
std::cout << timer.elapsed() << std::endl;
}
void test_tuple()
{
using namespace std;
using namespace kapok;
cout << is_basic_type<int>::value << endl;
cout << is_normal_class<int>::value << endl;
std::vector<int> v = { 1,2,3 };
std::tuple<vector<int>, int> tp = std::make_tuple(v, 2);
std::map<int, int> mp = { {1,2},{3,4} };
Serializer sr;
sr.Serialize(tp);
std::cout << sr.GetString() << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
std::tuple<vector<int>, int> tp1;
std::map<int, int> mp1;
dr.Deserialize(tp1);
}
struct my_person
{
std::vector<int> a;
int b;
META(a, b);
};
void test_myperson()
{
using namespace kapok;
my_person p = { {1,2,3}, 4 };
Serializer sr;
sr.Serialize(p);
std::cout << sr.GetString() << std::endl;
DeSerializer dr;
dr.Parse(sr.GetString());
my_person p1;
dr.Deserialize(p1);
}
struct T
{
int a;
char b;
META(a, b);
};
void test_simple()
{
using namespace kapok;
Serializer sr;
sr.Serialize((std::array<int, 5>{1, 2, 3, 4, 5}));
std::cout << sr.GetString() << std::endl;
T t{ 66, 'c' };
sr.Serialize(t, "T");
std::cout << sr.GetString() << std::endl;
}
void test_array()
{
using namespace kapok;
DeSerializer dr;
dr.Parse(R"({"array":[1,2,3,4,5]})");
std::array<int, 5> v;
std::array<int, 5> a{ 1, 2, 3, 4, 5 };
dr.Deserialize(v, "array");
}
void test_const(const person& p)
{
using namespace kapok;
Serializer sr;
sr.Serialize(p);
std::cout << sr.GetString() << std::endl;
}
void test_stack()
{
using namespace kapok;
DeSerializer dr;
dr.Parse(R"({"stack":[1,2,3,4,5]})");
std::stack<int> v;
dr.Deserialize(v, "stack");
for (int i = 0; i < 5; ++i)
{
if(v.top()==i+1)
std::cout << "ok" << std::endl;
v.pop();
}
}
struct messager
{
int code;
int id;
META(code, id);
};
void test_sr()
{
using namespace kapok;
messager m = { 1,2 };
Serializer sr;
sr.Serialize(m);
std::cout << sr.GetString() << std::endl;
}
void test_str()
{
using namespace kapok;
Serializer sr;
sr.Serialize("hello, world", "string value");
std::cout << sr.GetString() << std::endl;
}
void test_optional()
{
using namespace std::string_literals;
using namespace kapok;
struct test_optional_struct
{
int a;
float b;
boost::optional<std::string> str;
META(a, b, str);
};
// init without init test_optional_struct::str
boost::optional<test_optional_struct> to_sr = test_optional_struct{ 1, 1.0f };
Serializer sr;
sr.Serialize(to_sr);
std::cout << sr.GetString() << std::endl;
DeSerializer ds;
ds.Parse(sr.GetString());
boost::optional<test_optional_struct> to_ds;
ds.Deserialize(to_ds);
bool test_pass =
to_ds->a == to_sr->a &&
to_ds->b == to_sr->b &&
to_ds->str == to_sr->str;
//full init
to_sr = test_optional_struct{ 3, 2.0f, "hello optional"s };
sr.Serialize(to_sr);
std::cout << sr.GetString() << std::endl;
ds.Parse(sr.GetString());
to_ds.reset();
ds.Deserialize(to_ds);
test_pass =
to_ds->a == to_sr->a &&
to_ds->b == to_sr->b &&
to_ds->str == to_sr->str;
}
enum class foo_enum
{
hahahaha = 0,
jinkela = 1,
};
void test_enum()
{
using namespace kapok;
{
Serializer sr;
foo_enum aha = foo_enum::hahahaha;
sr.Serialize(aha);
std::cout << sr.GetString() << std::endl;
DeSerializer ds;
ds.Parse(sr.GetString());
foo_enum r;
ds.Deserialize(r);
assert(r == aha);
}
struct test_enum_t
{
foo_enum a;
int b;
META(a, b);
};
{
Serializer sr;
test_enum_t foo = { foo_enum::jinkela, 8 };
sr.Serialize(foo);
std::cout << sr.GetString() << std::endl;
DeSerializer ds;
ds.Parse(sr.GetString());
test_enum_t r;
ds.Deserialize(r);
assert(r.a == foo.a && r.b == foo.b);
}
}
void test_pair()
{
using namespace kapok;
std::pair<int, double> p = { 1, 0.2 };
std::pair<int, double> r;
Serializer sr;
sr.Serialize(p);
auto result = sr.GetString();
std::cout << result << std::endl;
DeSerializer ds;
ds.Parse(result);
ds.Deserialize(r);
assert(p.first == r.first && p.second == r.second);
}
void test_variant()
{
using namespace kapok;
Serializer sr;
variant<int, double, std::pair<float, std::string>> a, b;
a = std::make_pair(6.28, "zhengwei");
sr.Serialize(a);
auto result = sr.GetString();
std::cout << result << std::endl;
DeSerializer ds;
ds.Parse(result);
ds.Deserialize(b);
auto r = boost::get<std::pair<float, std::string>>(a) == boost::get<std::pair<float, std::string>>(b);
assert(r);
}
TEST_CASE(example)
{
test_pair();
test_sr();
test_str();
test_stack();
person p1 = { 20, "aa" };
test_const(p1);
test_array();
test_simple();
test_myperson();
// test_performance();
test_tuple();
test_recurse1();
test_recurse();
test_new_meta();
std::array<std::string, 5> arr = { "a","b","c", "d", "e" };
test_array(arr);
std::vector<std::string> vt = { "a","b","c", "d", "e" };
test_array(vt);
int int_arr[5] = { 1,2,3,4,5 };
test_array(int_arr);
std::string str_arr[5] = { "a","b","c", "d", "e" };
test_array(str_arr);
std::queue<std::string> que_arr;
que_arr.emplace("a");
que_arr.emplace("b");
test_array(que_arr);
std::deque<std::string> deque_arr;
deque_arr.push_back("a");
deque_arr.push_back("b");
test_array(deque_arr);
std::priority_queue<std::string> priodeque_arr;
priodeque_arr.push("a");
priodeque_arr.push("b");
test_array(priodeque_arr);
std::set<std::string> set_arr;
set_arr.emplace("a");
set_arr.emplace("b");
test_array(set_arr);
std::multiset<std::string> multiset_arr;
multiset_arr.emplace("a");
multiset_arr.emplace("b");
test_array(multiset_arr);
std::unordered_set<std::string> unordset_arr;
unordset_arr.emplace("a");
unordset_arr.emplace("b");
test_array(unordset_arr);
std::stack<std::string> stack_arr;
stack_arr.emplace("a");
stack_arr.emplace("b");
test_array(stack_arr);
std::map<int, std::string> map = { {1, "a"},{2, "b"} };
test_map(map);
std::multimap<int, std::string> multimap = { { 1, "a" },{ 2, "b" } };
test_map(multimap);
std::unordered_map<int, std::string> unodermap = { { 1, "a" },{ 2, "b" } };
test_map(unodermap);
std::map<std::string, int> map1 = { { "a", 1 },{ "b", 2 } };
test_map(map1);
person p = { 20, "test" };
test_object(p);
std::map<std::string, person> map2= { {"a", p} };
test_map(map2);
test_optional();
test_enum();
test_variant();
}
================================================
FILE: rapidjson/allocators.h
================================================
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// 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.
#ifndef RAPIDJSON_ALLOCATORS_H_
#define RAPIDJSON_ALLOCATORS_H_
#include "rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
// Allocator
/*! \class rapidjson::Allocator
\brief Concept for allocating, resizing and freeing memory block.
Note that Malloc() and Realloc() are non-static but Free() is static.
So if an allocator need to support Free(), it needs to put its pointer in
the header of memory block.
\code
concept Allocator {
static const bool kNeedFree; //!< Whether this allocator needs to call Free().
// Allocate a memory block.
// \param size of the memory block in bytes.
// \returns pointer to the memory block.
void* Malloc(size_t size);
// Resize a memory block.
// \param originalPtr The pointer to current memory block. Null pointer is permitted.
// \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
// \param newSize the new size in bytes.
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
// Free a memory block.
// \param pointer to the memory block. Null pointer is permitted.
static void Free(void *ptr);
};
\endcode
*/
///////////////////////////////////////////////////////////////////////////////
// CrtAllocator
//! C-runtime library allocator.
/*! This class is just wrapper for standard C library memory routines.
\note implements Allocator concept
*/
class CrtAllocator {
public:
static const bool kNeedFree = true;
void* Malloc(size_t size) {
if (size) // behavior of malloc(0) is implementation defined.
return std::malloc(size);
else
return NULL; // standardize to returning NULL.
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
(void)originalSize;
if (newSize == 0) {
std::free(originalPtr);
return NULL;
}
return std::realloc(originalPtr, newSize);
}
static void Free(void *ptr) { std::free(ptr); }
};
///////////////////////////////////////////////////////////////////////////////
// MemoryPoolAllocator
//! Default memory allocator used by the parser and DOM.
/*! This allocator allocate memory blocks from pre-allocated memory chunks.
It does not free memory blocks. And Realloc() only allocate new memory.
The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
User may also supply a buffer as the first chunk.
If the user-buffer is full then additional chunks are allocated by BaseAllocator.
The user-buffer is not deallocated by this allocator.
\tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
\note implements Allocator concept
*/
template <typename BaseAllocator = CrtAllocator>
class MemoryPoolAllocator {
public:
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
//! Constructor with chunkSize.
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks.
*/
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
{
}
//! Constructor with user-supplied buffer.
/*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
The user buffer will not be deallocated when this allocator is destructed.
\param buffer User supplied buffer.
\param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks.
*/
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
{
RAPIDJSON_ASSERT(buffer != 0);
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
chunkHead_->capacity = size - sizeof(ChunkHeader);
chunkHead_->size = 0;
chunkHead_->next = 0;
}
//! Destructor.
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
*/
~MemoryPoolAllocator() {
Clear();
RAPIDJSON_DELETE(ownBaseAllocator_);
}
//! Deallocates all memory chunks, excluding the user-supplied buffer.
void Clear() {
while (chunkHead_ && chunkHead_ != userBuffer_) {
ChunkHeader* next = chunkHead_->next;
baseAllocator_->Free(chunkHead_);
chunkHead_ = next;
}
if (chunkHead_ && chunkHead_ == userBuffer_)
chunkHead_->size = 0; // Clear user buffer
}
//! Computes the total capacity of allocated memory chunks.
/*! \return total capacity in bytes.
*/
size_t Capacity() const {
size_t capacity = 0;
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
capacity += c->capacity;
return capacity;
}
//! Computes the memory blocks allocated.
/*! \return total used bytes.
*/
size_t Size() const {
size_t size = 0;
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
size += c->size;
return size;
}
//! Allocates a memory block. (concept Allocator)
void* Malloc(size_t size) {
if (!size)
return NULL;
size = RAPIDJSON_ALIGN(size);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
chunkHead_->size += size;
return buffer;
}
//! Resizes a memory block (concept Allocator)
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
if (originalPtr == 0)
return Malloc(newSize);
if (newSize == 0)
return NULL;
originalSize = RAPIDJSON_ALIGN(originalSize);
newSize = RAPIDJSON_ALIGN(newSize);
// Do not shrink if new size is smaller than original
if (originalSize >= newSize)
return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space
if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
size_t increment = static_cast<size_t>(newSize - originalSize);
if (chunkHead_->size + increment <= chunkHead_->capacity) {
chunkHead_->size += increment;
return originalPtr;
}
}
// Realloc process: allocate and copy memory, do not free original buffer.
void* newBuffer = Malloc(newSize);
RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
if (originalSize)
std::memcpy(newBuffer, originalPtr, originalSize);
return newBuffer;
}
//! Frees a memory block (concept Allocator)
static void Free(void *ptr) { (void)ptr; } // Do nothing
private:
//! Copy constructor is not permitted.
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
//! Copy assignment operator is not permitted.
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
*/
void AddChunk(size_t capacity) {
if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity));
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
chunkHead_ = chunk;
}
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
//! Chunk header for perpending to each chunk.
/*! Chunks are stored as a singly linked list.
*/
struct ChunkHeader {
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
size_t size; //!< Current size of allocated memory in bytes.
ChunkHeader *next; //!< Next chunk in the linked list.
};
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
void *userBuffer_; //!< User supplied buffer.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
};
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_ENCODINGS_H_
================================================
FILE: rapidjson/document.h
================================================
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// 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.
#ifndef RAPIDJSON_DOCUMENT_H_
#define RAPIDJSON_DOCUMENT_H_
/*! \file document.h */
#include "reader.h"
#include "internal/meta.h"
#include "internal/strfunc.h"
#include "memorystream.h"
#include "encodedstream.h"
#include <new> // placement new
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
#endif
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(c++98-compat)
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include <iterator> // std::iterator, std::random_access_iterator_tag
#endif
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#include <utility> // std::move
#endif
RAPIDJSON_NAMESPACE_BEGIN
// Forward declaration.
template <typename Encoding, typename Allocator>
class GenericValue;
template <typename Encoding, typename Allocator, typename StackAllocator>
class GenericDocument;
//! Name-value pair in a JSON object value.
/*!
This class was internal to GenericValue. It used to be a inner struct.
But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
https://code.google.com/p/rapidjson/issues/detail?id=64
*/
template <typename Encoding, typename Allocator>
struct GenericMember {
GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
GenericValue<Encoding, Allocator> value; //!< value of member.
};
///////////////////////////////////////////////////////////////////////////////
// GenericMemberIterator
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
//! (Constant) member iterator for a JSON object value
/*!
\tparam Const Is this a constant iterator?
\tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
\tparam Allocator Allocator type for allocating memory of object, array and string.
This class implements a Random Access Iterator for GenericMember elements
of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
\note This iterator implementation is mainly intended to avoid implicit
conversions from iterator values to \c NULL,
e.g. from GenericValue::FindMember.
\note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
pointer-based implementation, if your platform doesn't provide
the C++ <iterator> header.
\see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
*/
template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator
: public std::iterator<std::random_access_iterator_tag
, typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
friend class GenericValue<Encoding,Allocator>;
template <bool, typename, typename> friend class GenericMemberIterator;
typedef GenericMember<Encoding,Allocator> PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
public:
//! Iterator type itself
typedef GenericMemberIterator Iterator;
//! Constant iterator type
typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
//! Non-constant iterator type
typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
//! Pointer to (const) GenericMember
typedef typename BaseType::pointer Pointer;
//! Reference to (const) GenericMember
typedef typename BaseType::reference Reference;
//! Signed integer type (e.g. \c ptrdiff_t)
typedef typename BaseType::difference_type DifferenceType;
//! Default constructor (singular value)
/*! Creates an iterator pointing to no element.
\note All operations, except for comparisons, are undefined on such values.
*/
GenericMemberIterator() : ptr_() {}
//! Iterator conversions to more const
/*!
\param it (Non-const) iterator to copy from
Allows the creation of an iterator from another GenericMemberIterator
that is "less const". Especially, creating a non-constant iterator
from a constant iterator are disabled:
\li const -> non-const (not ok)
\li const -> const (ok)
\li non-const -> const (ok)
\li non-const -> non-const (ok)
\note If the \c Const template parameter is already \c false, this
constructor effectively defines a regular copy-constructor.
Otherwise, the copy constructor is implicitly defined.
*/
GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }
//! @name stepping
//@{
Iterator& operator++(){ ++ptr_; return *this; }
Iterator& operator--(){ --ptr_; return *this; }
Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
//@}
//! @name increment/decrement
//@{
Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
//@}
//! @name relations
//@{
bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
//@}
//! @name dereference
//@{
Reference operator*() const { return *ptr_; }
Pointer operator->() const { return ptr_; }
Reference operator[](DifferenceType n) const { return ptr_[n]; }
//@}
//! Distance
DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
private:
//! Internal constructor from plain pointer
explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
Pointer ptr_; //!< raw pointer
};
#else // RAPIDJSON_NOMEMBERITERATORCLASS
// class-based member iterator implementation disabled, use plain pointers
template <bool Const, typename Encoding, typename Allocator>
struct GenericMemberIterator;
//! non-const GenericMemberIterator
template <typename Encoding, typename Allocator>
struct GenericMemberIterator<false,Encoding,Allocator> {
//! use plain pointer as iterator type
typedef GenericMember<Encoding,Allocator>* Iterator;
};
//! const GenericMemberIterator
template <typename Encoding, typename Allocator>
struct GenericMemberIterator<true,Encoding,Allocator> {
//! use plain const pointer as iterator type
typedef const GenericMember<Encoding,Allocator>* Iterator;
};
#endif // RAPIDJSON_NOMEMBERITERATORCLASS
///////////////////////////////////////////////////////////////////////////////
// GenericStringRef
//! Reference to a constant string (not taking a copy)
/*!
\tparam CharType character type of the string
This helper class is used to automatically infer constant string
references for string literals, especially from \c const \b (!)
character arrays.
The main use is for creating JSON string values without copying the
source string via an \ref Allocator. This requires that the referenced
string pointers have a sufficient lifetime, which exceeds the lifetime
of the associated GenericValue.
\b Example
\code
Value v("foo"); // ok, no need to copy & calculate length
const char foo[] = "foo";
v.SetString(foo); // ok
const char* bar = foo;
// Value x(bar); // not ok, can't rely on bar's lifetime
Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
Value y(StringRef(bar, 3)); // ok, explicitly pass length
\endcode
\see StringRef, GenericValue::SetString
*/
template<typename CharType>
struct GenericStringRef {
typedef CharType Ch; //!< character type of the string
//! Create string reference from \c const character array
#ifndef __clang__ // -Wdocumentation
/*!
This constructor implicitly creates a constant string reference from
a \c const character array. It has better performance than
\ref StringRef(const CharType*) by inferring the string \ref length
from the array length, and also supports strings containing null
characters.
\tparam N length of the string, automatically inferred
\param str Constant character array, lifetime assumed to be longer
than the use of the string in e.g. a GenericValue
\post \ref s == str
\note Constant complexity.
\note There is a hidden, private overload to disallow references to
non-const character arrays to be created via this constructor.
By this, e.g. function-scope arrays used to be filled via
\c snprintf are excluded from consideration.
In such cases, the referenced string should be \b copied to the
GenericValue instead.
*/
#endif
template<SizeType N>
GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
: s(str), length(N-1) {}
//! Explicitly create string reference from \c const character pointer
#ifndef __clang__ // -Wdocumentation
/*!
This constructor can be used to \b explicitly create a reference to
a constant string pointer.
\see StringRef(const CharType*)
\param str Constant character pointer, lifetime assumed to be longer
than the use of the string in e.g. a GenericValue
\post \ref s == str
\note There is a hidden, private overload to disallow references to
non-const character arrays to be created via this constructor.
By this, e.g. function-scope arrays used to be filled via
\c snprintf are excluded from consideration.
In such cases, the referenced string should be \b copied to the
GenericValue instead.
*/
#endif
explicit GenericStringRef(const CharType* str)
: s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); }
//! Create constant string reference from pointer and length
#ifndef __clang__ // -Wdocumentation
/*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\param len length of the string, excluding the trailing NULL terminator
\post \ref s == str && \ref length == len
\note Constant complexity.
*/
#endif
GenericStringRef(const CharType* str, SizeType len)
: s(str), length(len) { RAPIDJSON_ASSERT(s != 0); }
GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
//! implicit conversion to plain CharType pointer
operator const Ch *() const { return s; }
const Ch* const s; //!< plain CharType pointer
const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
private:
//! Disallow construction from non-const array
template<SizeType N>
GenericStringRef(CharType (&str)[N]) /* = delete */;
};
//! Mark a character pointer as constant string
/*! Mark a plain character pointer as a "string literal". This function
can be used to avoid copying a character string to be referenced as a
value in a JSON GenericValue object, if the string's lifetime is known
to be valid long enough.
\tparam CharType Character type of the string
\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\return GenericStringRef string reference object
\relatesalso GenericStringRef
\see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
*/
template<typename CharType>
inline GenericStringRef<CharType> StringRef(const CharType* str) {
return GenericStringRef<CharType>(str, internal::StrLen(str));
}
//! Mark a character pointer as constant string
/*! Mark a plain character pointer as a "string literal". This function
can be used to avoid copying a character string to be referenced as a
value in a JSON GenericValue object, if the string's lifetime is known
to be valid long enough.
This version has better performance with supplied length, and also
supports string containing null characters.
\tparam CharType character type of the string
\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\param length The length of source string.
\return GenericStringRef string reference object
\relatesalso GenericStringRef
*/
template<typename CharType>
inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
return GenericStringRef<CharType>(str, SizeType(length));
}
#if RAPIDJSON_HAS_STDSTRING
//! Mark a string object as constant string
/*! Mark a string object (e.g. \c std::string) as a "string literal".
This function can be used to avoid copying a string to be referenced as a
value in a JSON GenericValue object, if the string's lifetime is known
to be valid long enough.
\tparam CharType character type of the string
\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\return GenericStringRef string reference object
\relatesalso GenericStringRef
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
template<typename CharType>
inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
}
#endif
///////////////////////////////////////////////////////////////////////////////
// GenericValue type traits
namespace internal {
template <typename T, typename Encoding = void, typename Allocator = void>
struct IsGenericValueImpl : FalseType {};
// select candidates according to nested encoding and allocator types
template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
: IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
// helper to match arbitrary GenericValue instantiations, including derived classes
template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
} // namespace internal
///////////////////////////////////////////////////////////////////////////////
// TypeHelper
namespace internal {
template <typename ValueType, typename T>
struct TypeHelper {};
template<typename ValueType>
struct TypeHelper<ValueType, bool> {
static bool Is(const ValueType& v) { return v.IsBool(); }
static bool Get(const ValueType& v) { return v.GetBool(); }
static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }
static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, int> {
static bool Is(const ValueType& v) { return v.IsInt(); }
static int Get(const ValueType& v) { return v.GetInt(); }
static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }
static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, unsigned> {
static bool Is(const ValueType& v) { return v.IsUint(); }
static unsigned Get(const ValueType& v) { return v.GetUint(); }
static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); }
static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, int64_t> {
static bool Is(const ValueType& v) { return v.IsInt64(); }
static int64_t Get(const ValueType& v) { return v.GetInt64(); }
static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); }
static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, uint64_t> {
static bool Is(const ValueType& v) { return v.IsUint64(); }
static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); }
static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, double> {
static bool Is(const ValueType& v) { return v.IsDouble(); }
static double Get(const ValueType& v) { return v.GetDouble(); }
static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); }
static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, float> {
static bool Is(const ValueType& v) { return v.IsFloat(); }
static float Get(const ValueType& v) { return v.GetFloat(); }
static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }
static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, const typename ValueType::Ch*> {
typedef const typename ValueType::Ch* StringType;
static bool Is(const ValueType& v) { return v.IsString(); }
static StringType Get(const ValueType& v) { return v.GetString(); }
static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); }
static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
};
#if RAPIDJSON_HAS_STDSTRING
template<typename ValueType>
struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
typedef std::basic_string<typename ValueType::Ch> StringType;
static bool Is(const ValueType& v) { return v.IsString(); }
static StringType Get(const ValueType& v) { return v.GetString(); }
static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
};
#endif
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::Array> {
typedef typename ValueType::Array ArrayType;
static bool Is(const ValueType& v) { return v.IsArray(); }
static ArrayType Get(ValueType& v) { return v.GetArray(); }
static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }
static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::ConstArray> {
typedef typename ValueType::ConstArray ArrayType;
static bool Is(const ValueType& v) { return v.IsArray(); }
static ArrayType Get(const ValueType& v) { return v.GetArray(); }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::Object> {
typedef typename ValueType::Object ObjectType;
static bool Is(const ValueType& v) { return v.IsObject(); }
static ObjectType Get(ValueType& v) { return v.GetObject(); }
static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::ConstObject> {
typedef typename ValueType::ConstObject ObjectType;
static bool Is(const ValueType& v) { return v.IsObject(); }
static ObjectType Get(const ValueType& v) { return v.GetObject(); }
};
} // namespace internal
// Forward declarations
template <bool, typename> class GenericArray;
template <bool, typename> class GenericObject;
///////////////////////////////////////////////////////////////////////////////
// GenericValue
//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
/*!
A JSON value can be one of 7 types. This class is a variant type supporting
these types.
Use the Value if UTF8 and default allocator
\tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
\tparam Allocator Allocator type for allocating memory of object, array and string.
*/
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
class GenericValue {
public:
//! Name-value pair in an object.
typedef GenericMember<Encoding, Allocator> Member;
typedef Encoding EncodingType; //!< Encoding type from template parameter.
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself.
typedef GenericArray<false, ValueType> Array;
typedef GenericArray<true, ValueType> ConstArray;
typedef GenericObject<false, ValueType> Object;
typedef GenericObject<true, ValueType> ConstObject;
//!@name Constructors and destructor.
//@{
//! Default constructor creates a null value.
GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
rhs.data_.f.flags = kNullFlag; // give up contents
}
#endif
private:
//! Copy constructor is not permitted.
GenericValue(const GenericValue& rhs);
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Moving from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
//! Move assignment from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
#endif
public:
//! Constructor with JSON value type.
/*! This creates a Value of specified type with default content.
\param type Type of the value.
\note Default content for number is zero.
*/
explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
static const uint16_t defaultFlags[7] = {
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
kNumberAnyFlag
};
RAPIDJSON_ASSERT(type <= kNumberType);
data_.f.flags = defaultFlags[type];
// Use ShortString to store empty string.
if (type == kStringType)
data_.ss.SetLength(0);
}
//! Explicit copy constructor (with allocator)
/*! Creates a copy of a Value by using the given Allocator
\tparam SourceAllocator allocator of \c rhs
\param rhs Value to copy from (read-only)
\param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
\see CopyFrom()
*/
template< typename SourceAllocator >
GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
//! Constructor for boolean value.
/*! \param b Boolean value
\note This constructor is limited to \em real boolean values and rejects
implicitly converted types like arbitrary pointers. Use an explicit cast
to \c bool, if you want to construct a boolean JSON value in such cases.
*/
#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
template <typename T>
explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472
#else
explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
#endif
: data_() {
// safe-guard against failing SFINAE
RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
data_.f.flags = b ? kTrueFlag : kFalseFlag;
}
//! Constructor for int value.
explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
data_.n.i64 = i;
data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;
}
//! Constructor for unsigned value.
explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
data_.n.u64 = u;
data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
}
//! Constructor for int64_t value.
explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
data_.n.i64 = i64;
data_.f.flags = kNumberInt64Flag;
if (i64 >= 0) {
data_.f.flags |= kNumberUint64Flag;
if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
data_.f.flags |= kUintFlag;
if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
data_.f.flags |= kIntFlag;
}
else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
data_.f.flags |= kIntFlag;
}
//! Constructor for uint64_t value.
explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
data_.n.u64 = u64;
data_.f.flags = kNumberUint64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
data_.f.flags |= kInt64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
data_.f.flags |= kUintFlag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
data_.f.flags |= kIntFlag;
}
//! Constructor for double value.
explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
//! Constructor for constant string (i.e. do not make a copy of string)
GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
//! Constructor for constant string (i.e. do not make a copy of string)
explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }
//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }
//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
#if RAPIDJSON_HAS_STDSTRING
//! Constructor for copy-string from a string object (i.e. do make a copy of string)
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
#endif
//! Constructor for Array.
/*!
\param a An array obtained by \c GetArray().
\note \c Array is always pass-by-value.
\note the source array is moved into this value and the sourec array becomes empty.
*/
GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
a.value_.data_ = Data();
a.value_.data_.f.flags = kArrayFlag;
}
//! Constructor for Object.
/*!
\param o An object obtained by \c GetObject().
\note \c Object is always pass-by-value.
\note the source object is moved into this value and the sourec object becomes empty.
*/
GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
o.value_.data_ = Data();
o.value_.data_.f.flags = kObjectFlag;
}
//! Destructor.
/*! Need to destruct elements of array, members of object, or copy-string.
*/
~GenericValue() {
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
switch(data_.f.flags) {
case kArrayFlag:
{
GenericValue* e = GetElementsPointer();
for (GenericValue* v = e; v != e + data_.a.size; ++v)
v->~GenericValue();
Allocator::Free(e);
}
break;
case kObjectFlag:
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
m->~Member();
Allocator::Free(GetMembersPointer());
break;
case kCopyStringFlag:
Allocator::Free(const_cast<Ch*>(GetStringPointer()));
break;
default:
break; // Do nothing for other types.
}
}
}
//@}
//!@name Assignment operators
//@{
//! Assignment with move semantics.
/*! \param rhs Source of the assignment. It will become a null value after assignment.
*/
GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
RAPIDJSON_ASSERT(this != &rhs);
this->~GenericValue();
RawAssign(rhs);
return *this;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move assignment in C++11
GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
return *this = rhs.Move();
}
#endif
//! Assignment of constant string reference (no copy)
/*! \param str Constant string reference to be assigned
\note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
\see GenericStringRef, operator=(T)
*/
GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
GenericValue s(str);
return *this = s;
}
//! Assignment with primitive types.
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
\param value The value to be assigned.
\note The source type \c T explicitly disallows all pointer types,
especially (\c const) \ref Ch*. This helps avoiding implicitly
referencing character strings with insufficient lifetime, use
\ref SetString(const Ch*, Allocator&) (for copying) or
\ref StringRef() (to explicitly mark the pointer as constant) instead.
All other pointer types would implicitly convert to \c bool,
use \ref SetBool() instead.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
operator=(T value) {
GenericValue v(value);
return *this = v;
}
//! Deep-copy assignment from Value
/*! Assigns a \b copy of the Value to the current Value object
\tparam SourceAllocator Allocator type of \c rhs
\param rhs Value to copy from (read-only)
\param allocator Allocator to use for copying
*/
template <typename SourceAllocator>
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
this->~GenericValue();
new (this) GenericValue(rhs, allocator);
return *this;
}
//! Exchange the contents of this value with those of other.
/*!
\param other Another value.
\note Constant complexity.
*/
GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
GenericValue temp;
temp.RawAssign(*this);
RawAssign(other);
other.RawAssign(temp);
return *this;
}
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.value, b.value);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//! Prepare Value for move semantics
/*! \return *this */
GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
//@}
//!@name Equal-to and not-equal-to operators
//@{
//! Equal-to operator
/*!
\note If an object contains duplicated named member, comparing equality with any object is always \c false.
\note Linear time complexity (number of all values in the subtree and total lengths of all strings).
*/
template <typename SourceAllocator>
bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
typedef GenericValue<Encoding, SourceAllocator> RhsType;
if (GetType() != rhs.GetType())
return false;
switch (GetType()) {
case kObjectType: // Warning: O(n^2) inner-loop
if (data_.o.size != rhs.data_.o.size)
return false;
for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
return false;
}
return true;
case kArrayType:
if (data_.a.size != rhs.data_.a.size)
return false;
for (SizeType i = 0; i < data_.a.size; i++)
if ((*this)[i] != rhs[i])
return false;
return true;
case kStringType:
return StringEqual(rhs);
case kNumberType:
if (IsDouble() || rhs.IsDouble()) {
double a = GetDouble(); // May convert from integer to double.
double b = rhs.GetDouble(); // Ditto
return a >= b && a <= b; // Prevent -Wfloat-equal
}
else
return data_.n.u64 == rhs.data_.n.u64;
default:
return true;
}
}
//! Equal-to operator with const C-string pointer
bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
#if RAPIDJSON_HAS_STDSTRING
//! Equal-to operator with string object
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
#endif
//! Equal-to operator with primitive types
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
*/
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
//! Not-equal-to operator
/*! \return !(*this == rhs)
*/
template <typename SourceAllocator>
bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
//! Not-equal-to operator with const C-string pointer
bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
//! Not-equal-to operator with arbitrary types
/*! \return !(*this == rhs)
*/
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
//! Equal-to operator with arbitrary types (symmetric version)
/*! \return (rhs == lhs)
*/
template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
//! Not-Equal-to operator with arbitrary types (symmetric version)
/*! \return !(rhs == lhs)
*/
template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
//@}
//!@name Type
//@{
Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); }
bool IsNull() const { return data_.f.flags == kNullFlag; }
bool IsFalse() const { return data_.f.flags == kFalseFlag; }
bool IsTrue() const { return data_.f.flags == kTrueFlag; }
bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; }
bool IsObject() const { return data_.f.flags == kObjectFlag; }
bool IsArray() const { return data_.f.flags == kArrayFlag; }
bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; }
bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; }
bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; }
bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
// Checks whether a number can be losslessly converted to a double.
bool IsLosslessDouble() const {
if (!IsNumber()) return false;
if (IsUint64()) {
uint64_t u = GetUint64();
volatile double d = static_cast<double>(u);
return static_cast<uint64_t>(d) == u;
}
if (IsInt64()) {
int64_t i = GetInt64();
volatile double d = static_cast<double>(i);
return static_cast< int64_t>(d) == i;
}
return true; // double, int, uint are always lossless
}
// Checks whether a number is a float (possible lossy).
bool IsFloat() const {
if ((data_.f.flags & kDoubleFlag) == 0)
return false;
double d = GetDouble();
return d >= -3.4028234e38 && d <= 3.4028234e38;
}
// Checks whether a number can be losslessly converted to a float.
bool IsLosslessFloat() const {
if (!IsNumber()) return false;
double a = GetDouble();
double b = static_cast<double>(static_cast<float>(a));
return a >= b && a <= b; // Prevent -Wfloat-equal
}
//@}
//!@name Null
//@{
GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
//@}
//!@name Bool
//@{
bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
//!< Set boolean value
/*! \post IsBool() == true */
GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
//@}
//!@name Object
//@{
//! Set this value as an empty object.
/*! \post IsObject() == true */
GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
//! Get the number of members in the object.
SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
//! Check whether the object is empty.
bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
//! Get a value from an object associated with the name.
/*! \pre IsObject() == true
\tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
\note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
Since 0.2, if the name is not correct, it will assert.
If user is unsure whether a member exists, user should use HasMember() first.
A better approach is to use FindMember().
\note Linear time complexity.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
GenericValue n(StringRef(name));
return (*this)[n];
}
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
//! Get a value from an object associated with the name.
/*! \pre IsObject() == true
\tparam SourceAllocator Allocator of the \c name value
\note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
And it can also handle strings with embedded null characters.
\note Linear time complexity.
*/
template <typename SourceAllocator>
GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
MemberIterator member = FindMember(name);
if (member != MemberEnd())
return member->value;
else {
RAPIDJSON_ASSERT(false); // see above note
// This will generate -Wexit-time-destructors in clang
// static GenericValue NullValue;
// return NullValue;
// Use static buffer and placement-new to prevent destruction
static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
}
}
template <typename SourceAllocator>
const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
#if RAPIDJSON_HAS_STDSTRING
//! Get a value from an object associated with name (string object).
GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
#endif
//! Const member iterator
/*! \pre IsObject() == true */
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }
//! Const \em past-the-end member iterator
/*! \pre IsObject() == true */
ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }
//! Member iterator
/*! \pre IsObject() == true */
MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
//! \em Past-the-end member iterator
/*! \pre IsObject() == true */
MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
//! Check whether a member exists in the object.
/*!
\param name Member name to be searched.
\pre IsObject() == true
\return Whether a member with that name exists.
\note It is better to use FindMember() directly if you need the obtain the value as well.
\note Linear time complexity.
*/
bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
#if RAPIDJSON_HAS_STDSTRING
//! Check whether a member exists in the object with string object.
/*!
\param name Member name to be searched.
\pre IsObject() == true
\return Whether a member with that name exists.
\note It is better to use FindMember() directly if you need the obtain the value as well.
\note Linear time complexity.
*/
bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
#endif
//! Check whether a member exists in the object with GenericValue name.
/*!
This version is faster because it does not need a StrLen(). It can also handle string with null character.
\param name Member name to be searched.
\pre IsObject() == true
\return Whether a member with that name exists.
\note It is better to use FindMember() directly if you need the obtain the value as well.
\note Linear time complexity.
*/
template <typename SourceAllocator>
bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
//! Find member by name.
/*!
\param name Member name to be searched.
\pre IsObject() == true
\return Iterator to member, if it exists.
Otherwise returns \ref MemberEnd().
\note Earlier versions of Rapidjson returned a \c NULL pointer, in case
the requested member doesn't exist. For consistency with e.g.
\c std::map, this has been changed to MemberEnd() now.
\note Linear time complexity.
*/
MemberIterator FindMember(const Ch* name) {
GenericValue n(StringRef(name));
return FindMember(n);
}
ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
//! Find member by name.
/*!
This version is faster because it does not need a StrLen(). It can also handle string with null character.
\param name Member name to be searched.
\pre IsObject() == true
\return Iterator to member, if it exists.
Otherwise returns \ref MemberEnd().
\note Earlier versions of Rapidjson returned a \c NULL pointer, in case
the requested member doesn't exist. For consistency with e.g.
\c std::map, this has been changed to MemberEnd() now.
\note Linear time complexity.
*/
template <typename SourceAllocator>
MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(name.IsString());
MemberIterator member = MemberBegin();
for ( ; member != MemberEnd(); ++member)
if (name.StringEqual(member->name))
break;
return member;
}
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
#if RAPIDJSON_HAS_STDSTRING
//! Find member by string object name.
/*!
\param name Member name to be searched.
\pre IsObject() == true
\return Iterator to member, if it exists.
Otherwise returns \ref MemberEnd().
*/
MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(StringRef(name)); }
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(StringRef(name)); }
#endif
//! Add a member (name-value pair) to the object.
/*! \param name A string value as name of member.
\param value Value of any type.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\note The ownership of \c name and \c value will be transferred to this object on success.
\pre IsObject() && name.IsString()
\post name.IsNull() && value.IsNull()
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(name.IsString());
ObjectData& o = data_.o;
if (o.size >= o.capacity) {
if (o.capacity == 0) {
o.capacity = kDefaultObjectCapacity;
SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))));
}
else {
SizeType oldCapacity = o.capacity;
o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member))));
}
}
Member* members = GetMembersPointer();
members[o.size].name.RawAssign(name);
members[o.size].value.RawAssign(value);
o.size++;
return *this;
}
//! Add a constant string value as member (name-value pair) to the object.
/*! \param name A string value as name of member.
\param value constant string reference as value of member.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
GenericValue v(value);
return AddMember(name, v, allocator);
}
#if RAPIDJSON_HAS_STDSTRING
//! Add a string object as member (name-value pair) to the object.
/*! \param name A string value as name of member.
\param value constant string reference as value of member.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
GenericValue v(value, allocator);
return AddMember(name, v, allocator);
}
#endif
//! Add any primitive value as member (name-value pair) to the object.
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
\param name A string value as name of member.
\param value Value of primitive type \c T as value of member
\param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note The source type \c T explicitly disallows all pointer types,
especially (\c const) \ref Ch*. This helps avoiding implicitly
referencing character strings with insufficient lifetime, use
\ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
AddMember(StringRefType, StringRefType, Allocator&).
All other pointer types would implicitly convert to \c bool,
use an explicit cast instead, if needed.
\note Amortized Constant time complexity.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
AddMember(GenericValue& name, T value, Allocator& allocator) {
GenericValue v(value);
return AddMember(name, v, allocator);
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
GenericValue n(name);
return AddMember(n, value, allocator);
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Add a member (name-value pair) to the object.
/*! \param name A constant string reference as name of member.
\param value Value of any type.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\note The ownership of \c value will be transferred to this object on success.
\pre IsObject()
\post value.IsNull()
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
GenericValue n(name);
return AddMember(n, value, allocator);
}
//! Add a constant string value as member (name-value pair) to the object.
/*! \param name A constant string reference as name of member.
\param value constant string reference as value of member.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
GenericValue v(value);
return AddMember(name, v, allocator);
}
//! Add any primitive value as member (name-value pair) to the object.
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
\param name A constant string reference as name of member.
\param value Value of primitive type \c T as value of member
\param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note The source type \c T explicitly disallows all pointer types,
especially (\c const) \ref Ch*. This helps avoiding implicitly
referencing character strings with insufficient lifetime, use
\ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
AddMember(StringRefType, StringRefType, Allocator&).
All other pointer types would implicitly convert to \c bool,
use an explicit cast instead, if needed.
\note Amortized Constant time complexity.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
AddMember(StringRefType name, T value, Allocator& allocator) {
GenericValue n(name);
return AddMember(n, value, allocator);
}
//! Remove all members in the object.
/*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
\note Linear time complexity.
*/
void RemoveAllMembers() {
RAPIDJSON_ASSERT(IsObject());
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
m->~Member();
data_.o.size = 0;
}
//! Remove a member in object by its name.
/*! \param name Name of member to be removed.
\return Whether the member existed.
\note This function may reorder the object members. Use \ref
EraseMember(ConstMemberIterator) if you need to preserve the
relative order of the remaining members.
\note Linear time complexity.
*/
bool RemoveMember(const Ch* name) {
GenericValue n(StringRef(name));
return RemoveMember(n);
}
#if RAPIDJSON_HAS_STDSTRING
bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
#endif
template <typename SourceAllocator>
bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
MemberIterator m = FindMember(name);
if (m != MemberEnd()) {
RemoveMember(m);
return true;
}
else
return false;
}
//! Remove a member in object by iterator.
/*! \param m member iterator (obtained by FindMember() or MemberBegin()).
\return the new iterator after removal.
\note This function may reorder the object members. Use \ref
EraseMember(ConstMemberIterator) if you need to preserve the
relative order of the remaining members.
\note Constant time complexity.
*/
MemberIterator RemoveMember(MemberIterator m) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(data_.o.size > 0);
RAPIDJSON_ASSERT(GetMembersPointer() != 0);
RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
if (data_.o.size > 1 && m != last)
*m = *last; // Move the last one to this place
else
m->~Member(); // Only one left, just destroy
--data_.o.size;
return m;
}
//! Remove a member from an object by iterator.
/*! \param pos iterator to the member to remove
\pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
\return Iterator following the removed element.
If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
\note This function preserves the relative order of the remaining object
members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
\note Linear time complexity.
*/
MemberIterator EraseMember(ConstMemberIterator pos) {
return EraseMember(pos, pos +1);
}
//! Remove members in the range [first, last) from an object.
/*! \param first iterator to the first member to remove
\param last iterator following the last member to remove
\pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
\return Iterator following the last removed element.
\note This function preserves the relative order of the remaining object
members.
\note Linear time complexity.
*/
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(data_.o.size > 0);
RAPIDJSON_ASSERT(GetMembersPointer() != 0);
RAPIDJSON_ASSERT(first >= MemberBegin());
RAPIDJSON_ASSERT(first <= last);
RAPIDJSON_ASSERT(last <= MemberEnd());
MemberIterator pos = MemberBegin() + (first - MemberBegin());
for (MemberIterator itr = pos; itr != last; ++itr)
itr->~Member();
std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
data_.o.size -= static_cast<SizeType>(last - first);
return pos;
}
//! Erase a member in object by its name.
/*! \param name Name of member to be removed.
\return Whether the member existed.
\note Linear time complexity.
*/
bool EraseMember(const Ch* name) {
GenericValue n(StringRef(name));
return EraseMember(n);
}
#if RAPIDJSON_HAS_STDSTRING
bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
#endif
template <typename SourceAllocator>
bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
MemberIterator m = FindMember(name);
if (m != MemberEnd()) {
EraseMember(m);
return true;
}
else
return false;
}
Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
//@}
//!@name Array
//@{
//! Set this value as an empty array.
/*! \post IsArray == true */
GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
//! Get the number of elements in array.
SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
//! Get the capacity of array.
SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
//! Check whether the array is empty.
bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
//! Remove all elements in the array.
/*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
\note Linear time complexity.
*/
void Clear() {
RAPIDJSON_ASSERT(IsArray());
GenericValue* e = GetElementsPointer();
for (GenericValue* v = e; v != e + data_.a.size; ++v)
v->~GenericValue();
data_.a.size = 0;
}
//! Get an element from array by index.
/*! \pre IsArray() == true
\param index Zero-based index of element.
\see operator[](T*)
*/
GenericValue& operator[](SizeType index) {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(index < data_.a.size);
return GetElementsPointer()[index];
}
const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
//! Element iterator
/*! \pre IsArray() == true */
ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }
//! \em Past-the-end element iterator
/*! \pre IsArray() == true */
ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }
//! Constant element iterator
/*! \pre IsArray() == true */
ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
//! Constant \em past-the-end element iterator
/*! \pre IsArray() == true */
ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
//! Request the array to have enough capacity to store elements.
/*! \param newCapacity The capacity that the array at least need to have.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\note Linear time complexity.
*/
GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
RAPIDJSON_ASSERT(IsArray());
if (newCapacity > data_.a.capacity) {
SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));
data_.a.capacity = newCapacity;
}
return *this;
}
//! Append a GenericValue at the end of the array.
/*! \param value Value to be appended.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\pre IsArray() == true
\post value.IsNull() == true
\return The value itself for fluent API.
\note The ownership of \c value will be transferred to this array on success.
\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
\note Amortized constant time complexity.
*/
GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
RAPIDJSON_ASSERT(IsArray());
if (data_.a.size >= data_.a.capacity)
Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
GetElementsPointer()[data_.a.size++].RawAssign(value);
return *this;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
return PushBack(value, allocator);
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Append a constant string reference at the end of the array.
/*! \param value Constant string reference to be appended.
\param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
\pre IsArray() == true
\return The value itself for fluent API.
\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
\note Amortized constant time complexity.
\see GenericStringRef
*/
GenericValue& PushBack(StringRefType value, Allocator& allocator) {
return (*this).template PushBack<StringRefType>(value, allocator);
}
//! Append a primitive value at the end of the array.
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
\param value Value of primitive type T to be appended.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\pre IsArray() == true
\return The value itself for fluent API.
\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
\note The source type \c T explicitly disallows all pointer types,
especially (\c const) \ref Ch*. This helps avoiding implicitly
referencing character strings with insufficient lifetime, use
\ref PushBack(GenericValue&, Allocator&) or \ref
PushBack(StringRefType, Allocator&).
All other pointer types would implicitly convert to \c bool,
use an explicit cast instead, if needed.
\note Amortized constant time complexity.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
PushBack(T value, Allocator& allocator) {
GenericValue v(value);
return PushBack(v, allocator);
}
//! Remove the last element in the array.
/*!
\note Constant time complexity.
*/
GenericValue& PopBack() {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(!Empty());
GetElementsPointer()[--data_.a.size].~GenericValue();
return *this;
}
//! Remove an element of array by iterator.
/*!
\param pos iterator to the element to remove
\pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
\return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
\note Linear time complexity.
*/
ValueIterator Erase(ConstValueIterator pos) {
return Erase(pos, pos + 1);
}
//! Remove elements in the range [first, last) of the array.
/*!
\param first iterator to the first element to remove
\param last iterator following the last element to remove
\pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
\return Iterator following the last removed element.
\note Linear time complexity.
*/
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(data_.a.size > 0);
RAPIDJSON_ASSERT(GetElementsPointer() != 0);
RAPIDJSON_ASSERT(first >= Begin());
RAPIDJSON_ASSERT(first <= last);
RAPIDJSON_ASSERT(last <= End());
ValueIterator pos = Begin() + (first - Begin());
for (ValueIterator itr = pos; itr != last; ++itr)
itr->~GenericValue();
std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
data_.a.size -= static_cast<SizeType>(last - first);
return pos;
}
Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
//@}
//!@name Number
//@{
int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; }
unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; }
int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
//! Get the value as double type.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
*/
double GetDouble() const {
RAPIDJSON_ASSERT(IsNumber());
if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double
if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
}
//! Get the value as float type.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless.
*/
float GetFloat() const {
return static_cast<float>(GetDouble());
}
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
//@}
//!@name String
//@{
const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
//! Get the length of string.
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
*/
SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
//! Set this value as a string without copying source string.
/*! This version has better performance with supplied length, and also support string containing null character.
\param s source string pointer.
\param length The length of source string, excluding the trailing null terminator.
\return The value itself for fluent API.
\post IsString() == true && GetString() == s && GetStringLength() == length
\see SetString(StringRefType)
*/
GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
//! Set this value as a string without copying source string.
/*! \param s source string reference
\return The value itself for fluent API.
\post IsString() == true && GetString() == s && GetStringLength() == s.length
*/
GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
//! Set this value as a string by copying from source string.
/*! This version has better performance with supplied length, and also support string containing null character.
\param s source string.
\param length The length of source string, excluding the trailing null terminator.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/
GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
//! Set this value as a string by copying from source string.
/*! \param s source string.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/
GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
#if RAPIDJSON_HAS_STDSTRING
//! Set this value as a string by copying from source string.
/*! \param s source string.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
#endif
//@}
//!@name Array
//@{
//! Templated version for checking whether this value is type T.
/*!
\tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch>
*/
template <typename T>
bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
template <typename T>
T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
template <typename T>
T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }
template<typename T>
ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }
template<typename T>
ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
//@}
//! Generate events of this value to a Handler.
/*! This function adopts the GoF visitor pattern.
Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
It can also be used to deep clone this value via GenericDocument, which is also a Handler.
\tparam Handler type of handler.
\param handler An object implementing concept Handler.
*/
template <typename Handler>
bool Accept(Handler& handler) const {
switch(GetType()) {
case kNullType: return handler.Null();
case kFalseType: return handler.Bool(false);
case kTrueType: return handler.Bool(true);
case kObjectType:
if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
return false;
for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))
return false;
if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))
return false;
}
return handler.EndObject(data_.o.size);
case kArrayType:
if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
return false;
for (const GenericValue* v = Begin(); v != End(); ++v)
if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
return false;
return handler.EndArray(data_.a.size);
case kStringType:
return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
default:
RAPIDJSON_ASSERT(GetType() == kNumberType);
if (IsDouble()) return handler.Double(data_.n.d);
else if (IsInt()) return handler.Int(data_.n.i.i);
else if (IsUint()) return handler.Uint(data_.n.u.u);
else if (IsInt64()) return handler.Int64(data_.n.i64);
else return handler.Uint64(data_.n.u64);
}
}
private:
template <typename, typename> friend class GenericValue;
template <typename, typename, typename> friend class GenericDocument;
enum {
kBoolFlag = 0x0008,
kNumberFlag = 0x0010,
kIntFlag = 0x0020,
kUintFlag = 0x0040,
kInt64Flag = 0x0080,
kUint64Flag = 0x0100,
kDoubleFlag = 0x0200,
kStringFlag = 0x0400,
kCopyFlag = 0x0800,
kInlineStrFlag = 0x1000,
// Initial flags of different types.
kNullFlag = kNullType,
kTrueFlag = kTrueType | kBoolFlag,
kFalseFlag = kFalseType | kBoolFlag,
kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
kConstStringFlag = kStringType | kStringFlag,
kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
kObjectFlag = kObjectType,
kArrayFlag = kArrayType,
kTypeMask = 0x07
};
static const SizeType kDefaultArrayCapacity = 16;
static const SizeType kDefaultObjectCapacity = 16;
struct Flag {
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer
#elif RAPIDJSON_64BIT
char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes
#else
char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes
#endif
uint16_t flags;
};
struct String {
SizeType length;
SizeType hashcode; //!< reserved
const Ch* str;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
// (excluding the terminating zero) and store a value to determine the length of the contained
// string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
// to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
// the string terminator as well. For getting the string length back from that value just use
// "MaxSize - str[LenPos]".
// This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
// 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).
struct ShortString {
enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
Ch str[MaxChars];
inline static bool Usable(SizeType len) { return (MaxSize >= len); }
inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); }
inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); }
}; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// By using proper binary layout, retrieval of different integer types do not need conversions.
union Number {
#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
struct I {
int i;
char padding[4];
}i;
struct U {
unsigned u;
char padding2[4];
}u;
#else
struct I {
char padding[4];
int i;
}i;
struct U {
char padding2[4];
unsigned u;
}u;
#endif
int64_t i64;
uint64_t u64;
double d;
}; // 8 bytes
struct ObjectData {
SizeType size;
SizeType capacity;
Member* members;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
struct ArrayData {
SizeType size;
SizeType capacity;
GenericValue* elements;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
union Data {
String s;
ShortString ss;
Number n;
ObjectData o;
ArrayData a;
Flag f;
}; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
// Initialize this value as array with initial data, without calling destructor.
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
data_.f.flags = kArrayFlag;
if (count) {
GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
SetElementsPointer(e);
std::memcpy(e, values, count * sizeof(GenericValue));
}
else
SetElementsPointer(0);
data_.a.size = data_.a.capacity = count;
}
//! Initialize this value as object with initial data, without calling destructor.
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
data_.f.flags = kObjectFlag;
if (count) {
Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
SetMembersPointer(m);
std::memcpy(m, members, count * sizeof(Member));
}
else
SetMembersPointer(0);
data_.o.size = data_.o.capacity = count;
}
//! Initialize this value as constant string, without calling destructor.
void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
data_.f.flags = kConstStringFlag;
SetStringPointer(s);
data_.s.length = s.length;
}
//! Initialize this value as copy string with initial data, without calling destructor.
void SetStringRaw(StringRefType s, Allocator& allocator) {
Ch* str = 0;
if (ShortString::Usable(s.length)) {
data_.f.flags = kShortStringFlag;
data_.ss.SetLength(s.length);
str = data_.ss.str;
} else {
data_.f.flags = kCopyStringFlag;
data_.s.length = s.length;
str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
SetStringPointer(str);
}
std::memcpy(str, s, s.length * sizeof(Ch));
str[s.length] = '\0';
}
//! Assignment without calling destructor
void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
data_ = rhs.data_;
// data_.f.flags = rhs.data_.f.flags;
rhs.data_.f.flags = kNullFlag;
}
template <typename SourceAllocator>
bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
RAPIDJSON_ASSERT(IsString());
RAPIDJSON_ASSERT(rhs.IsString());
const SizeType len1 = GetStringLength();
const SizeType len2 = rhs.GetStringLength();
if(len1 != len2) { return false; }
const Ch* const str1 = GetString();
const Ch* const str2 = rhs.GetString();
if(str1 == str2) { return true; } // fast path for constant string
return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
}
Data data_;
};
//! GenericValue with UTF8 encoding
typedef GenericValue<UTF8<> > Value;
///////////////////////////////////////////////////////////////////////////////
// GenericDocument
//! A document for parsing JSON text as DOM.
/*!
\note implements Handler concept
\tparam Encoding Encoding for both parsing and string storage.
\tparam Allocator Allocator for allocating memory for the DOM
\tparam StackAllocator Allocator for allocating memory for stack during parsing.
\warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
*/
template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
class GenericDocument : public GenericValue<Encoding, Allocator> {
public:
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
//! Constructor
/*! Creates an empty document of specified type.
\param type Mandatory type of object to create.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack.
*/
explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
}
//! Constructor
/*! Creates an empty document which type is Null.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack.
*/
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
: ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_),
stack_(std::move(rhs.stack_)),
parseResult_(rhs.parseResult_)
{
rhs.allocator_ = 0;
rhs.ownAllocator_ = 0;
rhs.parseResult_ = ParseResult();
}
#endif
~GenericDocument() {
Destroy();
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move assignment in C++11
GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
{
// The cast to ValueType is necessary here, because otherwise it would
// attempt to call GenericValue's templated assignment operator.
ValueType::operator=(std::forward<ValueType>(rhs));
// Calling the destructor here would prematurely call stack_'s destructor
Destroy();
allocator_ = rhs.allocator_;
ownAllocator_ = rhs.ownAllocator_;
stack_ = std::move(rhs.stack_);
parseResult_ = rhs.parseResult_;
rhs.allocator_ = 0;
rhs.ownAllocator_ = 0;
rhs.parseResult_ = ParseResult();
return *this;
}
#endif
//! Exchange the contents of this document with those of another.
/*!
\param rhs Another document.
\note Constant complexity.
\see GenericValue::Swap
*/
GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
ValueType::Swap(rhs);
stack_.Swap(rhs.stack_);
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(parseResult_, rhs.parseResult_);
return *this;
}
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.doc, b.doc);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//! Populate this document by a generator which produces SAX events.
/*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
\param g Generator functor which sends SAX events to the parameter.
\return The document itself for fluent API.
*/
template <typename Generator>
GenericDocument& Populate(Generator& g) {
ClearStackOnExit scope(*this);
if (g(*this)) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
}
return *this;
}
//!@name Parse from stream
//!@{
//! Parse JSON text from an input stream (with Encoding conversion)
/*! \tparam parseFlags Combination of \ref ParseFlag.
\tparam SourceEncoding Encoding of input stream
\tparam InputStream Type of input stream, implementing Stream concept
\param is Input stream to be parsed.
\return The document itself for fluent API.
*/
template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
GenericDocument& ParseStream(InputStream& is) {
GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
ClearStackOnExit scope(*this);
parseResult_ = reader.template Parse<parseFlags>(is, *this);
if (parseResult_) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
}
return *this;
}
//! Parse JSON text from an input stream
/*! \tparam parseFlags Combination of \ref ParseFlag.
\tparam InputStream Type of input stream, implementing Stream concept
\param is Input stream to be parsed.
\return The document itself for fluent API.
*/
template <unsigned parseFlags, typename InputStream>
GenericDocument& ParseStream(InputStream& is) {
return ParseStream<parseFlags, Encoding, InputStream>(is);
}
//! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
/*! \tparam InputStream Type of input stream, implementing Stream concept
\param is Input stream to be parsed.
\return The document itself for fluent API.
*/
template <typename InputStream>
GenericDocument& ParseStream(InputStream& is) {
return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
}
//!@}
//!@name Parse in-place from mutable string
//!@{
//! Parse JSON text from a mutable string
/*! \tparam parseFlags Combination of \ref ParseFlag.
\param str Mutable zero-terminated string to be parsed.
\return The document itself for fluent API.
*/
template <unsigned parseFlags>
GenericDocument& ParseInsitu(Ch* str) {
GenericInsituStringStream<Encoding> s(str);
return ParseStream<parseFlags | kParseInsituFlag>(s);
}
//! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
/*! \param str Mutable zero-terminated string to be parsed.
\return The document itself for fluent API.
*/
GenericDocument& ParseInsitu(Ch* str) {
return ParseInsitu<kParseDefaultFlags>(str);
}
//!@}
//!@name Parse from read-only string
//!@{
//! Parse JSON text from a read-only string (with Encoding conversion)
/*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
\tparam SourceEncoding Transcoding from input Encoding
\param str Read-only zero-terminated string to be parsed.
*/
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
GenericStringStream<SourceEncoding> s(str);
return ParseStream<parseFlags, SourceEncoding>(s);
}
//! Parse JSON text from a read-only string
/*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
\param str Read-only zero-terminated string to be parsed.
*/
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) {
return Parse<parseFlags, Encoding>(str);
}
//! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
/*! \param str Read-only zero-terminated string to be parsed.
*/
GenericDocument& Parse(const Ch* str) {
return Parse<kParseDefaultFlags>(str);
}
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
ParseStream<parseFlags, SourceEncoding>(is);
return *this;
}
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str, size_t length) {
return Parse<parseFlags, Encoding>(str, length);
}
GenericDocument& Parse(const Ch* str, size_t length) {
return Parse<kParseDefaultFlags>(str, length);
}
#if RAPIDJSON_HAS_STDSTRING
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) {
// c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t)
return Parse<parseFlags, SourceEncoding>(str.c_str());
}
template <unsigned parseFlags>
GenericDocument& Parse(const std::basic_string<Ch>& str) {
return Parse<parseFlags, Encoding>(str.c_str());
}
GenericDocument& Parse(const std::basic_string<Ch>& str) {
return Parse<kParseDefaultFlags>(str);
}
#endif // RAPIDJSON_HAS_STDSTRING
//!@}
//!@name Handling parse errors
//!@{
//! Whether a parse error has occured in the last parsing.
bool HasParseError() const { return parseResult_.IsError(); }
//! Get the \ref ParseErrorCode of last parsing.
ParseErrorCode GetParseError() const { return parseResult_.Code(); }
//! Get the position of last parsing error in input, 0 otherwise.
size_t GetErrorOffset() const { return parseResult_.Offset(); }
//! Implicit conversion to get the last parse result
#ifndef __clang // -Wdocumentation
/*! \return \ref ParseResult of the last parse operation
\code
Document doc;
ParseResult ok = doc.Parse(json);
if (!ok)
printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset());
\endcode
*/
#endif
operator ParseResult() const { return parseResult_; }
//!@}
//! Get the allocator of this document.
Allocator& GetAllocator() {
RAPIDJSON_ASSERT(allocator_);
return *allocator_;
}
//! Get the capacity of stack in bytes.
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
private:
// clear stack on any exit from ParseStream, e.g. due to exception
struct ClearStackOnExit {
explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
~ClearStackOnExit() { d_.ClearStack(); }
private:
ClearStackOnExit(const ClearStackOnExit&);
ClearStackOnExit& operator=(const ClearStackOnExit&);
GenericDocument& d_;
};
// callers of the following private Handler functions
// template <typename,typename,typename> friend class GenericReader; // for parsing
template <typename, typename> friend class GenericValue; // for deep copying
public:
// Implementation of Handler
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
bool RawNumber(const Ch* str, SizeType length, bool copy) {
if (copy)
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
else
new (stack_.template Push<ValueType>()) ValueType(str, length);
return true;
}
bool String(const Ch* str, SizeType length, bool copy) {
if (copy)
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
else
new (stack_.template Push<ValueType>()) ValueType(str, length);
return true;
}
bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
bool EndObject(SizeType memberCount) {
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
return true;
}
bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
bool EndArray(SizeType elementCount) {
ValueType* elements = stack_.template Pop<ValueType>(elementCount);
stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
return true;
}
private:
//! Prohibit copying
GenericDocument(const GenericDocument&);
//! Prohibit assignment
GenericDocument& operator=(const GenericDocument&);
void ClearStack() {
if (Allocator::kNeedFree)
while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
(stack_.template Pop<ValueType>(1))->~ValueType();
else
stack_.Clear();
stack_.ShrinkToFit();
}
void Destroy() {
RAPIDJSON_DELETE(ownAllocator_);
}
static const size_t kDefaultStackCapacity = 1024;
Allocator* allocator_;
Allocator* ownAllocator_;
internal::Stack<StackAllocator> stack_;
ParseResult parseResult_;
};
//! GenericDocument with UTF8 encoding
typedef GenericDocument<UTF8<> > Document;
// defined here due to the dependency on GenericDocument
template <typename Encoding, typename Allocator>
template <typename SourceAllocator>
inline
GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
{
switch (rhs.GetType()) {
case kObjectType:
case kArrayType: { // perform deep copy via SAX Handler
GenericDocument<Encoding,Allocator> d(&allocator);
rhs.Accept(d);
RawAssign(*d.stack_.template Pop<GenericValue>(1));
}
break;
case kStringType:
if (rhs.data_.f.flags == kConstStringFlag) {
data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
} else {
SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
}
break;
default:
data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
break;
}
}
//! Helper class for accessing Value of array type.
/*!
Instance of this helper class is obtained by \c GenericValue::GetArray().
In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
*/
template <bool Const, typename ValueT>
class GenericArray {
public:
typedef GenericArray<true, ValueT> ConstArray;
typedef GenericArray<false, ValueT> Array;
typedef ValueT PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef ValueType* ValueIterator; // This may be const or non-const iterator
typedef const ValueT* ConstValueIterator;
typedef typename ValueType::AllocatorType AllocatorType;
typedef typename ValueType::StringRefType StringRefType;
template <typename, typename>
friend class GenericValue;
GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
~GenericArray() {}
SizeType Size() const { return value_.Size(); }
SizeType Capacity() const { return value_.Capacity(); }
bool Empty() const { return value_.Empty(); }
void Clear() const { value_.Clear(); }
ValueType& operator[](SizeType index) const { return value_[index]; }
ValueIterator Begin() const { return value_.Begin(); }
ValueIterator End() const { return value_.End(); }
GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }
GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
GenericArray PopBack() const { value_.PopBack(); return *this; }
ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
ValueIterator begin() const { return value_.Begin(); }
ValueIterator end() const { return value_.End(); }
#endif
private:
GenericArray();
GenericArray(ValueType& value) : value_(value) {}
ValueType& value_;
};
//! Helper class for accessing Value of object type.
/*!
Instance of this helper class is obtained by \c GenericValue::GetObject().
In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
*/
template <bool Const, typename ValueT>
class GenericObject {
public:
typedef GenericObject<true, ValueT> ConstObject;
typedef GenericObject<false, ValueT> Object;
typedef ValueT PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator
typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator;
typedef typename ValueType::AllocatorType AllocatorType;
typedef typename ValueType::StringRefType StringRefType;
typedef typename ValueType::EncodingType EncodingType;
typedef typename ValueType::Ch Ch;
template <typename, typename>
friend class GenericValue;
GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
~GenericObject() {}
SizeType MemberCount() const { return value_.MemberCount(); }
bool ObjectEmpty() const { return value_.ObjectEmpty(); }
template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
#if RAPIDJSON_HAS_STDSTRING
ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }
#endif
MemberIterator MemberBegin() const { return value_.MemberBegin(); }
MemberIterator MemberEnd() const { return value_.MemberEnd(); }
bool HasMember(const Ch* name) const { return value_.HasMember(name); }
#if RAPIDJSON_HAS_STDSTRING
bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
#endif
template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }
template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
#if RAPIDJSON_HAS_STDSTRING
MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }
#endif
GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#if RAPIDJSON_HAS_STDSTRING
GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#endif
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
void RemoveAllMembers() { return value_.RemoveAllMembers(); }
bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
#if RAPIDJSON_HAS_STDSTRING
bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
#endif
template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }
MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }
bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }
#if RAPIDJSON_HAS_STDSTRING
bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }
#endif
template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
MemberIterator begin() const { return value_.MemberBegin(); }
MemberIterator end() const { return value_.MemberEnd(); }
#endif
private:
GenericObject();
GenericObject(ValueType& value) : value_(value) {}
ValueType& value_;
};
RAPIDJSON_NAMESPACE_END
#ifdef _MSC_VER
RAPIDJSON_DIAG_POP
#endif
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_DOCUMENT_H_
================================================
FILE: rapidjson/encodedstream.h
================================================
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// 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.
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
#define RAPIDJSON_ENCODEDSTREAM_H_
#include "stream.h"
#include "memorystream.h"
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
#endif
RAPIDJSON_NAMESPACE_BEGIN
//! Input byte stream wrapper with a statically bound encoding.
/*!
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
\tparam InputByteStream Type of input byte stream. For example, FileReadStream.
*/
template <typename Encoding, typename InputByteStream>
class EncodedInputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
public:
typedef typename Encoding::Ch Ch;
EncodedInputStream(InputByteStream& is) : is_(is) {
current_ = Encoding::TakeBOM(is_);
}
Ch Peek() const { return current_; }
Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
size_t Tell() const { return is_.Tell(); }
// Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
private:
EncodedInputStream(const EncodedInputStream&);
EncodedInputStream& operator=(const EncodedInputStream&);
InputByteStream& is_;
Ch current_;
};
//! Specialized for UTF8 MemoryStream.
template <>
class EncodedInputStream<UTF8<>, MemoryStream> {
public:
typedef UTF8<>::Ch Ch;
EncodedInputStream(MemoryStream& is) : is_(is) {
if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
}
Ch Peek() const { return is_.Peek(); }
Ch Take() { return is_.Take(); }
size_t Tell() const { return is_.Tell(); }
// Not implemented
void Put(Ch) {}
void Flush() {}
Ch* PutBegin() { return 0; }
size_t PutEnd(Ch*) { return 0; }
MemoryStream& is_;
private:
EncodedInputStream(const EncodedInputStream&);
EncodedInputStream& operator=(const EncodedInputStream&);
};
//! Output byte stream wrapper with statically bound encoding.
/*!
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
\tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
*/
template <typename Encoding, typename OutputByteStream>
class EncodedOutputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
public:
typedef typename Encoding::Ch Ch;
EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
if (putBOM)
Encoding::PutBOM(os_);
}
void Put(Ch c) { Encoding::Put(os_, c); }
void Flush() { os_.Flush(); }
// Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
private:
EncodedOutputStream(const EncodedOutputStream&);
EncodedOutputStream& operator=(const EncodedOutputStream&);
OutputByteStream& os_;
};
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
/*!
\tparam CharType Type of character for reading.
\tparam InputByteStream type of input byte stream to be wrapped.
*/
template <typename CharType, typename InputByteStream>
class AutoUTFInputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
public:
typedef CharType Ch;
//! Constructor.
/*!
\param is input stream to be wrapped.
\param type UTF encoding type if it is not detected from the stream.
*/
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
DetectType();
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
takeFunc_ = f[type_];
current_ = takeFunc_(*is_);
}
UTFType GetType() const { return type_; }
bool HasBOM() const { return hasBOM_; }
Ch Peek() const { return current_; }
Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
size_t Tell() const { return is_->Tell(); }
// Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
private:
AutoUTFInputStream(const AutoUTFInputStream&);
AutoUTFInputStream& operator=(const AutoUTFInputStream&);
// Detect encoding type with BOM or RFC 4627
void DetectType() {
// BOM (Byte Order Mark):
// 00 00 FE FF UTF-32BE
// FF FE 00 00 UTF-32LE
// FE FF UTF-16BE
// FF FE UTF-16LE
// EF BB BF UTF-8
const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
if (!c)
return;
unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
hasBOM_ = false;
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
// RFC 4627: Section 3
// "Since the first two characters of a JSON text will always be ASCII
// characters [RFC0020], it is possible to determine whether an octet
// stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
// at the pattern of nulls in the first four octets."
// 00 00 00 xx UTF-32BE
// 00 xx 00 xx UTF-16BE
// xx 00 00 00 UTF-32LE
// xx 00 xx 00 UTF-16LE
// xx xx xx xx UTF-8
if (!hasBOM_) {
unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
switch (pattern) {
case 0x08: type_ = kUTF32BE; break;
case 0x0A: type_ = kUTF16BE; break;
case 0x01: type_ = kUTF32LE; break;
case 0x05: type_ = kUTF16LE; break;
case 0x0F: type_ = kUTF8; break;
default: break; // Use type defined by user.
}
}
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
}
typedef Ch (*TakeFunc)(InputByteStream& is);
InputByteStream* is_;
UTFType type_;
Ch current_;
TakeFunc takeFunc_;
bool hasBOM_;
};
//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
/*!
\tparam CharType Type of character for writing.
\tparam OutputByteStream type of output byte stream to be wrapped.
*/
template <typename CharType, typename OutputByteStream>
class AutoUTFOutputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
public:
typedef CharType Ch;
//! Constructor.
/*!
\param os output stream to be wrapped.
\param type UTF encoding type.
\param putBOM Whether to write BOM at the beginning of the stream.
*/
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
putFunc_ = f[type_];
if (putBOM)
PutBOM();
}
UTFType GetType() const { return type_; }
void Put(Ch c) { putFunc_(*os_, c); }
void Flush() { os_->Flush(); }
// Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
private:
AutoUTFOutputStream(const AutoUTFOutputStream&);
AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
void PutBOM() {
typedef void (*PutBOMFunc)(OutputByteStream&);
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
f[type_](*os_);
}
typedef void (*PutFunc)(OutputByteStream&, Ch);
OutputByteStream* os_;
UTFType type_;
PutFunc putFunc_;
};
#undef RAPIDJSON_ENCODINGS_FUNC
RAPIDJSON_NAMESPACE_END
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_FILESTREAM_H_
================================================
FILE: rapidjson/encodings.h
================================================
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// 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.
#ifndef RAPIDJSON_ENCODINGS_H_
#define RAPIDJSON_ENCODINGS_H_
#include "rapidjson.h"
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
RAPIDJSON_DIAG_OFF(4702) // unreachable code
#elif defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_OFF(overflow)
#endif
RAPIDJSON_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
// Encoding
/*! \class rapidjson::Encoding
\brief Concept for encoding of Unicode characters.
\code
concept Encoding {
typen
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
SYMBOL INDEX (821 symbols across 49 files)
FILE: Test.hpp
function Performance (line 3) | void Performance()
FILE: kapok/Common.hpp
type kapok (line 6) | namespace kapok {
function split (line 8) | std::array<std::string, N> split(const std::string& s, const char deli...
function make (line 30) | static inline auto make(const std::array<std::string, N>&ar, unsigned ...
function make (line 36) | static inline auto make(const std::array<std::string, N>&ar, unsigned ...
class NonCopyable (line 147) | class NonCopyable
method NonCopyable (line 150) | NonCopyable(const NonCopyable&) = delete;
method NonCopyable (line 151) | NonCopyable& operator = (const NonCopyable&) = delete;
method NonCopyable (line 152) | NonCopyable() = default;
FILE: kapok/DeSerializer.hpp
type kapok (line 6) | namespace kapok {
class DeSerializer (line 7) | class DeSerializer : NonCopyable
method DeSerializer (line 10) | DeSerializer() = default;
method DeSerializer (line 11) | DeSerializer(const char* jsonText, std::size_t length)
method DeSerializer (line 16) | DeSerializer(const std::string& jsonText)
method Parse (line 25) | void Parse(const std::string& jsonText)
method Parse (line 30) | void Parse(const char* jsonText, std::size_t length)
method Deserialize (line 41) | void Deserialize(T& t, const std::string& key, bool has_root = true)
method Deserialize (line 47) | void Deserialize(T& t, const char* key, bool has_root = true)
method Deserialize (line 55) | void Deserialize(T& t, bool has_root = false)
method Deserialize (line 63) | void Deserialize(T(&p)[N], const char* key)
method Deserialize (line 69) | void Deserialize(std::array<T, N>& arr, const char* key)
method ReadArray (line 94) | void ReadArray(T& t, const char* key)
method ReadArray (line 102) | void ReadArray(T& t, rapidjson::Value& jsonval)
method ReadObject (line 114) | typename std::enable_if<is_tuple<T>::value>::type ReadObject(T& t, r...
method ReadObject (line 120) | typename std::enable_if<is_user_class<T>::value>::type ReadObject(T&...
method ReadObject (line 126) | auto ReadObject(T& t, rapidjson::Value& val, BeginObject) -> std::en...
method ReadObject (line 134) | auto ReadObject(T& t, rapidjson::Value& val, BeginObject) -> std::en...
method ReadObject (line 145) | void ReadObject(variant<Args...>& v, rapidjson::Value& value, BeginO...
method ReadTuple (line 160) | void ReadTuple(Tuple&& tp, rapidjson::Value& val, BeginObject bo)
method SetValueByIndex (line 171) | inline auto SetValueByIndex(size_t, Tuple&, rapidjson::Value&, Begin...
method SetValueByIndex (line 178) | inline auto SetValueByIndex(size_t index, Tuple& tp, rapidjson::Valu...
method ReadObject (line 192) | auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) ->
method ReadObject (line 207) | auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) ->
method ReadObject (line 222) | auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) ->
method push (line 237) | auto push(T& t, value_type& v, std::size_t index) ->
method push (line 244) | auto push(T& t, value_type& v, std::size_t index) ->
method push (line 251) | auto push(T& t, value_type& v, std::size_t index) ->
method push (line 258) | auto push(T& t, value_type& v, std::size_t index) ->
method ReadObject (line 265) | auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::ena...
method ReadObject (line 285) | auto ReadObject(T&& t, rapidjson::Value& v, BeginObject) -> std::ena...
method ReadValue (line 291) | auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::en...
method ReadValue (line 297) | auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::en...
method ReadValue (line 303) | void ReadValue(variant<Args...>& v, rapidjson::Value& val, BeginObje...
method ReadValue (line 310) | auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::en...
method ReadObject (line 318) | auto ReadObject(T&& t, rapidjson::Value& val, std::true_type bo) -> ...
method ReadObject (line 334) | auto ReadObject(T&& t, rapidjson::Value& val, std::false_type bo) ->...
method ReadValue (line 340) | auto ReadValue(T&& t, rapidjson::Value& val, BeginObject) -> std::en...
method ReadValue (line 346) | auto ReadValue(T&& t, rapidjson::Value& val, std::false_type bo) -> ...
method ReadValue (line 362) | auto ReadValue(T&& t, rapidjson::Value& val, std::true_type bo) -> s...
method LoadVariantImplFunc (line 373) | void LoadVariantImplFunc(rapidjson::Value& value, variant<Args...>& v)
type LoadVariantImpl (line 385) | struct LoadVariantImpl
type LoadVariantImpl<End, End> (line 401) | struct LoadVariantImpl<End, End>
method LoadVariant (line 417) | void LoadVariant(rapidjson::Value& value, size_t index, variant<Args...
FILE: kapok/JsonUtil.hpp
type kapok (line 11) | namespace kapok {
class JsonUtil (line 12) | class JsonUtil : NonCopyable
method JsonUtil (line 17) | JsonUtil() : m_writer(m_buf)
method WriteJson (line 22) | void WriteJson(const char* key, T&& value)
method WriteJson (line 29) | void WriteJson(const std::string& key, T&& value)
method Reset (line 35) | void Reset()
method StartObject (line 41) | void StartObject()
method EndObject (line 46) | void EndObject()
method StartArray (line 51) | void StartArray()
method EndArray (line 56) | void EndArray()
method WriteValue (line 61) | void WriteValue(const char* val)
method ReadValue (line 69) | void ReadValue(char*& t, rapidjson::Value& val)
method WriteValue (line 75) | void WriteValue(const std::string& val)
method ReadValue (line 80) | void ReadValue(std::string& t, rapidjson::Value& val)
method Parse (line 86) | void Parse(const char* json)
method Parse (line 95) | void Parse(const char* json, std::size_t length)
method WriteValue (line 109) | void WriteValue(uint8_t val)
method ReadValue (line 114) | void ReadValue(uint8_t& t, rapidjson::Value& val)
method WriteValue (line 120) | void WriteValue(int8_t val)
method ReadValue (line 125) | void ReadValue(int8_t& t, rapidjson::Value& val)
method WriteValue (line 131) | void WriteValue(int16_t val)
method ReadValue (line 136) | void ReadValue(int16_t& t, rapidjson::Value& val)
method WriteValue (line 142) | void WriteValue(uint16_t val)
method ReadValue (line 147) | void ReadValue(uint16_t& t, rapidjson::Value& val)
method WriteValue (line 153) | void WriteValue(int val)
method ReadValue (line 158) | void ReadValue(int& t, rapidjson::Value& val)
method WriteValue (line 164) | void WriteValue(char val)
method ReadValue (line 169) | void ReadValue(char& t, rapidjson::Value& val)
method WriteValue (line 175) | void WriteValue(uint32_t val)
method ReadValue (line 180) | void ReadValue(uint32_t& t, rapidjson::Value& val)
method WriteValue (line 186) | void WriteValue(int64_t val)
method ReadValue (line 191) | void ReadValue(int64_t& t, rapidjson::Value& val)
method WriteValue (line 197) | void WriteValue(uint64_t val)
method ReadValue (line 202) | void ReadValue(uint64_t& t, rapidjson::Value& val)
method WriteValue (line 208) | void WriteValue(double val)
method ReadValue (line 213) | void ReadValue(double& t, rapidjson::Value& val)
method WriteValue (line 219) | void WriteValue(float val)
method ReadValue (line 224) | void ReadValue(float& t, rapidjson::Value& val)
method WriteValue (line 231) | typename std::enable_if<std::is_same<T, bool>::value>::type WriteVal...
method WriteValue (line 238) | typename std::enable_if<is_pointer_ext<T>::value>::type WriteValue(T...
method WriteNull (line 244) | void WriteNull()
method ReadValue (line 249) | void ReadValue(bool& t, rapidjson::Value& val)
FILE: kapok/Serializer.hpp
type kapok (line 12) | namespace kapok {
class Serializer (line 13) | class Serializer : NonCopyable
method Serializer (line 17) | Serializer()
method Serialize (line 45) | void Serialize(const T& t, const char* key = nullptr)
method SerializeImpl (line 60) | void SerializeImpl(T const& t, const char* key)
method has_space (line 85) | bool has_space(const char* str)
method WriteObject (line 98) | std::enable_if_t<is_optional<T>::value> WriteObject(T const& t, Begi...
type serialize_visitor (line 120) | struct serialize_visitor : boost::static_visitor<>
method serialize_visitor (line 122) | explicit serialize_visitor(Serializer& s, int which)
method WriteObject (line 144) | void WriteObject(variant<Args...> const& v, BeginObj bj)
method WriteObject (line 158) | typename std::enable_if<is_user_class<T>::value>::type WriteObject(c...
method WriteObject (line 166) | typename std::enable_if<is_tuple<T>::value>::type WriteObject(T cons...
method WriteTuple (line 174) | typename std::enable_if<I == std::tuple_size<Tuple>::value>::type Wr...
method WriteTuple (line 179) | typename std::enable_if<I < std::tuple_size<Tuple>::value>::type Wri...
method WriteObject (line 186) | typename std::enable_if<is_singlevalue_container<T>::value>::type Wr...
method WriteAdaptor (line 192) | auto WriteAdaptor(Adaptor&& adaptor, F get)
method WriteObject (line 206) | auto WriteObject(T&& t, BeginObject) -> std::enable_if_t<is_queue<T>...
method WriteObject (line 212) | auto WriteObject(T&& t, BeginObject) -> std::enable_if_t<is_stack<T>...
method WriteObject (line 218) | typename std::enable_if<is_map_container<T>::value>::type WriteObjec...
method WriteObject (line 232) | typename std::enable_if<is_pair<T>::value>::type WriteObject(T const...
method WriteObject (line 242) | typename std::enable_if<is_pair<T>::value>::type WriteObject(T const...
method WriteObject (line 251) | void WriteObject(std::array<T, N> const& t, BeginObject)
method WriteObject (line 257) | void WriteObject(T const(&p)[N], BeginObject)
method WriteObject (line 263) | void WriteObject(char const(&p)[N], BeginObject bj)
method WriteArray (line 275) | inline void WriteArray(Array const& v)
method WriteObject (line 286) | typename std::enable_if<is_basic_type<T>::value>::type WriteObject(T...
method WriteObject (line 292) | auto WriteObject(T const& val, BeginObject) ->std::enable_if_t<std::...
method WriteObject (line 300) | void WriteObject(const char* t, std::true_type)
method WriteObject (line 305) | void WriteObject(const char* t, std::false_type)
method WriteKV (line 317) | void WriteKV(const char* k, V& v)
method BeginWriteKV (line 324) | void BeginWriteKV(const char* k, V& v)
method WriteValue (line 332) | typename std::enable_if<is_basic_type<T>::value>::type WriteValue(T ...
method WriteNull (line 337) | void WriteNull()
FILE: kapok/traits.hpp
type kapok (line 17) | namespace kapok {
type variant (line 19) | struct variant : boost::variant<boost::blank, Args...>
method variant (line 30) | variant& operator= (T&& t)
type detail (line 67) | namespace detail
type is_instantiation_of (line 75) | struct is_instantiation_of : std::false_type {}
type is_tuple (line 81) | struct is_tuple : is_instantiation_of<std::tuple, T>
type has_begin_end (line 87) | struct has_begin_end
type has_const_iterator (line 101) | struct has_const_iterator
type has_mapped_type (line 114) | struct has_mapped_type
type is_poiner_extent (line 141) | struct is_poiner_extent : std::false_type{}
type is_poiner_extent<std::shared_ptr<T>> (line 142) | struct is_poiner_extent<std::shared_ptr<T>> : std::true_type{}
type is_poiner_extent<std::unique_ptr<T>> (line 143) | struct is_poiner_extent<std::unique_ptr<T>> : std::true_type{}
type is_poiner_extent<std::weak_ptr<T>> (line 144) | struct is_poiner_extent<std::weak_ptr<T>> : std::true_type{}
type is_std_array (line 155) | struct is_std_array : std::false_type {}
type is_std_array<std::array<T, N>> (line 158) | struct is_std_array<std::array<T, N>> : std::true_type {}
type is_string (line 161) | struct is_string : std::integral_constant<bool, std::is_same<detail::d...
type is_container (line 164) | struct is_container : public std::integral_constant<bool, detail::has_...
type is_singlevalue_container (line 167) | struct is_singlevalue_container : public std::integral_constant<bool, ...
type is_map_container (line 170) | struct is_map_container : public std::integral_constant<bool, is_conta...
type is_normal_class (line 173) | struct is_normal_class : std::integral_constant<bool, std::is_class<de...
type is_basic_type (line 177) | struct is_basic_type : std::integral_constant<bool, std::is_arithmetic...
type is_smart_pointer (line 181) | struct is_smart_pointer : detail::is_poiner_extent<detail::decay_t<T>>{}
type is_pointer_ext (line 184) | struct is_pointer_ext : std::integral_constant<bool, std::is_pointer<d...
type is_specialization_of (line 187) | struct is_specialization_of : std::false_type {}
type is_optional (line 192) | struct is_optional : is_specialization_of<detail::decay_t<T>, boost::o...
type is_tuple (line 193) | struct is_tuple : is_specialization_of<detail::decay_t<T>, std::tuple>{}
type is_queue (line 194) | struct is_queue : is_specialization_of<detail::decay_t<T>, std::queue>{}
type is_stack (line 195) | struct is_stack : is_specialization_of<detail::decay_t<T>, std::stack>{}
type is_set (line 196) | struct is_set : is_specialization_of<detail::decay_t<T>, std::set> {}
type is_multiset (line 197) | struct is_multiset : is_specialization_of<detail::decay_t<T>, std::mul...
type is_unordered_set (line 198) | struct is_unordered_set : is_specialization_of<detail::decay_t<T>, std...
type is_priority_queue (line 199) | struct is_priority_queue : is_specialization_of<detail::decay_t<T>, st...
type is_pair (line 200) | struct is_pair : is_specialization_of<detail::decay_t<T>, std::pair> {}
type is_variant (line 201) | struct is_variant : is_specialization_of<detail::decay_t<T>, variant> {}
type is_container_adapter (line 213) | struct is_container_adapter : std::integral_constant<bool, is_queue<T>...
type is_user_class (line 218) | struct is_user_class : std::integral_constant<bool, is_normal_class<T>...
type is_instantiation_of< U, U<Args...> > (line 78) | struct is_instantiation_of< U, U<Args...> > : std::true_type {}
type is_specialization_of<Template<Args...>, Template> (line 190) | struct is_specialization_of<Template<Args...>, Template> : std::true_type{}
FILE: main.cpp
function test (line 15) | void test()
function test_array (line 28) | void test_array( T& arr)
function test_map (line 42) | void test_map( T& map)
type person (line 55) | struct person
function test_object (line 64) | void test_object(T& t)
type test_p (line 77) | struct test_p
type complex_t (line 87) | struct complex_t
type complex_t1 (line 98) | struct complex_t1
function test_recurse1 (line 107) | void test_recurse1()
function test_recurse (line 122) | void test_recurse()
function test_new_meta (line 137) | void test_new_meta()
function test_performance (line 156) | void test_performance()
function test_tuple (line 181) | void test_tuple()
type my_person (line 201) | struct my_person
function test_myperson (line 208) | void test_myperson()
type T (line 222) | struct T
function test_simple (line 230) | void test_simple()
function test_array (line 242) | void test_array()
function test_const (line 252) | void test_const(const person& p)
function test_stack (line 260) | void test_stack()
type messager (line 276) | struct messager
function test_sr (line 283) | void test_sr()
function test_str (line 292) | void test_str()
function test_optional (line 300) | void test_optional()
type foo_enum (line 342) | enum class foo_enum
function test_enum (line 348) | void test_enum()
function test_pair (line 385) | void test_pair()
function test_variant (line 403) | void test_variant()
function TEST_CASE (line 422) | TEST_CASE(example)
FILE: rapidjson/allocators.h
function RAPIDJSON_NAMESPACE_BEGIN (line 20) | RAPIDJSON_NAMESPACE_BEGIN
function Clear (line 145) | void Clear() {
function Capacity (line 158) | size_t Capacity() const {
function Free (line 222) | static void Free(void *ptr) { (void)ptr; }
function AddChunk (line 233) | void AddChunk(size_t capacity) {
type ChunkHeader (line 248) | struct ChunkHeader {
FILE: rapidjson/document.h
function RAPIDJSON_DIAG_PUSH (line 28) | RAPIDJSON_DIAG_PUSH
type GenericMember (line 106) | typedef GenericMember<Encoding,Allocator> PlainType;
type typename (line 107) | typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
type std (line 108) | typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
type typename (line 119) | typedef typename BaseType::pointer Pointer;
type typename (line 121) | typedef typename BaseType::reference Reference;
type typename (line 123) | typedef typename BaseType::difference_type DifferenceType;
function ptr_ (line 147) | GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
function ConstIterator (line 169) | bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
function ConstIterator (line 170) | bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
function ConstIterator (line 171) | bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
function ConstIterator (line 172) | bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
function operator (line 173) | bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
function operator (line 174) | bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
function Reference (line 179) | Reference operator*() const { return *ptr_; }
function Pointer (line 180) | Pointer operator->() const { return ptr_; }
function Reference (line 181) | Reference operator[](DifferenceType n) const { return ptr_[n]; }
type CharType (line 248) | typedef CharType Ch;
function explicit (line 300) | explicit GenericStringRef(const CharType* str)
function operator (line 320) | operator const Ch *() const { return s; }
function namespace (line 389) | namespace internal {
function namespace (line 406) | namespace internal {
function Is (line 480) | static bool Is(const ValueType& v) { return v.IsString(); }
function StringType (line 481) | static StringType Get(const ValueType& v) { return v.GetString(); }
type typename (line 488) | typedef typename ValueType::Array ArrayType;
function Is (line 489) | static bool Is(const ValueType& v) { return v.IsArray(); }
function ArrayType (line 490) | static ArrayType Get(ValueType& v) { return v.GetArray(); }
type typename (line 497) | typedef typename ValueType::ConstArray ArrayType;
function Is (line 498) | static bool Is(const ValueType& v) { return v.IsArray(); }
function ArrayType (line 499) | static ArrayType Get(const ValueType& v) { return v.GetArray(); }
type typename (line 504) | typedef typename ValueType::Object ObjectType;
function Is (line 505) | static bool Is(const ValueType& v) { return v.IsObject(); }
function ObjectType (line 506) | static ObjectType Get(ValueType& v) { return v.GetObject(); }
type typename (line 513) | typedef typename ValueType::ConstObject ObjectType;
function Is (line 514) | static bool Is(const ValueType& v) { return v.IsObject(); }
function ObjectType (line 515) | static ObjectType Get(const ValueType& v) { return v.GetObject(); }
type Encoding (line 542) | typedef Encoding EncodingType;
type Allocator (line 543) | typedef Allocator AllocatorType;
type typename (line 544) | typedef typename Encoding::Ch Ch;
type GenericStringRef (line 545) | typedef GenericStringRef<Ch> StringRefType;
type typename (line 546) | typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterat...
type typename (line 547) | typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterato...
type GenericValue (line 548) | typedef GenericValue* ValueIterator;
type GenericValue (line 549) | typedef const GenericValue* ConstValueIterator;
type GenericValue (line 550) | typedef GenericValue<Encoding, Allocator> ValueType;
function explicit (line 623) | explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
function explicit (line 632) | explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
function explicit (line 638) | explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
function explicit (line 644) | explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
function explicit (line 659) | explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
function explicit (line 671) | explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d...
function explicit (line 677) | explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { Se...
function data_ (line 698) | GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
function data_ (line 709) | GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
type GenericValue (line 851) | typedef GenericValue<Encoding, SourceAllocator> RhsType;
function rhs (line 898) | bool operator==(const std::basic_string<Ch>& rhs) const { return *this =...
function GetBool (line 992) | bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags ...
function SizeType (line 1007) | SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data...
function GenericValue (line 1061) | const GenericValue& operator[](const std::basic_string<Ch>& name) const ...
function ConstMemberIterator (line 1066) | ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); ...
function MemberIterator (line 1072) | MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); ...
function MemberIterator (line 1075) | MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); ...
function HasMember (line 1085) | bool HasMember(const Ch* name) const { return FindMember(name) != Member...
function HasMember (line 1096) | bool HasMember(const std::basic_string<Ch>& name) const { return FindMem...
function MemberIterator (line 1123) | MemberIterator FindMember(const Ch* name) {
function ConstMemberIterator (line 1128) | ConstMemberIterator FindMember(const Ch* name) const { return const_cast...
function MemberIterator (line 1163) | MemberIterator FindMember(const std::basic_string<Ch>& name) { return Fi...
function ConstMemberIterator (line 1164) | ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const ...
function RemoveAllMembers (line 1328) | void RemoveAllMembers() {
function RemoveMember (line 1343) | bool RemoveMember(const Ch* name) {
function MemberIterator (line 1371) | MemberIterator RemoveMember(MemberIterator m) {
function MemberIterator (line 1395) | MemberIterator EraseMember(ConstMemberIterator pos) {
function MemberIterator (line 1408) | MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterato...
function EraseMember (line 1429) | bool EraseMember(const Ch* name) {
function Object (line 1449) | Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
function ConstObject (line 1450) | ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return Con...
function SizeType (line 1462) | SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
function Empty (line 1468) | bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size ==...
function GenericValue (line 1492) | const GenericValue& operator[](SizeType index) const { return const_cast...
function ValueIterator (line 1496) | ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsP...
function ValueIterator (line 1499) | ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPoi...
function ValueIterator (line 1601) | ValueIterator Erase(ConstValueIterator pos) {
function ValueIterator (line 1613) | ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
function Array (line 1628) | Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
function ConstArray (line 1629) | ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstA...
function GetDouble (line 1644) | double GetDouble() const {
function Ch (line 1672) | const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data...
function SizeType (line 1677) | SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ...
type Flag (line 1836) | struct Flag {
type String (line 1847) | struct String {
function SetLength (line 1861) | struct ShortString {
type I (line 1873) | struct I {
type U (line 1877) | struct U {
type I (line 1882) | struct I {
type U (line 1886) | struct U {
type ObjectData (line 1896) | struct ObjectData {
type ArrayData (line 1902) | struct ArrayData {
function RAPIDJSON_FORCEINLINE (line 1917) | RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJ...
function RAPIDJSON_FORCEINLINE (line 1918) | RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return...
function RAPIDJSON_FORCEINLINE (line 1919) | RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return ...
function RAPIDJSON_FORCEINLINE (line 1920) | RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* ele...
function RAPIDJSON_FORCEINLINE (line 1921) | RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJS...
function RAPIDJSON_FORCEINLINE (line 1922) | RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { retur...
function SetArrayRaw (line 1925) | void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloca...
function SetObjectRaw (line 1938) | void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
function SetStringRaw (line 1951) | void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
function SetStringRaw (line 1958) | void SetStringRaw(StringRefType s, Allocator& allocator) {
function RawAssign (line 1975) | void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
type GenericValue (line 2001) | typedef GenericValue<UTF8<> > Value;
type GenericValue (line 2018) | typedef GenericValue<Encoding, Allocator> ValueType;
type Allocator (line 2019) | typedef Allocator AllocatorType;
type ClearStackOnExit (line 2309) | struct ClearStackOnExit {
function Bool (line 2325) | bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b)...
function Int (line 2326) | bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); ...
function Uint (line 2327) | bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueTyp...
function Int64 (line 2328) | bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueTyp...
function Uint64 (line 2329) | bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueT...
function Double (line 2330) | bool Double(double d) { new (stack_.template Push<ValueType>()) ValueTyp...
function RawNumber (line 2332) | bool RawNumber(const Ch* str, SizeType length, bool copy) {
function String (line 2340) | bool String(const Ch* str, SizeType length, bool copy) {
function StartObject (line 2348) | bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(k...
function Key (line 2350) | bool Key(const Ch* str, SizeType length, bool copy) { return String(str,...
function EndObject (line 2352) | bool EndObject(SizeType memberCount) {
function StartArray (line 2358) | bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kA...
function EndArray (line 2360) | bool EndArray(SizeType elementCount) {
function ClearStack (line 2372) | void ClearStack() {
function Destroy (line 2381) | void Destroy() {
type GenericDocument (line 2393) | typedef GenericDocument<UTF8<> > Document;
type ValueT (line 2434) | typedef ValueT PlainType;
type typename (line 2435) | typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
type ValueType (line 2436) | typedef ValueType* ValueIterator;
type ValueT (line 2437) | typedef const ValueT* ConstValueIterator;
type typename (line 2438) | typedef typename ValueType::AllocatorType AllocatorType;
type typename (line 2439) | typedef typename ValueType::StringRefType StringRefType;
function value_ (line 2444) | GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
function GenericArray (line 2455) | GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) con...
function GenericArray (line 2456) | GenericArray PushBack(ValueType& value, AllocatorType& allocator) const ...
function GenericArray (line 2458) | GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const...
function GenericArray (line 2460) | GenericArray PushBack(StringRefType value, AllocatorType& allocator) con...
function ValueIterator (line 2463) | ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(...
function ValueIterator (line 2464) | ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) c...
function value_ (line 2473) | value_(value) {}
type ValueT (line 2487) | typedef ValueT PlainType;
type typename (line 2488) | typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
type GenericMemberIterator (line 2489) | typedef GenericMemberIterator<Const, typename
type GenericMemberIterator (line 2490) | typedef GenericMemberIterator<true, typename
type typename (line 2491) | typedef typename ValueType::AllocatorType AllocatorType;
type typename (line 2492) | typedef typename ValueType::StringRefType StringRefType;
type typename (line 2493) | typedef typename ValueType::EncodingType EncodingType;
type typename (line 2494) | typedef typename ValueType::Ch Ch;
function value_ (line 2499) | GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
function HasMember (line 2512) | bool HasMember(const Ch* name) const { return value_.HasMember(name); }
function MemberIterator (line 2517) | MemberIterator FindMember(const Ch* name) const { return value_.FindMemb...
function GenericObject (line 2525) | GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, A...
function GenericObject (line 2529) | GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorTy...
function GenericObject (line 2530) | GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorTyp...
function GenericObject (line 2531) | GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorTyp...
function GenericObject (line 2532) | GenericObject AddMember(StringRefType name, ValueType&& value, Allocator...
function GenericObject (line 2534) | GenericObject AddMember(StringRefType name, ValueType& value, AllocatorT...
function GenericObject (line 2535) | GenericObject AddMember(StringRefType name, StringRefType value, Allocat...
function RemoveMember (line 2538) | bool RemoveMember(const Ch* name) const { return value_.RemoveMember(nam...
function value_ (line 2559) | value_(value) {}
FILE: rapidjson/encodedstream.h
function RAPIDJSON_DIAG_PUSH (line 27) | RAPIDJSON_DIAG_PUSH
function Ch (line 49) | Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
function Put (line 53) | void Put(Ch) { RAPIDJSON_ASSERT(false); }
function Flush (line 54) | void Flush() { RAPIDJSON_ASSERT(false); }
function Ch (line 55) | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
function PutEnd (line 56) | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
function is_ (line 72) | is_(is) {
function Ch (line 78) | Ch Take() { return is_.Take(); }
function Put (line 82) | void Put(Ch) {}
function Flush (line 83) | void Flush() {}
function Ch (line 84) | Ch* PutBegin() { return 0; }
function PutEnd (line 85) | size_t PutEnd(Ch*) { return 0; }
function os_ (line 105) | os_(os) {
function Put (line 110) | void Put(Ch c) { Encoding::Put(os_, c); }
function Flush (line 111) | void Flush() { os_.Flush(); }
function Ch (line 115) | Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
function Tell (line 116) | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
function Ch (line 157) | Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
function Put (line 161) | void Put(Ch) { RAPIDJSON_ASSERT(false); }
function Flush (line 162) | void Flush() { RAPIDJSON_ASSERT(false); }
function Ch (line 163) | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
function PutEnd (line 164) | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
function DetectType (line 171) | void DetectType() {
type Ch (line 219) | typedef Ch (*TakeFunc)(InputByteStream& is);
function Put (line 260) | void Put(Ch c) { putFunc_(*os_, c); }
function Flush (line 261) | void Flush() { os_->Flush(); }
function Ch (line 265) | Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
function Tell (line 266) | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
function PutBOM (line 274) | void PutBOM() {
FILE: rapidjson/encodings.h
function RAPIDJSON_DIAG_PUSH (line 25) | RAPIDJSON_DIAG_PUSH
function else (line 131) | else if (codepoint <= 0xFFFF) {
function GetRange (line 200) | static unsigned char GetRange(unsigned char c) {
type CharType (line 266) | typedef CharType Ch;
type CharType (line 415) | typedef CharType Ch;
type CharType (line 539) | typedef CharType Ch;
type UTFType (line 599) | enum UTFType {
type CharType (line 612) | typedef CharType Ch;
function Encode (line 619) | static void Encode(OutputStream& os, unsigned codepoint) {
function EncodeUnsafe (line 626) | static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
function Decode (line 633) | static bool Decode(InputStream& is, unsigned* codepoint) {
function Validate (line 640) | static bool Validate(InputStream& is, OutputStream& os) {
function Transcode (line 657) | static bool Transcode(InputStream& is, OutputStream& os) {
function TranscodeUnsafe (line 666) | static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
function Validate (line 676) | static bool Validate(InputStream& is, OutputStream& os) {
function Transcode (line 689) | static bool Transcode(InputStream& is, OutputStream& os) {
function TranscodeUnsafe (line 695) | static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
function Validate (line 701) | static bool Validate(InputStream& is, OutputStream& os) {
FILE: rapidjson/error/en.h
function RAPIDJSON_DIAG_PUSH (line 21) | RAPIDJSON_DIAG_PUSH
FILE: rapidjson/error/error.h
function RAPIDJSON_NAMESPACE_BEGIN (line 55) | RAPIDJSON_NAMESPACE_BEGIN
type RAPIDJSON_ERROR_CHARTYPE (line 147) | typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorC...
FILE: rapidjson/filereadstream.h
function RAPIDJSON_DIAG_PUSH (line 22) | RAPIDJSON_DIAG_PUSH
function Ch (line 51) | Ch Take() { Ch c = *current_; Read(); return c; }
function Put (line 55) | void Put(Ch) { RAPIDJSON_ASSERT(false); }
function Flush (line 56) | void Flush() { RAPIDJSON_ASSERT(false); }
function Ch (line 57) | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
function PutEnd (line 58) | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
function Ch (line 61) | const Ch* Peek4() const {
FILE: rapidjson/filestream.h
function RAPIDJSON_NAMESPACE_BEGIN (line 27) | RAPIDJSON_NAMESPACE_BEGIN
FILE: rapidjson/filewritestream.h
function RAPIDJSON_DIAG_PUSH (line 22) | RAPIDJSON_DIAG_PUSH
function Put (line 40) | void Put(char c) {
function PutN (line 47) | void PutN(char c, size_t n) {
function Flush (line 63) | void Flush() {
function Peek (line 75) | char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
function Tell (line 77) | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
function PutEnd (line 79) | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
function PutN (line 94) | inline void PutN(FileWriteStream& stream, char c, size_t n) {
FILE: rapidjson/fwd.h
type GenericStringStream (line 49) | typedef GenericStringStream<UTF8<char> > StringStream;
type GenericInsituStringStream (line 54) | typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
type GenericStringBuffer (line 61) | typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
type GenericMemoryBuffer (line 76) | typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
type MemoryStream (line 80) | struct MemoryStream
type GenericReader (line 90) | typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
type GenericValue (line 116) | typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
type GenericDocument (line 121) | typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, C...
type GenericPointer (line 128) | typedef GenericPointer<Value, CrtAllocator> Pointer;
type GenericSchemaDocument (line 138) | typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
type IGenericRemoteSchemaDocumentProvider (line 139) | typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSche...
type GenericSchemaValidator (line 147) | typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<ch...
FILE: rapidjson/internal/biginteger.h
function RAPIDJSON_NAMESPACE_BEGIN (line 25) | RAPIDJSON_NAMESPACE_BEGIN
function Difference (line 186) | bool Difference(const BigInteger& rhs, BigInteger* out) const {
function Compare (line 208) | int Compare(const BigInteger& rhs) const {
function Type (line 220) | Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); re...
function PushBack (line 234) | void PushBack(Type digit) {
function ParseUint64 (line 239) | static uint64_t ParseUint64(const char* begin, const char* end) {
function MulAdd64 (line 249) | static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* o...
FILE: rapidjson/internal/diyfp.h
function RAPIDJSON_DIAG_PUSH (line 39) | RAPIDJSON_DIAG_PUSH
type uint128 (line 78) | __extension__ typedef unsigned __int128 uint128;
function DiyFp (line 119) | DiyFp NormalizeBoundary() const {
function NormalizedBoundaries (line 130) | void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
function ToDouble (line 139) | double ToDouble() const {
function DiyFp (line 226) | inline DiyFp GetCachedPower(int e, int* K) {
function DiyFp (line 240) | inline DiyFp GetCachedPower10(int exp, int *outExp) {
FILE: rapidjson/internal/dtoa.h
function RAPIDJSON_NAMESPACE_BEGIN (line 26) | RAPIDJSON_NAMESPACE_BEGIN
FILE: rapidjson/internal/ieee754.h
function RAPIDJSON_NAMESPACE_BEGIN (line 20) | RAPIDJSON_NAMESPACE_BEGIN
FILE: rapidjson/internal/itoa.h
function RAPIDJSON_NAMESPACE_BEGIN (line 20) | RAPIDJSON_NAMESPACE_BEGIN
FILE: rapidjson/internal/meta.h
function RAPIDJSON_NAMESPACE_BEGIN (line 34) | RAPIDJSON_NAMESPACE_BEGIN
FILE: rapidjson/internal/pow10.h
function RAPIDJSON_NAMESPACE_BEGIN (line 20) | RAPIDJSON_NAMESPACE_BEGIN
FILE: rapidjson/internal/regex.h
function RAPIDJSON_DIAG_PUSH (line 23) | RAPIDJSON_DIAG_PUSH
function AddState (line 646) | bool AddState(Stack<Allocator>& l, SizeType index) const {
function MatchRange (line 661) | bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
type GenericRegex (line 688) | typedef GenericRegex<UTF8<> > Regex;
FILE: rapidjson/internal/stack.h
function RAPIDJSON_DIAG_PUSH (line 22) | RAPIDJSON_DIAG_PUSH
function T (line 149) | T* Top() const {
function T (line 158) | T* End() const { return reinterpret_cast<T*>(stackTop_); }
function T (line 164) | T* Bottom() const { return reinterpret_cast<T*>(stack_); }
function Resize (line 199) | void Resize(size_t newCapacity) {
function Destroy (line 206) | void Destroy() {
FILE: rapidjson/internal/strfunc.h
function RAPIDJSON_NAMESPACE_BEGIN (line 20) | RAPIDJSON_NAMESPACE_BEGIN
FILE: rapidjson/internal/strtod.h
function RAPIDJSON_NAMESPACE_BEGIN (line 23) | RAPIDJSON_NAMESPACE_BEGIN
FILE: rapidjson/internal/swap.h
function RAPIDJSON_DIAG_PUSH (line 21) | RAPIDJSON_DIAG_PUSH
FILE: rapidjson/istreamwrapper.h
function Ch (line 57) | Ch Take() {
function Ch (line 70) | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
function Put (line 71) | void Put(Ch) { RAPIDJSON_ASSERT(false); }
function Flush (line 72) | void Flush() { RAPIDJSON_ASSERT(false); }
function PutEnd (line 73) | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
function Ch (line 76) | const Ch* Peek4() const {
type BasicIStreamWrapper (line 103) | typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
type BasicIStreamWrapper (line 104) | typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
FILE: rapidjson/memorystream.h
function RAPIDJSON_DIAG_PUSH (line 21) | RAPIDJSON_DIAG_PUSH
function Ch (line 46) | Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
function Ch (line 49) | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
function Put (line 50) | void Put(Ch) { RAPIDJSON_ASSERT(false); }
function Flush (line 51) | void Flush() { RAPIDJSON_ASSERT(false); }
function PutEnd (line 52) | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
function Ch (line 55) | const Ch* Peek4() const {
FILE: rapidjson/msinttypes/inttypes.h
type imaxdiv_t (line 57) | typedef struct {
function _inline (line 286) | static
FILE: rapidjson/msinttypes/stdint.h
type int_least8_t (line 140) | typedef int8_t int_least8_t;
type int_least16_t (line 141) | typedef int16_t int_least16_t;
type int_least32_t (line 142) | typedef int32_t int_least32_t;
type int_least64_t (line 143) | typedef int64_t int_least64_t;
type uint_least8_t (line 144) | typedef uint8_t uint_least8_t;
type uint_least16_t (line 145) | typedef uint16_t uint_least16_t;
type uint_least32_t (line 146) | typedef uint32_t uint_least32_t;
type uint_least64_t (line 147) | typedef uint64_t uint_least64_t;
type int_fast8_t (line 150) | typedef int8_t int_fast8_t;
type int_fast16_t (line 151) | typedef int16_t int_fast16_t;
type int_fast32_t (line 152) | typedef int32_t int_fast32_t;
type int_fast64_t (line 153) | typedef int64_t int_fast64_t;
type uint_fast8_t (line 154) | typedef uint8_t uint_fast8_t;
type uint_fast16_t (line 155) | typedef uint16_t uint_fast16_t;
type uint_fast32_t (line 156) | typedef uint32_t uint_fast32_t;
type uint_fast64_t (line 157) | typedef uint64_t uint_fast64_t;
type intmax_t (line 169) | typedef int64_t intmax_t;
type uintmax_t (line 170) | typedef uint64_t uintmax_t;
FILE: rapidjson/ostreamwrapper.h
function RAPIDJSON_DIAG_PUSH (line 19) | RAPIDJSON_DIAG_PUSH
function Put (line 47) | void Put(Ch c) {
function Flush (line 51) | void Flush() {
function Peek (line 56) | char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
function Tell (line 58) | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
function PutEnd (line 60) | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
type BasicOStreamWrapper (line 69) | typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
type BasicOStreamWrapper (line 70) | typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
FILE: rapidjson/pointer.h
function RAPIDJSON_DIAG_PUSH (line 27) | RAPIDJSON_DIAG_PUSH
function Token (line 320) | const Token* GetTokens() const { return tokens_; }
function Erase (line 711) | bool Erase(ValueType& root) const {
function NeedPercentEncode (line 786) | bool NeedPercentEncode(Ch c) const {
function Parse (line 798) | void Parse(const Ch* source, size_t length) {
function class (line 976) | class PercentDecodeStream {
function Put (line 1024) | void Put(char c) { // UTF-8 must be byte
type GenericPointer (line 1045) | typedef GenericPointer<Value> Pointer;
FILE: rapidjson/prettywriter.h
function Null (line 85) | bool Null() { PrettyPrefix(kNullType); return Base::Wr...
function Bool (line 86) | bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); ...
function Int (line 87) | bool Int(int i) { PrettyPrefix(kNumberType); return Base::Wr...
function Uint (line 88) | bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::Wr...
function Int64 (line 89) | bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::Wr...
function Uint64 (line 90) | bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::Wr...
function Double (line 91) | bool Double(double d) { PrettyPrefix(kNumberType); return Base::Wr...
function StartObject (line 111) | bool StartObject() {
function StartArray (line 137) | bool StartArray() {
function String (line 167) | bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
function Key (line 168) | bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
function RawValue (line 181) | bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(t...
function WriteIndent (line 228) | void WriteIndent() {
FILE: rapidjson/rapidjson.h
type STATIC_ASSERTION_FAILURE (line 415) | struct STATIC_ASSERTION_FAILURE
FILE: rapidjson/reader.h
function RAPIDJSON_DIAG_PUSH (line 38) | RAPIDJSON_DIAG_PUSH
type ParseFlag (line 143) | enum ParseFlag {
type typename (line 194) | typedef typename Encoding::Ch Ch;
type typename (line 196) | typedef typename internal::SelectIf<internal::IsSame<Derived, void>, Bas...
function Default (line 198) | bool Default() { return true; }
function Null (line 199) | bool Null() { return static_cast<Override&>(*this).Default(); }
function Bool (line 200) | bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
function Int (line 201) | bool Int(int) { return static_cast<Override&>(*this).Default(); }
function Uint (line 202) | bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
function Int64 (line 203) | bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
function Uint64 (line 204) | bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
function Double (line 205) | bool Double(double) { return static_cast<Override&>(*this).Default(); }
function RawNumber (line 207) | bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_c...
function String (line 208) | bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*...
function StartObject (line 209) | bool StartObject() { return static_cast<Override&>(*this).Default(); }
function Key (line 210) | bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Ov...
function EndObject (line 211) | bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(...
function StartArray (line 212) | bool StartArray() { return static_cast<Override&>(*this).Default(); }
function EndArray (line 213) | bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
function namespace (line 219) | namespace internal {
function SkipWhitespace (line 429) | inline void SkipWhitespace(InsituStringStream& is) {
function SkipWhitespace (line 434) | inline void SkipWhitespace(StringStream& is) {
function SkipWhitespace (line 438) | inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
function ClearStack (line 544) | void ClearStack() { stack_.Clear(); }
type ClearStackOnExit (line 547) | struct ClearStackOnExit {
function Consume (line 741) | bool Consume(InputStream& is, typename InputStream::Ch expect) {
function RAPIDJSON_FORCEINLINE (line 779) | RAPIDJSON_FORCEINLINE void Put(Ch c) {
function RAPIDJSON_FORCEINLINE (line 784) | RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
function Ch (line 791) | Ch* Pop() {
type typename (line 1072) | typedef typename InputStream::Ch Ch;
function is (line 1074) | is(s) { (void)reader; }
function RAPIDJSON_FORCEINLINE (line 1078) | RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
function RAPIDJSON_FORCEINLINE (line 1079) | RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
function RAPIDJSON_FORCEINLINE (line 1080) | RAPIDJSON_FORCEINLINE void Push(char) {}
function Tell (line 1082) | size_t Tell() { return is.Tell(); }
function Length (line 1083) | size_t Length() { return 0; }
function RAPIDJSON_FORCEINLINE (line 1099) | RAPIDJSON_FORCEINLINE Ch TakePush() {
function RAPIDJSON_FORCEINLINE (line 1104) | RAPIDJSON_FORCEINLINE void Push(char c) {
function Length (line 1108) | size_t Length() { return stackStream.Length(); }
function RAPIDJSON_FORCEINLINE (line 1126) | RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
type IterativeParsingState (line 1388) | enum IterativeParsingState {
type Token (line 1414) | enum Token {
function RAPIDJSON_FORCEINLINE (line 1433) | RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
function RAPIDJSON_FORCEINLINE (line 1460) | RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingStat...
function IterativeParsingState (line 1627) | IterativeParsingState Transit(IterativeParsingState src, Token token, It...
type GenericReader (line 1840) | typedef GenericReader<UTF8<>, UTF8<> > Reader;
FILE: rapidjson/schema.h
function namespace (line 83) | namespace internal {
function namespace (line 135) | namespace internal {
type typename (line 346) | typedef typename SchemaDocumentType::AllocatorType AllocatorType;
type typename (line 347) | typedef typename SchemaDocumentType::PointerType PointerType;
type typename (line 348) | typedef typename ValueType::EncodingType EncodingType;
type typename (line 349) | typedef typename EncodingType::Ch Ch;
type SchemaValidationContext (line 350) | typedef SchemaValidationContext<SchemaDocumentType> Context;
type Schema (line 351) | typedef Schema<SchemaDocumentType> SchemaType;
type GenericValue (line 352) | typedef GenericValue<EncodingType, AllocatorType> SValue;
type typename (line 388) | typedef typename ValueType::ConstValueIterator ConstValueIterator;
type typename (line 389) | typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
type Hasher (line 407) | typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
function BeginValue (line 601) | bool BeginValue(Context& context) const {
function Null (line 693) | bool Null(Context& context) const {
function Bool (line 699) | bool Bool(Context& context, bool) const {
function Int (line 705) | bool Int(Context& context, int i) const {
function Uint (line 711) | bool Uint(Context& context, unsigned u) const {
function Int64 (line 717) | bool Int64(Context& context, int64_t i) const {
function Uint64 (line 723) | bool Uint64(Context& context, uint64_t u) const {
function Double (line 729) | bool Double(Context& context, double d) const {
function String (line 745) | bool String(Context& context, const Ch* str, SizeType length, bool) const {
function StartObject (line 765) | bool StartObject(Context& context) const {
function Key (line 784) | bool Key(Context& context, const Ch* str, SizeType len, bool) const {
function EndObject (line 829) | bool EndObject(Context& context, SizeType memberCount) const {
function StartArray (line 859) | bool StartArray(Context& context) const {
function EndArray (line 869) | bool EndArray(Context& context, SizeType elementCount) const {
type SchemaValueType (line 926) | enum SchemaValueType {
type internal (line 938) | typedef internal::GenericRegex<EncodingType> RegexType;
type std (line 940) | typedef std::basic_regex<Ch> RegexType;
type RegexType (line 942) | typedef char RegexType;
type SchemaArray (line 945) | struct SchemaArray {
function SchemaType (line 953) | static const SchemaType* GetTypeless() {
function ValueType (line 967) | static const ValueType* GetMember(const ValueType& value, const ValueTyp...
function AssignIfExist (line 972) | static void AssignIfExist(bool& out, const ValueType& value, const Value...
function AssignIfExist (line 978) | static void AssignIfExist(SizeType& out, const ValueType& value, const V...
function AssignIfExist (line 984) | void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument,...
function IsPatternMatch (line 1014) | static bool IsPatternMatch(const RegexType* pattern, const Ch *str, Size...
function IsPatternMatch (line 1029) | static bool IsPatternMatch(const RegexType* pattern, const Ch *str, Size...
function FindPropertyIndex (line 1087) | bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
function CheckInt (line 1100) | bool CheckInt(Context& context, int64_t i) const {
function CheckUint (line 1139) | bool CheckUint(Context& context, uint64_t i) const {
function CheckDoubleMinimum (line 1177) | bool CheckDoubleMinimum(Context& context, double d) const {
function CheckDoubleMaximum (line 1183) | bool CheckDoubleMaximum(Context& context, double d) const {
function CheckDoubleMultipleOf (line 1189) | bool CheckDoubleMultipleOf(Context& context, double d) const {
type Property (line 1198) | struct Property {
type PatternProperty (line 1209) | struct PatternProperty {
function virtual (line 1304) | virtual ~IGenericRemoteSchemaDocumentProvider() {}
type IGenericRemoteSchemaDocumentProvider (line 1324) | typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRem...
type Allocator (line 1325) | typedef Allocator AllocatorType;
type typename (line 1326) | typedef typename ValueType::EncodingType EncodingType;
type typename (line 1327) | typedef typename EncodingType::Ch Ch;
type internal (line 1328) | typedef internal::Schema<GenericSchemaDocument> SchemaType;
type GenericPointer (line 1329) | typedef GenericPointer<ValueType, Allocator> PointerType;
type SchemaRefEntry (line 1410) | struct SchemaRefEntry {
function CreateSchemaRecursive (line 1430) | void CreateSchemaRecursive(const SchemaType** schema, const PointerType&...
function CreateSchema (line 1447) | void CreateSchema(const SchemaType** schema, const PointerType& pointer,...
function HandleRefSchema (line 1459) | bool HandleRefSchema(const PointerType& source, const SchemaType** schem...
function SchemaType (line 1505) | const SchemaType* GetSchema(const PointerType& pointer) const {
function PointerType (line 1512) | PointerType GetPointer(const SchemaType* schema) const {
type GenericSchemaDocument (line 1531) | typedef GenericSchemaDocument<Value> SchemaDocument;
type IGenericRemoteSchemaDocumentProvider (line 1533) | typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSche...
type typename (line 1560) | typedef typename SchemaDocumentType::PointerType PointerType;
type typename (line 1561) | typedef typename SchemaType::EncodingType EncodingType;
type typename (line 1562) | typedef typename EncodingType::Ch Ch;
function Reset (line 1626) | void Reset() {
function Ch (line 1643) | const Ch* GetInvalidSchemaKeyword() const {
function Null (line 1690) | bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (Curren...
function Bool (line 1691) | bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (Curren...
function Int (line 1692) | bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (Curren...
function Uint (line 1693) | bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (Curren...
function Int64 (line 1694) | bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (Curren...
function Uint64 (line 1695) | bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (Curren...
function Double (line 1696) | bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (Curren...
function RawNumber (line 1697) | bool RawNumber(const Ch* str, SizeType length, bool copy)
function String (line 1699) | bool String(const Ch* str, SizeType length, bool copy)
function StartObject (line 1702) | bool StartObject() {
function Key (line 1708) | bool Key(const Ch* str, SizeType len, bool copy) {
function EndObject (line 1716) | bool EndObject(SizeType memberCount) {
function StartArray (line 1723) | bool StartArray() {
function EndArray (line 1729) | bool EndArray(SizeType elementCount) {
function virtual (line 1742) | virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
function virtual (line 1750) | virtual void DestroySchemaValidator(ISchemaValidator* validator) {
function virtual (line 1756) | virtual void* CreateHasher() {
function virtual (line 1760) | virtual uint64_t GetHashCode(void* hasher) {
function virtual (line 1764) | virtual void DestroryHasher(void* hasher) {
function virtual (line 1770) | virtual void* MallocState(size_t size) {
function virtual (line 1774) | virtual void FreeState(void* p) {
type GenericValue (line 1780) | typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
type internal (line 1781) | typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
function BeginValue (line 1813) | bool BeginValue() {
function EndValue (line 1844) | bool EndValue() {
function AppendToken (line 1881) | void AppendToken(const Ch* str, SizeType len) {
function RAPIDJSON_FORCEINLINE (line 1898) | RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (s...
function RAPIDJSON_FORCEINLINE (line 1900) | RAPIDJSON_FORCEINLINE void PopSchema() {
function OutputHandler (line 1913) | static OutputHandler& GetNullHandler() {
type GenericSchemaValidator (line 1933) | typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
type typename (line 1957) | typedef typename InputStream::Ch Ch;
function Ch (line 1990) | const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
FILE: rapidjson/stream.h
function RAPIDJSON_NAMESPACE_BEGIN (line 22) | RAPIDJSON_NAMESPACE_BEGIN
type typename (line 111) | typedef typename Encoding::Ch Ch;
function Ch (line 116) | Ch Take() { return *src_++; }
function Ch (line 119) | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
function Put (line 120) | void Put(Ch) { RAPIDJSON_ASSERT(false); }
function Flush (line 121) | void Flush() { RAPIDJSON_ASSERT(false); }
function PutEnd (line 122) | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
type GenericStringStream (line 134) | typedef GenericStringStream<UTF8<> > StringStream;
type typename (line 145) | typedef typename Encoding::Ch Ch;
function Ch (line 150) | Ch Peek() { return *src_; }
function Ch (line 151) | Ch Take() { return *src_++; }
function Tell (line 152) | size_t Tell() { return static_cast<size_t>(src_ - head_); }
function Put (line 155) | void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
function Ch (line 157) | Ch* PutBegin() { return dst_ = src_; }
function PutEnd (line 158) | size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
function Flush (line 159) | void Flush() {}
function Ch (line 161) | Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
function Pop (line 162) | void Pop(size_t count) { dst_ -= count; }
type GenericInsituStringStream (line 175) | typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
FILE: rapidjson/writer.h
type WriteFlag (line 62) | enum WriteFlag {
function SetMaxDecimalPlaces (line 161) | void SetMaxDecimalPlaces(int maxDecimalPlaces) {
function Null (line 170) | bool Null() { Prefix(kNullType); return WriteNull(); }
function Bool (line 171) | bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return...
function Int (line 172) | bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
function Uint (line 173) | bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
function Int64 (line 174) | bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64...
function Uint64 (line 175) | bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u6...
function Double (line 182) | bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
function StartObject (line 202) | bool StartObject() {
function StartArray (line 221) | bool StartArray() {
function String (line 243) | bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
function Key (line 244) | bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
function RawValue (line 256) | bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); ...
type Level (line 260) | struct Level {
function WriteNull (line 268) | bool WriteNull() {
function WriteBool (line 273) | bool WriteBool(bool b) {
function WriteInt (line 285) | bool WriteInt(int i) {
function WriteUint (line 294) | bool WriteUint(unsigned u) {
function WriteInt64 (line 303) | bool WriteInt64(int64_t i64) {
function WriteUint64 (line 312) | bool WriteUint64(uint64_t u64) {
function WriteDouble (line 321) | bool WriteDouble(double d) {
function WriteString (line 333) | bool WriteString(const Ch* str, SizeType length) {
function ScanWriteUnescapedString (line 407) | bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, s...
function WriteStartObject (line 411) | bool WriteStartObject() { os_->Put('{'); return true; }
function WriteEndObject (line 412) | bool WriteEndObject() { os_->Put('}'); return true; }
function WriteStartArray (line 413) | bool WriteStartArray() { os_->Put('['); return true; }
function WriteEndArray (line 414) | bool WriteEndArray() { os_->Put(']'); return true; }
function WriteRawValue (line 416) | bool WriteRawValue(const Ch* json, size_t length) {
function Prefix (line 425) | void Prefix(Type type) {
function WriteInt (line 459) | bool Writer<StringBuffer>::WriteInt(int i) {
function WriteUint (line 467) | inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
function WriteInt64 (line 475) | inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
function WriteUint64 (line 483) | inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
function WriteDouble (line 491) | inline bool Writer<StringBuffer>::WriteDouble(double d) {
FILE: test/UnitTest.hpp
type BaseCase (line 8) | struct BaseCase
type AbortThisCase (line 16) | struct AbortThisCase {}
class UnitTest (line 18) | class UnitTest
method UnitTest (line 21) | UnitTest() : last_checked_line_{0}, failure_num_{0}, current_case_{nul...
method UnitTest (line 29) | static UnitTest& getInstance()
method runAll (line 35) | void runAll()
method BaseCase (line 45) | BaseCase* currentCase()
method registerTestCase (line 50) | void registerTestCase(BaseCase *test)
method printLastCheckedPoint (line 55) | void printLastCheckedPoint()
method checkFile (line 61) | void checkFile(const std::string& file)
method checkLine (line 66) | void checkLine(size_t line)
method incFailure (line 71) | void incFailure()
method getFailureNum (line 76) | size_t getFailureNum()
type TestCase (line 82) | struct TestCase : BaseCase
method TestCase (line 85) | TestCase(std::function<void()> method, const std::string& name, const ...
method run (line 91) | void run() override
method abort (line 125) | void abort() override
method isAborted (line 130) | bool isAborted() override
function report_and_exit (line 146) | [[noreturn]]
function main (line 154) | int main()
function do_check_failed (line 169) | void do_check_failed(F&& f, Args&&... args)
function do_check_failed (line 175) | void do_check_failed(Msgs&&... msgs)
FILE: test/panic.cpp
function TEST_CASE (line 4) | TEST_CASE(deserialize_with_wrong_key)
function TEST_CASE (line 24) | TEST_CASE(deserialize_with_invalid_string)
FILE: test/primitive.cpp
function TEST_CASE (line 4) | TEST_CASE(char_serialize)
function TEST_CASE (line 12) | TEST_CASE(char_deserialize)
function TEST_CASE (line 22) | TEST_CASE(int_serialize)
function TEST_CASE (line 30) | TEST_CASE(int_deserialize)
function TEST_CASE (line 40) | TEST_CASE(array_serialize)
function TEST_CASE (line 49) | TEST_CASE(array_deserialize)
FILE: test/stl.cpp
function TEST_CASE (line 6) | TEST_CASE(string_serialize)
function TEST_CASE (line 14) | TEST_CASE(string_deserialize)
function TEST_CASE (line 24) | TEST_CASE(array_serialize)
function TEST_CASE (line 32) | TEST_CASE(array_deserialize)
function TEST_CASE (line 43) | TEST_CASE(vector_serialize)
function TEST_CASE (line 51) | TEST_CASE(vector_deserialize)
function TEST_CASE (line 61) | TEST_CASE(queue_serialize)
function TEST_CASE (line 70) | TEST_CASE(queue_deserialize)
function TEST_CASE (line 84) | TEST_CASE(stack_serialize)
function TEST_CASE (line 93) | TEST_CASE(stack_deserialize)
function TEST_CASE (line 107) | TEST_CASE(set_serialize)
function TEST_CASE (line 115) | TEST_CASE(set_deserialize)
function TEST_CASE (line 125) | TEST_CASE(unordered_set_serialize_and_deserialize)
function TEST_CASE (line 138) | TEST_CASE(unordered_set_deserialize)
function TEST_CASE (line 148) | TEST_CASE(map_serialize)
function TEST_CASE (line 156) | TEST_CASE(map_deserialize)
function TEST_CASE (line 166) | TEST_CASE(unordered_map_serialize_and_deserialize)
function TEST_CASE (line 179) | TEST_CASE(unordered_map_deserialize)
function TEST_CASE (line 189) | TEST_CASE(stl_with_user_type)
FILE: test/user.cpp
function TEST_CASE (line 5) | TEST_CASE(user_type_with_primitive)
function TEST_CASE (line 29) | TEST_CASE(user_type_with_string)
function TEST_CASE (line 52) | TEST_CASE(user_type_with_container)
FILE: test_kapok.hpp
function test_func (line 5) | int test_func(int a, int b)
function TEST_CASE (line 10) | TEST_CASE(test_add)
FILE: test_performance.cpp
type person (line 11) | struct person
function test_msgpack (line 19) | void test_msgpack()
type my_person (line 43) | struct my_person
function test_kapok (line 51) | void test_kapok()
function test_fmt (line 74) | void test_fmt()
function test_boost_cast (line 87) | void test_boost_cast()
function test_kapok_all (line 96) | void test_kapok_all()
function test_msgpack_all (line 113) | void test_msgpack_all()
function main (line 130) | int main(void) {
FILE: unit_test.hpp
type BaseCase (line 8) | struct BaseCase
type AbortThisCase (line 16) | struct AbortThisCase {}
class UnitTest (line 18) | class UnitTest
method UnitTest (line 21) | UnitTest() : last_checked_line_{ 0 }, failure_num_{ 0 }, current_case_...
method UnitTest (line 29) | static UnitTest& getInstance()
method runAll (line 35) | void runAll()
method BaseCase (line 45) | BaseCase* currentCase()
method registerTestCase (line 50) | void registerTestCase(BaseCase *test)
method printLastCheckedPoint (line 55) | void printLastCheckedPoint()
method checkFile (line 61) | void checkFile(const std::string& file)
method checkLine (line 66) | void checkLine(size_t line)
method incFailure (line 71) | void incFailure()
method getFailureNum (line 76) | size_t getFailureNum()
type TestCase (line 82) | struct TestCase : BaseCase
method TestCase (line 85) | TestCase(std::function<void()> method, const std::string& name, const ...
method run (line 91) | void run() override
method abort (line 125) | void abort() override
method isAborted (line 130) | bool isAborted() override
function report_and_exit (line 146) | [[noreturn]]
function main (line 154) | int main()
function do_check_failed (line 169) | void do_check_failed(F&& f, Args&&... args)
function do_check_failed (line 175) | void do_check_failed(Msgs&&... msgs)
Condensed preview — 59 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (714K chars).
[
{
"path": ".gitmodules",
"chars": 71,
"preview": "[submodule \"fmt\"]\n\tpath = fmt\n\turl = https://github.com/fmtlib/fmt.git\n"
},
{
"path": "CMakeLists.txt",
"chars": 2338,
"preview": "cmake_minimum_required(VERSION 2.8)\n\nproject(kapok)\nadd_definitions(-DFMT_HEADER_ONLY)\nset(CMAKE_MODULE_PATH ${CMAKE_MOD"
},
{
"path": "LICENSE",
"chars": 11321,
"preview": "Apache License\n Version 2.0, January 2004\n http://www.apache.org/licens"
},
{
"path": "README.md",
"chars": 340,
"preview": "# Kapok\n现在请使用更好的序列化引擎iguana,比kapok更高效,本项目也不再维护,后面只维护iguana。\n更好的序列化库,纯c++14开发,header-only,简洁高效。\n\nKapok---一个更好的序列化/反序列化库\n\n"
},
{
"path": "Test.hpp",
"chars": 417,
"preview": "#include \"kapok/Kapok.hpp\"\n\nvoid Performance()\n{\n\tkapok::Serializer sr;\n\tkapok::DeSerializer dr;\n\t\n\tauto tp = std::make_"
},
{
"path": "kapok/Common.hpp",
"chars": 7870,
"preview": "#pragma once\n\n#include <array>\n#include <tuple>\n\nnamespace kapok {\ntemplate<unsigned N>\nstd::array<std::string, N> split"
},
{
"path": "kapok/DeSerializer.hpp",
"chars": 11547,
"preview": "#pragma once\n#include \"JsonUtil.hpp\"\n#include \"traits.hpp\"\n#include <boost/lexical_cast.hpp>\n\nnamespace kapok {\nclass De"
},
{
"path": "kapok/JsonUtil.hpp",
"chars": 4259,
"preview": "#pragma once\n#include <string>\n#include <cstdint>\n#include \"rapidjson/writer.h\"\n#include \"rapidjson/stringbuffer.h\"\n#inc"
},
{
"path": "kapok/Kapok.hpp",
"chars": 67,
"preview": "#pragma once\n#include \"Serializer.hpp\"\n#include \"DeSerializer.hpp\"\n"
},
{
"path": "kapok/Serializer.hpp",
"chars": 7445,
"preview": "#pragma once\n#include <typeinfo>\n#ifndef _MSC_VER\n#include <cxxabi.h>\n#endif\n#include \"traits.hpp\"\n#include \"Common.hpp\""
},
{
"path": "kapok/traits.hpp",
"chars": 7341,
"preview": "#pragma once\n#include <memory>\n#include <type_traits>\n#include <vector>\n#include <array>\n#include <queue>\n#include <stac"
},
{
"path": "main.cpp",
"chars": 9575,
"preview": "#include <array>\n#include <vector>\n#include <string>\n#include <set>\n#include <queue>\n#include <deque>\n#include <map>\n#in"
},
{
"path": "rapidjson/allocators.h",
"chars": 10169,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/document.h",
"chars": 113273,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/encodedstream.h",
"chars": 10686,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/encodings.h",
"chars": 28468,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/error/en.h",
"chars": 3870,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/error/error.h",
"chars": 5824,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/filereadstream.h",
"chars": 2988,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/filestream.h",
"chars": 2571,
"preview": "// Copyright (C) 2011 Milo Yip\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of "
},
{
"path": "rapidjson/filewritestream.h",
"chars": 3139,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/fwd.h",
"chars": 4035,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/biginteger.h",
"chars": 9139,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/diyfp.h",
"chars": 11512,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/dtoa.h",
"chars": 8104,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/ieee754.h",
"chars": 3022,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/itoa.h",
"chars": 10306,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/meta.h",
"chars": 6572,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/pow10.h",
"chars": 3595,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/regex.h",
"chars": 24825,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/stack.h",
"chars": 7026,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/strfunc.h",
"chars": 1897,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/strtod.h",
"chars": 8668,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/internal/swap.h",
"chars": 1419,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n//\n// Copyright (C) 2015 THL A"
},
{
"path": "rapidjson/istreamwrapper.h",
"chars": 3464,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/memorybuffer.h",
"chars": 2560,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/memorystream.h",
"chars": 2667,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/msinttypes/inttypes.h",
"chars": 8372,
"preview": "// ISO C9x compliant inttypes.h for Microsoft Visual Studio\n// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) "
},
{
"path": "rapidjson/msinttypes/stdint.h",
"chars": 9386,
"preview": "// ISO C9x compliant stdint.h for Microsoft Visual Studio\n// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG"
},
{
"path": "rapidjson/ostreamwrapper.h",
"chars": 2219,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/pointer.h",
"chars": 58368,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/prettywriter.h",
"chars": 9456,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/rapidjson.h",
"chars": 21414,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/reader.h",
"chars": 78510,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n//\n// Copyright (C) 2015 THL A"
},
{
"path": "rapidjson/schema.h",
"chars": 80134,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available->\n// \n// Copyright (C) 2015 THL"
},
{
"path": "rapidjson/stream.h",
"chars": 5474,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/stringbuffer.h",
"chars": 3798,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "rapidjson/writer.h",
"chars": 21629,
"preview": "// Tencent is pleased to support the open source community by making RapidJSON available.\n// \n// Copyright (C) 2015 THL "
},
{
"path": "test/CMakeLists.txt",
"chars": 321,
"preview": "SET(TEST_SOURCES\n\ttest.cpp\n primitive.cpp\n stl.cpp\n user.cpp\n panic.cpp\n)\n\nINCLUDE_DIRECTORIES(..)\nADD_EXECU"
},
{
"path": "test/UnitTest.hpp",
"chars": 7275,
"preview": "#pragma once\n#include <functional>\n#include <vector>\n#include <string>\n#include <iostream>\n#include <csignal>\n\nstruct Ba"
},
{
"path": "test/panic.cpp",
"chars": 900,
"preview": "#include \"unit_test.hpp\"\n#include \"kapok/Kapok.hpp\"\n\nTEST_CASE(deserialize_with_wrong_key)\n{\n\tusing namespace kapok;\n "
},
{
"path": "test/primitive.cpp",
"chars": 1310,
"preview": "#include \"unit_test.hpp\"\n#include \"kapok/Kapok.hpp\"\n\nTEST_CASE(char_serialize)\n{\n\tusing namespace kapok;\n Serializer "
},
{
"path": "test/stl.cpp",
"chars": 5405,
"preview": "#include \"unit_test.hpp\"\n#include \"kapok/Kapok.hpp\"\n#include <map>\n#include <unordered_map>\n\nTEST_CASE(string_serialize)"
},
{
"path": "test/user.cpp",
"chars": 1932,
"preview": "#include \"UnitTest.hpp\"\n#include \"kapok/Kapok.hpp\"\n#include <map>\n\nTEST_CASE(user_type_with_primitive)\n{\n using names"
},
{
"path": "test_kapok.hpp",
"chars": 164,
"preview": "#pragma once\n#define TEST_MAIN\n#include \"unit_test.hpp\"\n\nint test_func(int a, int b)\n{\n\treturn a + b;\n}\n\nTEST_CASE(test_"
},
{
"path": "test_performance.cpp",
"chars": 2234,
"preview": "#include <msgpack.hpp>\n#include <iostream>\n#include <vector>\n#include <string>\n#include <boost/timer.hpp>\n#include <kapo"
},
{
"path": "unit_test.hpp",
"chars": 6690,
"preview": "#pragma once\n#include <functional>\n#include <vector>\n#include <string>\n#include <iostream>\n#include <csignal>\n\nstruct Ba"
},
{
"path": "vcproject/vcproject/vcproject.vcxproj",
"chars": 7354,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.micros"
},
{
"path": "vcproject/vcproject.sln",
"chars": 1279,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.23107.0\nMini"
}
]
About this extraction
This page contains the full source code of the qicosmos/Kapok GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 59 files (669.9 KB), approximately 174.3k tokens, and a symbol index with 821 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.