├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── examples ├── CMakeLists.txt ├── addressbook.proto ├── example.cpp ├── example_protobuf.cpp └── profile_json.cpp ├── include └── serialization │ ├── detail │ ├── binary_iarchive.h │ ├── binary_oarchive.h │ ├── byte_order.h │ ├── config.h │ ├── endian.h │ ├── json_iarchive.h │ ├── json_oarchive.h │ ├── meta.h │ ├── rapidjson │ │ ├── allocators.h │ │ ├── cursorstreamwrapper.h │ │ ├── document.h │ │ ├── encodedstream.h │ │ ├── encodings.h │ │ ├── error │ │ │ ├── en.h │ │ │ └── error.h │ │ ├── filereadstream.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 │ ├── rapidxml │ │ ├── rapidxml.hpp │ │ ├── rapidxml_iterators.hpp │ │ ├── rapidxml_print.hpp │ │ └── rapidxml_utils.hpp │ ├── serialization_error.h │ ├── serialization_helper.h │ ├── serialization_unpack.h │ ├── xml_iarchive.h │ └── xml_oarchive.h │ └── serialization.h ├── serialization2.dia ├── serialization2.png └── test ├── CMakeLists.txt ├── jsontest.cpp ├── unittest.cpp ├── unittest.h └── xmltest.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | libstream/include/version.hpp 13 | 14 | # Build results 15 | [Dd]ebug/ 16 | [Dd]ebugPublic/ 17 | [Rr]elease/ 18 | [Rr]eleases/ 19 | [Xx]64/ 20 | [Xx]86/ 21 | [Bb]uild/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | 26 | # Visual Studio 2015 cache/options directory 27 | .vs/ 28 | # Uncomment if you have tasks that create the project's static files in wwwroot 29 | #wwwroot/ 30 | 31 | # MSTest test Results 32 | [Tt]est[Rr]esult*/ 33 | [Bb]uild[Ll]og.* 34 | 35 | # NUNIT 36 | *.VisualState.xml 37 | TestResult.xml 38 | 39 | # Build Results of an ATL Project 40 | [Dd]ebugPS/ 41 | [Rr]eleasePS/ 42 | dlldata.c 43 | 44 | # DNX 45 | project.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Microsoft Azure ApplicationInsights config file 170 | ApplicationInsights.config 171 | 172 | # Windows Store app package directory 173 | AppPackages/ 174 | BundleArtifacts/ 175 | 176 | # Visual Studio cache files 177 | # files ending in .cache can be ignored 178 | *.[Cc]ache 179 | # but keep track of directories ending in .cache 180 | !*.[Cc]ache/ 181 | 182 | # Others 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | orleans.codegen.cs 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # GhostDoc plugin setting file 218 | *.GhostDoc.xml 219 | 220 | # Node.js Tools for Visual Studio 221 | .ntvs_analysis.dat 222 | 223 | # Visual Studio 6 build log 224 | *.plg 225 | 226 | # Visual Studio 6 workspace options file 227 | *.opt 228 | 229 | # Visual Studio LightSwitch build output 230 | **/*.HTMLClient/GeneratedArtifacts 231 | **/*.DesktopClient/GeneratedArtifacts 232 | **/*.DesktopClient/ModelManifest.xml 233 | **/*.Server/GeneratedArtifacts 234 | **/*.Server/ModelManifest.xml 235 | _Pvt_Extensions 236 | 237 | # LightSwitch generated files 238 | GeneratedArtifacts/ 239 | ModelManifest.xml 240 | 241 | # Paket dependency manager 242 | .paket/paket.exe 243 | 244 | # FAKE - F# Make 245 | .fake/ 246 | 247 | vs2017/ 248 | build/ 249 | tcmalloc/ 250 | clang/ 251 | gcc/ 252 | ninja/ 253 | linux/ 254 | 255 | # kdev 256 | .kdev4/ 257 | *.kdev4 258 | btest/ 259 | 260 | build* 261 | .vscode 262 | .vscode/.cmaketools.json 263 | .vscode/launch.json 264 | CMakeLists.txt.user 265 | CMakeLists.txt.asc 266 | CMakeLists.txt.asc.gpg 267 | CMakeLists.txt.gpg 268 | doc 269 | doc/.vscode/.cmaketools.json 270 | doc/.vscode/launch.json 271 | doc/app-none-wap.js 272 | doc/flibpq_public_npay_merchant.sql 273 | doc/name 274 | doc/package-lock.json 275 | doc/package.json 276 | 277 | withopenssl 278 | clang-build/ 279 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | language: cpp 4 | 5 | compiler: 6 | - gcc 7 | - clang 8 | 9 | dist: trusty 10 | 11 | arch: 12 | packages: 13 | - cmake 14 | - gcc 15 | - gtest 16 | - protobuf 17 | script: 18 | - "mkdir build" 19 | - "cd build" 20 | - "cmake ../ -DENABLE_TEST=ON" 21 | - "make -j4" 22 | - "make test" 23 | 24 | script: 25 | - "curl -s https://raw.githubusercontent.com/Jackarain/arch-travis/master/arch-travis.sh | bash" 26 | 27 | branches: 28 | only: 29 | - master 30 | notifications: 31 | recipients: 32 | - zwkno1@gmail.com 33 | email: 34 | on_success: change 35 | on_failure: always 36 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | option(ENABLE_TEST "enablle unittest" OFF) 4 | option(ENABLE_PROTOBUF_EXAMPLE "protobuf example" OFF) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | add_subdirectory(examples) 9 | 10 | if (ENABLE_TEST) 11 | enable_testing() 12 | include(GNUInstallDirs) 13 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) 14 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) 15 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 16 | add_subdirectory(test) 17 | endif() 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## serialization2 2 | 3 | 一个神奇的序列化库。 4 | 消灭可恶的序列化代码。 5 | 6 | ## 示例 7 | 8 | ```cpp 9 | 10 | struct Person 11 | { 12 | std::string name; 13 | std::string number; 14 | 15 | SERIALIZATION_DEFINE(name, age) 16 | }; 17 | 18 | struct AddressBook 19 | { 20 | std::vector people; 21 | 22 | SERIALIZATION_DEFINE(people) 23 | }; 24 | 25 | int main(int argc, char * argv[]) 26 | { 27 | AddressBook ab; 28 | 29 | // 序列化为json 30 | serialization::json_oarchive oa; 31 | serialization::serialize(oa, ab); 32 | 33 | // 打印json数据 34 | std::cout << oa.data() << std::endl; 35 | 36 | // 将json反序列化 37 | AddressBook ab2; 38 | serialization::json_iarchive ia; 39 | ia.load_data(oa.data()); 40 | serialization::unserialize(ia, ab2); 41 | } 42 | 43 | ``` 44 | 45 | 详细使用方法参考examples文件夹 46 | 47 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | project(serialize_example) 4 | 5 | include_directories(../include) 6 | 7 | add_executable(example 8 | example.cpp 9 | ) 10 | 11 | if(ENABLE_PROTOBUF_EXAMPLE) 12 | find_package(Protobuf REQUIRED) 13 | 14 | 15 | FILE(GLOB_RECURSE LibFiles "../include/*/*.h") 16 | add_custom_target(headers SOURCES ${LibFiles}) 17 | 18 | file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto") 19 | PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles}) 20 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 21 | 22 | add_executable(example_protobuf 23 | example_protobuf.cpp 24 | ${ProtoSources} 25 | ${ProtoHeaders} 26 | ) 27 | target_link_libraries(example_protobuf ${PROTOBUF_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) 28 | endif() 29 | 30 | -------------------------------------------------------------------------------- /examples/addressbook.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | message Person 5 | { 6 | string name = 1; 7 | int32 age = 2; 8 | double money = 3; 9 | } 10 | 11 | message AddressBook 12 | { 13 | repeated Person people = 1; 14 | } 15 | -------------------------------------------------------------------------------- /examples/example.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | // print debug message 6 | //#define ENABLE_SERIALIZATION_TRACE 1 7 | 8 | #include 9 | 10 | struct Person 11 | { 12 | std::string name; 13 | int32_t age; 14 | 15 | bool operator==(const Person & other) const 16 | { 17 | return (name == other.name) && (age == other.age); 18 | } 19 | 20 | SERIALIZATION_DEFINE(name, age) 21 | }; 22 | 23 | struct AddressBook 24 | { 25 | std::vector people; 26 | std::optional opt; 27 | std::map mapTest; 28 | std::vector > > vectorTest; 29 | 30 | bool operator==(const AddressBook & other) const 31 | { 32 | return (people == other.people) 33 | && (opt == other.opt) 34 | && (mapTest == other.mapTest) 35 | && (vectorTest == other.vectorTest); 36 | } 37 | 38 | SERIALIZATION_DEFINE(people, opt, mapTest, vectorTest) 39 | }; 40 | 41 | struct Customize 42 | { 43 | int a; 44 | std::string b; 45 | 46 | bool operator==(const Customize & other) const 47 | { 48 | return (a == other.a) && (b == other.b); 49 | } 50 | 51 | SERIALIZATION_DEFINE_META_DATA("aaa", "bbb") 52 | SERIALIZATION_DEFINE_META_FUNC(a, b) 53 | }; 54 | 55 | int main(int argc, char * argv[]) 56 | { 57 | try 58 | { 59 | AddressBook ab = { 60 | { 61 | {"aaaaaaa", 12}, 62 | {"qwasasdq", 22331}, 63 | {"12qweqweqweqwe", 123123} 64 | }, 65 | "opt string", 66 | { 67 | {"a", {"a", 1} }, 68 | {"b", {"b", 2} }, 69 | {"c", {"c", 3} }, 70 | }, 71 | { 72 | { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }, 73 | { {11, 12, 13}, {14, 15, 16} }, 74 | { {21, 22, 23} }, 75 | } 76 | }; 77 | 78 | // json serialize 79 | serialization::json_oarchive json_oa; 80 | serialization::serialize(json_oa, ab); 81 | std::cout << "json serilize result: " << json_oa.data() << std::endl; 82 | 83 | // json unserialize 84 | AddressBook ab2; 85 | serialization::json_iarchive json_ia; 86 | json_ia.load_data(json_oa.data()); 87 | serialization::unserialize(json_ia, ab2); 88 | std::cout << "json unserilize result: " << (ab == ab2 ? "success" : "fail") << std::endl; 89 | 90 | // xml serialize 91 | serialization::xml_oarchive xml_oa; 92 | serialization::serialize(xml_oa, ab); 93 | std::string xml_str = xml_oa.data(); 94 | std::cout << "xml serilize result: " << xml_str << std::endl; 95 | 96 | // xml unserialize 97 | AddressBook ab3; 98 | serialization::xml_iarchive xml_ia; 99 | xml_ia.load_data(&xml_str[0]); 100 | serialization::unserialize(xml_ia, ab3); 101 | std::cout << "xml unserilize result: " << (ab == ab3 ? "success" : "fail") << std::endl; 102 | 103 | //test coustomize 104 | Customize c{123, "456"}, c2; 105 | serialization::serialize(json_oa, c); 106 | std::cout << "customize json serilize result: " << json_oa.data() << std::endl; 107 | json_ia.load_data(json_oa.data()); 108 | serialization::unserialize(json_ia, c2); 109 | std::cout << "customize json unserilize result: " << (c == c2 ? "success" : "fail") << std::endl; 110 | 111 | } 112 | catch (serialization::serialization_error & err) 113 | { 114 | std::cout << err.where() << ":" << err.what() << std::endl; 115 | } 116 | } 117 | 118 | -------------------------------------------------------------------------------- /examples/example_protobuf.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "addressbook.pb.h" 5 | #include 6 | 7 | using namespace std; 8 | 9 | void test(const AddressBook & ab) 10 | { 11 | std::string str = ab.SerializeAsString(); 12 | AddressBook tmp; 13 | if(!tmp.ParseFromString(str)) 14 | { 15 | std::cout << "parse from string error" << std::endl; 16 | } 17 | } 18 | 19 | int main(int argc, char* argv[]) 20 | { 21 | GOOGLE_PROTOBUF_VERIFY_VERSION; 22 | 23 | if (argc != 2) 24 | return -1; 25 | 26 | AddressBook ab; 27 | for(int i = 0; i < 10; ++i) 28 | { 29 | Person* p = ab.add_people(); 30 | p->set_name("zbcdefghijklmnopqrstuvwxyz0123456789"); 31 | p->set_age(18); 32 | p->set_money(123123.123123); 33 | } 34 | 35 | std::string str; 36 | google::protobuf::util::MessageToJsonString(ab, &str); 37 | std::cout << str << std::endl; 38 | for(int i = 0; i < atoi(argv[1]); ++i) 39 | { 40 | google::protobuf::util::MessageToJsonString(ab, &str); 41 | str.clear(); 42 | } 43 | //str = ab.SerializeAsString(); 44 | //test(ab); 45 | 46 | google::protobuf::ShutdownProtobufLibrary(); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /examples/profile_json.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | // print debug message 7 | //#define ENABLE_SERIALIZATION_TRACE 1 8 | 9 | #include 10 | 11 | struct Person 12 | { 13 | std::string name; 14 | int32_t age; 15 | double money; 16 | 17 | SERIALIZATION_DEFINE(name, age, money) 18 | }; 19 | 20 | struct AddressBook 21 | { 22 | std::vector people; 23 | //std::vector> address; 24 | //std::map test; 25 | std::optional opt; 26 | //SERIALIZATION_DEFINE(people, address, test, opt) 27 | // 28 | 29 | SERIALIZATION_DEFINE(people, opt) 30 | }; 31 | 32 | 33 | int main(int argc, char * argv[]) 34 | { 35 | if(argc < 3) 36 | return 0; 37 | 38 | AddressBook ab = { 39 | { 40 | {"aaaaaaa", 12, 1123.123}, 41 | {"qwasasdq", 22331, 1212.121}, 42 | {"1234567890qwertyuiopasdfghjklzxcvbnm", 123123, 1212} 43 | }, 44 | "opt string" 45 | }; 46 | 47 | try 48 | { 49 | if(strcmp(argv[1], "serialize_sax") == 0) 50 | { 51 | size_t size = 0; 52 | for(int i = 0; i < atoi(argv[2]); ++i) 53 | { 54 | rapidjson::StringBuffer buffer; 55 | rapidjson::Writer writer{buffer}; 56 | writer.StartObject(); 57 | writer.Key("people"); 58 | writer.StartArray(); 59 | for(auto & i : ab.people) 60 | { 61 | writer.StartObject(); 62 | writer.Key("name"); 63 | writer.String(i.name.c_str(), i.name.length()); 64 | writer.Key("age"); 65 | writer.Int(i.age); 66 | writer.Key("money"); 67 | writer.Double(i.money); 68 | writer.EndObject(); 69 | } 70 | writer.EndArray(); 71 | if(ab.opt) 72 | { 73 | writer.Key("opt"); 74 | writer.String(ab.opt->c_str(), ab.opt->length()); 75 | } 76 | writer.EndObject(); 77 | size += buffer.GetSize(); 78 | //std::cout << buffer.GetString() << std::endl; 79 | } 80 | std::cout << "serialize total size: " << size << std::endl; 81 | } 82 | else if(strcmp(argv[1], "serialize_dom") == 0) 83 | { 84 | size_t size = 0; 85 | for(int i = 0; i < atoi(argv[2]); ++i) 86 | { 87 | rapidjson::Document d; 88 | auto & a = d.GetAllocator(); 89 | d.SetObject(); 90 | rapidjson::Value p{rapidjson::kArrayType}; 91 | for(auto & i : ab.people) 92 | { 93 | rapidjson::Value v{rapidjson::kObjectType}; 94 | v.AddMember("name", rapidjson::Value().SetString(i.name.c_str(), i.name.size()), a); 95 | v.AddMember("age", rapidjson::Value().SetInt(i.age), a); 96 | v.AddMember("money", rapidjson::Value().SetDouble(i.money), a); 97 | p.PushBack(v, a); 98 | } 99 | d.AddMember("people", p, a); 100 | if(ab.opt) 101 | { 102 | d.AddMember("opt", rapidjson::Value().SetString(ab.opt->c_str(), ab.opt->size()), a); 103 | } 104 | rapidjson::StringBuffer buffer; 105 | rapidjson::Writer writer(buffer); 106 | d.Accept(writer); 107 | size += buffer.GetSize(); 108 | //std::cout << buffer.GetString() << std::endl; 109 | } 110 | std::cout << "serialize total size: " << size << std::endl; 111 | } 112 | else if(strcmp(argv[1], "serialize") == 0) 113 | { 114 | size_t size = 0; 115 | for(int i = 0; i < atoi(argv[2]); ++i) 116 | { 117 | // serialize 118 | serialization::json_oarchive oa; 119 | serialization::serialize(oa, ab); 120 | //std::cout << oa.data() << std::endl; 121 | size += oa.size(); 122 | } 123 | std::cout << "serialize total size: " << size << std::endl; 124 | } 125 | else 126 | { 127 | for(int i = 0; i < atoi(argv[2]); ++i) 128 | { 129 | // unserialize 130 | serialization::json_iarchive ia; 131 | ia.load_data(R"({"people":[{"name":"aaaaaaa","age":12,"money":1123.123},{"name":"qwasasdq","age":22331,"money":1212.121},{"name":"1234567890qwertyuiopasdfghjklzxcvbnm","age":123123,"money":1212.0}],"opt":"opt string"})"); 132 | AddressBook ab2; 133 | serialization::unserialize(ia, ab2); 134 | } 135 | } 136 | } 137 | catch (serialization::serialization_error & err) 138 | { 139 | std::cout << err.where() << ":" << err.what() << std::endl; 140 | } 141 | } 142 | 143 | -------------------------------------------------------------------------------- /include/serialization/detail/binary_iarchive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #if __cplusplus > 201402L 10 | #include 11 | #endif 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | namespace serialization 21 | { 22 | 23 | class binary_iarchive 24 | { 25 | public: 26 | binary_iarchive(const uint8_t* data, size_t size) 27 | : data_(data, data+size) 28 | , index_(0) 29 | { 30 | } 31 | 32 | template 33 | inline void load_start(Argument & arg) const 34 | { 35 | serialization_trace trace(__func__, __FILE__, __LINE__); 36 | } 37 | 38 | template 39 | inline void load_end(Argument & arg) const 40 | { 41 | serialization_trace trace(__func__, __FILE__, __LINE__); 42 | } 43 | 44 | template 45 | void load(T & out) const 46 | { 47 | serialization_trace trace(__func__, __FILE__, __LINE__); 48 | if(!can_read(sizeof(out))) 49 | throw_serialization_error("load", "data size too short"); 50 | const T * p = reinterpret_cast(&data_[index_]); 51 | out = *p; 52 | index_ += sizeof(out); 53 | } 54 | 55 | void load(std::string & out) const 56 | { 57 | serialization_trace trace(__func__, __FILE__, __LINE__); 58 | size_type size; 59 | load(size); 60 | if(!can_read(size)) 61 | throw_serialization_error("load", "data size too short"); 62 | out = std::string(reinterpret_cast(&data_[index_]), size); 63 | index_ += size; 64 | } 65 | 66 | #if __cplusplus > 201402L 67 | template 68 | void load(std::optional & out) const 69 | { 70 | std::cout << "load optional" << std::endl; 71 | serialization_trace trace(__func__, __FILE__, __LINE__); 72 | uint8_t hasValue; 73 | load(hasValue); 74 | if(hasValue) 75 | { 76 | T value; 77 | load(value); 78 | out = value; 79 | } 80 | } 81 | #endif 82 | 83 | void unserialize_start() const 84 | { 85 | serialization_trace trace(__func__, __FILE__, __LINE__); 86 | index_ = 0; 87 | size_type size; 88 | load(size); 89 | if(size != data_.size()) 90 | throw_serialization_error("unserialize start", "size error"); 91 | } 92 | 93 | void unserialize_end() const 94 | { 95 | serialization_trace trace(__func__, __FILE__, __LINE__); 96 | } 97 | 98 | private: 99 | bool can_read(size_t size) const 100 | { 101 | return index_ + size <= data_.size(); 102 | } 103 | 104 | std::vector data_; 105 | 106 | mutable size_t index_; 107 | }; 108 | 109 | } // namespace serialization 110 | -------------------------------------------------------------------------------- /include/serialization/detail/binary_oarchive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace serialization 16 | { 17 | 18 | class binary_oarchive 19 | { 20 | typedef std::vector::const_iterator const_iterator; 21 | 22 | public: 23 | binary_oarchive() 24 | { 25 | } 26 | 27 | template 28 | void save_start(Argument & arg) const 29 | { 30 | serialization_trace trace(__func__, __FILE__, __LINE__); 31 | } 32 | 33 | template 34 | void save_end(Argument & arg) const 35 | { 36 | serialization_trace trace(__func__, __FILE__, __LINE__); 37 | } 38 | 39 | template 40 | void save(const T & v) 41 | { 42 | serialization_trace trace(__func__, __FILE__, __LINE__); 43 | size_t size = data_.size(); 44 | data_.resize(size + sizeof(v)); 45 | save_at(v, size); 46 | } 47 | 48 | void save(const std::string & v) 49 | { 50 | serialization_trace trace(__func__, __FILE__, __LINE__); 51 | size_type size = v.size(); 52 | save(size); 53 | save_raw(v.data(), v.size()); 54 | } 55 | 56 | #if __cplusplus > 201402L 57 | template 58 | void save(const std::optional & v) 59 | { 60 | serialization_trace trace(__func__, __FILE__, __LINE__); 61 | uint8_t hasValue = v ? 1 : 0; 62 | save(hasValue); 63 | if(hasValue) 64 | { 65 | save(*v); 66 | } 67 | } 68 | #endif 69 | 70 | void serialize_start() 71 | { 72 | serialization_trace trace(__func__, __FILE__, __LINE__); 73 | data_.clear(); 74 | size_type size = 0; 75 | save(size); 76 | } 77 | 78 | void serialize_end() 79 | { 80 | serialization_trace trace(__func__, __FILE__, __LINE__); 81 | size_type size = data_.size(); 82 | save_at(size, 0); 83 | } 84 | 85 | const uint8_t * data() const 86 | { 87 | return data_.data(); 88 | } 89 | 90 | size_t size() const 91 | { 92 | return data_.size(); 93 | } 94 | 95 | const_iterator begin() const 96 | { 97 | return data_.begin(); 98 | } 99 | 100 | const_iterator end() const 101 | { 102 | return data_.end(); 103 | } 104 | 105 | private: 106 | template 107 | void save_at(const T & v, size_t offset) 108 | { 109 | T val = (v); 110 | const uint8_t * p = reinterpret_cast(&val); 111 | assert(data_.size() >= offset + sizeof(val)); 112 | std::copy(p, p + sizeof(val), data_.begin() + offset); 113 | } 114 | 115 | void save_raw(const char * data, size_t size) 116 | { 117 | data_.reserve(data_.size() + size); 118 | data_.insert(data_.end(), data, data+size); 119 | } 120 | 121 | std::vector data_; 122 | }; 123 | 124 | } // namespace serialization 125 | -------------------------------------------------------------------------------- /include/serialization/detail/byte_order.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace serialization 5 | { 6 | 7 | template 8 | inline T ntoh(const T & v) 9 | { 10 | #if defined(USE_LITTLE_ENDIAN) 11 | return endian::letoh(v); 12 | #elif defined(USE_BIG_ENDIAN) 13 | return endian::betoh(v); 14 | #else 15 | return v; 16 | #endif 17 | } 18 | 19 | template 20 | inline T hton(const T & v) 21 | { 22 | #if defined(USE_LITTLE_ENDIAN) 23 | return endian::htole(v); 24 | #elif defined(USE_BIG_ENDIAN) 25 | return endian::htobe(v); 26 | #else 27 | return v; 28 | #endif 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /include/serialization/detail/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define USE_LITTLE_ENDIAN 8 | 9 | namespace serialization 10 | { 11 | 12 | typedef uint32_t size_type; 13 | typedef unsigned int uint; 14 | 15 | #if(ENABLE_SERIALIZATION_TRACE) 16 | struct serialization_trace 17 | { 18 | template 19 | serialization_trace(Args&& ... args) 20 | { 21 | std::stringstream s; 22 | s << ":"; 23 | build(s, std::forward(args)...); 24 | str_ = s.str(); 25 | std::cout << ">"; 26 | print_level(" >"); 27 | std::cout << str_ << std::endl; 28 | ++level_; 29 | } 30 | 31 | template 32 | void build(std::stringstream & s, T t, Args&& ... next) 33 | { 34 | s << t << ","; 35 | build(s, next...); 36 | } 37 | 38 | void build(std::stringstream & s) 39 | { 40 | } 41 | 42 | ~serialization_trace() 43 | { 44 | --level_; 45 | std::cout << "<"; 46 | print_level(" <"); 47 | std::cout << str_ << std::endl; 48 | } 49 | 50 | void print_level(const char * str) 51 | { 52 | for(int i = 0; i < level_; ++i) 53 | { 54 | std::cout << str; 55 | } 56 | } 57 | 58 | std::string str_; 59 | static int level_; 60 | }; 61 | int serialization_trace::level_ = 0; 62 | #else 63 | struct serialization_trace 64 | { 65 | template 66 | serialization_trace(Args&& ... args) 67 | { 68 | } 69 | }; 70 | #endif 71 | 72 | } // namespace serialization 73 | -------------------------------------------------------------------------------- /include/serialization/detail/endian.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) 4 | #define __WINDOWS__ 5 | #endif 6 | 7 | #if defined(__linux__) || defined(__CYGWIN__) 8 | 9 | # include 10 | 11 | #elif defined(__APPLE__) 12 | 13 | # include 14 | 15 | # define htobe16(x) OSSwapHostToBigInt16(x) 16 | # define htole16(x) OSSwapHostToLittleInt16(x) 17 | # define be16toh(x) OSSwapBigToHostInt16(x) 18 | # define le16toh(x) OSSwapLittleToHostInt16(x) 19 | 20 | # define htobe32(x) OSSwapHostToBigInt32(x) 21 | # define htole32(x) OSSwapHostToLittleInt32(x) 22 | # define be32toh(x) OSSwapBigToHostInt32(x) 23 | # define le32toh(x) OSSwapLittleToHostInt32(x) 24 | 25 | # define htobe64(x) OSSwapHostToBigInt64(x) 26 | # define htole64(x) OSSwapHostToLittleInt64(x) 27 | # define be64toh(x) OSSwapBigToHostInt64(x) 28 | # define le64toh(x) OSSwapLittleToHostInt64(x) 29 | 30 | # define __BYTE_ORDER BYTE_ORDER 31 | # define __BIG_ENDIAN BIG_ENDIAN 32 | # define __LITTLE_ENDIAN LITTLE_ENDIAN 33 | # define __PDP_ENDIAN PDP_ENDIAN 34 | 35 | #elif defined(__OpenBSD__) 36 | 37 | # include 38 | 39 | #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) 40 | 41 | # include 42 | 43 | # define be16toh(x) betoh16(x) 44 | # define le16toh(x) letoh16(x) 45 | 46 | # define be32toh(x) betoh32(x) 47 | # define le32toh(x) letoh32(x) 48 | 49 | # define be64toh(x) betoh64(x) 50 | # define le64toh(x) letoh64(x) 51 | 52 | #elif defined(__WINDOWS__) 53 | 54 | # include 55 | 56 | # if !defined(_MSC_VER) 57 | # include 58 | # endif // _MSC_VER 59 | 60 | # if BYTE_ORDER == LITTLE_ENDIAN 61 | 62 | # define htobe16(x) htons(x) 63 | # define htole16(x) (x) 64 | # define be16toh(x) ntohs(x) 65 | # define le16toh(x) (x) 66 | 67 | # define htobe32(x) htonl(x) 68 | # define htole32(x) (x) 69 | # define be32toh(x) ntohl(x) 70 | # define le32toh(x) (x) 71 | 72 | # define htobe64(x) htonll(x) 73 | # define htole64(x) (x) 74 | # define be64toh(x) ntohll(x) 75 | # define le64toh(x) (x) 76 | 77 | # elif BYTE_ORDER == BIG_ENDIAN 78 | 79 | /* that would be xbox 360 */ 80 | # define htobe16(x) (x) 81 | # define htole16(x) __builtin_bswap16(x) 82 | # define be16toh(x) (x) 83 | # define le16toh(x) __builtin_bswap16(x) 84 | 85 | # define htobe32(x) (x) 86 | # define htole32(x) __builtin_bswap32(x) 87 | # define be32toh(x) (x) 88 | # define le32toh(x) __builtin_bswap32(x) 89 | 90 | # define htobe64(x) (x) 91 | # define htole64(x) __builtin_bswap64(x) 92 | # define be64toh(x) (x) 93 | # define le64toh(x) __builtin_bswap64(x) 94 | 95 | # else 96 | 97 | # error byte order not supported 98 | 99 | # endif 100 | 101 | # define __BYTE_ORDER BYTE_ORDER 102 | # define __BIG_ENDIAN BIG_ENDIAN 103 | # define __LITTLE_ENDIAN LITTLE_ENDIAN 104 | # define __PDP_ENDIAN PDP_ENDIAN 105 | 106 | #else 107 | 108 | # error platform not supported 109 | 110 | #endif 111 | 112 | namespace serialization 113 | { 114 | namespace detail 115 | { 116 | 117 | template 118 | struct endian 119 | { 120 | template 121 | inline static T htobe(T t) 122 | { 123 | return t; 124 | } 125 | 126 | template 127 | inline static T betoh(T t) 128 | { 129 | return t; 130 | } 131 | 132 | template 133 | inline static T htole(T t) 134 | { 135 | return t; 136 | } 137 | 138 | template 139 | inline static T letoh(T t) 140 | { 141 | return t; 142 | } 143 | }; 144 | 145 | template<> 146 | struct endian<2> 147 | { 148 | template 149 | inline static T htobe(T t) 150 | { 151 | return htobe16(t); 152 | } 153 | 154 | template 155 | inline static T betoh(T t) 156 | { 157 | return be16toh(t); 158 | } 159 | 160 | template 161 | inline static T htole(T t) 162 | { 163 | return htole16(t); 164 | } 165 | 166 | template 167 | inline static T letoh(T t) 168 | { 169 | return le16toh(t); 170 | } 171 | }; 172 | 173 | template<> 174 | struct endian<4> 175 | { 176 | template 177 | inline static T htobe(T t) 178 | { 179 | return htobe32(t); 180 | } 181 | 182 | template 183 | inline static T betoh(T t) 184 | { 185 | return be32toh(t); 186 | } 187 | 188 | template 189 | inline static T htole(T t) 190 | { 191 | return htole32(t); 192 | } 193 | 194 | template 195 | inline static T letoh(T t) 196 | { 197 | return le32toh(t); 198 | } 199 | }; 200 | 201 | template<> 202 | struct endian<8> 203 | { 204 | template 205 | inline static T htobe(T t) 206 | { 207 | return htobe64(t); 208 | } 209 | 210 | template 211 | inline static T betoh(T t) 212 | { 213 | return be64toh(t); 214 | } 215 | 216 | template 217 | inline static T htole(T t) 218 | { 219 | return htole64(t); 220 | } 221 | 222 | template 223 | inline static T letoh(T t) 224 | { 225 | return le64toh(t); 226 | } 227 | }; 228 | 229 | } // namespace detail 230 | 231 | struct endian 232 | { 233 | template 234 | inline static T betoh(T t) 235 | { 236 | return detail::endian::betoh(t); 237 | } 238 | 239 | template 240 | inline static T htobe(T t) 241 | { 242 | return detail::endian::htobe(t); 243 | } 244 | 245 | template 246 | inline static T htole(T t) 247 | { 248 | return detail::endian::htole(t); 249 | } 250 | 251 | template 252 | inline static T letoh(T t) 253 | { 254 | return detail::endian::letoh(t); 255 | } 256 | }; 257 | 258 | } // namespace serialization 259 | -------------------------------------------------------------------------------- /include/serialization/detail/json_iarchive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace serialization 16 | { 17 | 18 | class json_iarchive 19 | { 20 | public: 21 | json_iarchive() 22 | { 23 | } 24 | 25 | void load_data(const char * data) 26 | { 27 | doc_.Parse(data); 28 | if(doc_.GetParseError()) 29 | { 30 | throw_serialization_error("json", "parse"); 31 | } 32 | } 33 | 34 | void load_key_start(const char * key) const 35 | { 36 | serialization_trace trace(__func__, key); 37 | 38 | if(stack_.empty() || (!stack_.top()->IsObject())) 39 | throw_serialization_error("expect key", key); 40 | 41 | auto iter = stack_.top()->FindMember(key); 42 | if(iter == stack_.top()->MemberEnd()) 43 | throw_serialization_error("expect key", key); 44 | 45 | stack_.push(&iter->value); 46 | } 47 | 48 | bool load_key_start_optional(const char * key) const 49 | { 50 | serialization_trace trace(__func__, key); 51 | 52 | if(stack_.empty() || (!stack_.top()->IsObject())) 53 | throw_serialization_error("expect key", key); 54 | 55 | auto iter = stack_.top()->FindMember(key); 56 | if(iter == stack_.top()->MemberEnd()) 57 | return false; 58 | 59 | stack_.push(&iter->value); 60 | return true; 61 | } 62 | 63 | void load_key_end(const char * key) const 64 | { 65 | serialization_trace trace(__func__, key); 66 | assert(!stack_.empty()); 67 | stack_.pop(); 68 | } 69 | 70 | void load_object_start() const 71 | { 72 | serialization_trace trace(__func__, "json"); 73 | assert(!stack_.empty()); 74 | if(stack_.empty() || (!stack_.top()->IsObject())) 75 | throw_serialization_error("expect object", ""); 76 | } 77 | 78 | void load_object_end() const 79 | { 80 | serialization_trace trace(__func__, "json"); 81 | } 82 | 83 | size_type sequence_size() const 84 | { 85 | if(stack_.empty() || (!stack_.top()->IsArray())) 86 | throw_serialization_error("expect array", ""); 87 | return stack_.top()->GetArray().Size(); 88 | } 89 | 90 | size_type load_sequence_start() const 91 | { 92 | if(stack_.empty() || (!stack_.top()->IsArray())) 93 | throw_serialization_error("expect array", "json"); 94 | return stack_.top()->GetArray().Size(); 95 | } 96 | 97 | void load_sequence_end() const 98 | { 99 | } 100 | 101 | void load_sequence_item_start(size_type i) const 102 | { 103 | serialization_trace trace(__func__, "json"); 104 | assert(!stack_.empty()); 105 | if(i >= stack_.top()->GetArray().Size()) 106 | throw_serialization_error("array size", "json"); 107 | stack_.push(&stack_.top()->GetArray()[i]); 108 | } 109 | 110 | void load_sequence_item_end() const 111 | { 112 | serialization_trace trace(__func__, "json"); 113 | assert(!stack_.empty()); 114 | stack_.pop(); 115 | } 116 | 117 | void load(bool & v) const 118 | { 119 | if(stack_.empty() || (!stack_.top()->IsBool())) 120 | throw_serialization_error("json", "expect bool"); 121 | v = stack_.top()->GetBool(); 122 | } 123 | 124 | void load(int & v) const 125 | { 126 | if(stack_.empty() || (!stack_.top()->IsInt())) 127 | throw_serialization_error("json", "expect int"); 128 | v = stack_.top()->GetInt(); 129 | } 130 | 131 | void load(uint & v) const 132 | { 133 | if(stack_.empty() || (!stack_.top()->IsUint())) 134 | throw_serialization_error("json", "expect uint"); 135 | v = stack_.top()->GetUint(); 136 | } 137 | 138 | void load(int64_t & v) const 139 | { 140 | if(stack_.empty() || (!stack_.top()->IsInt64())) 141 | throw_serialization_error("json", "expect int64"); 142 | v = stack_.top()->GetInt64(); 143 | } 144 | 145 | void load(uint64_t & v) const 146 | { 147 | if(stack_.empty() || (!stack_.top()->IsUint64())) 148 | throw_serialization_error("json", "expect uint64"); 149 | v = stack_.top()->GetUint64(); 150 | } 151 | 152 | template 153 | std::enable_if_t::value> load(T & v) const 154 | { 155 | if(stack_.empty() || (!stack_.top()->IsUint64())) 156 | throw_serialization_error("json", "expect uint64"); 157 | v = stack_.top()->GetInt64(); 158 | } 159 | 160 | template 161 | std::enable_if_t::value> load(T & v) const 162 | { 163 | if(stack_.empty() || (!stack_.top()->IsUint64())) 164 | throw_serialization_error("json", "expect uint64"); 165 | v = stack_.top()->GetUint64(); 166 | } 167 | 168 | void load(double & v) const 169 | { 170 | if(stack_.empty() || (!stack_.top()->IsNumber())) 171 | throw_serialization_error("json", "expect number"); 172 | v = stack_.top()->GetDouble(); 173 | } 174 | 175 | void load(std::string & v) const 176 | { 177 | if(stack_.empty() || (!stack_.top()->IsString())) 178 | throw_serialization_error("json", "expect string"); 179 | v = stack_.top()->GetString(); 180 | } 181 | 182 | void unserialize_start() const 183 | { 184 | serialization_trace trace(__func__, "json"); 185 | stack_ = std::stack {}; 186 | stack_.push(&doc_); 187 | } 188 | 189 | void unserialize_end() const 190 | { 191 | serialization_trace trace(__func__, "json"); 192 | } 193 | 194 | private: 195 | rapidjson::Document doc_; 196 | 197 | mutable std::stack stack_; 198 | }; 199 | 200 | } // namespace serialization 201 | -------------------------------------------------------------------------------- /include/serialization/detail/json_oarchive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace serialization 12 | { 13 | 14 | class json_oarchive 15 | { 16 | public: 17 | json_oarchive() 18 | { 19 | } 20 | 21 | const char * data() const 22 | { 23 | return buffer_.GetString(); 24 | } 25 | 26 | size_t size() const 27 | { 28 | return buffer_.GetSize(); 29 | } 30 | 31 | void save_key_start(const char * key) 32 | { 33 | serialization_trace trace(__func__, key); 34 | writer_.Key(key); 35 | } 36 | 37 | void save_key_end(const char * key) 38 | { 39 | serialization_trace trace(__func__, key); 40 | } 41 | 42 | void save_object_start() 43 | { 44 | serialization_trace trace(__func__, "json"); 45 | writer_.StartObject(); 46 | } 47 | 48 | void save_object_end() 49 | { 50 | serialization_trace trace(__func__, "json"); 51 | writer_.EndObject(); 52 | } 53 | 54 | void save_sequence_start(std::size_t size) 55 | { 56 | serialization_trace trace(__func__, "json"); 57 | writer_.StartArray(); 58 | } 59 | 60 | void save_sequence_end() 61 | { 62 | serialization_trace trace(__func__, "json"); 63 | writer_.EndArray(); 64 | } 65 | 66 | void save_sequence_item_start() 67 | { 68 | } 69 | 70 | void save_sequence_item_end() 71 | { 72 | } 73 | 74 | void save(bool v) 75 | { 76 | writer_.Bool(v); 77 | } 78 | 79 | void save(int v) 80 | { 81 | writer_.Int(v); 82 | } 83 | 84 | void save(uint v) 85 | { 86 | writer_.Uint(v); 87 | } 88 | 89 | void save(int64_t v) 90 | { 91 | writer_.Int64(v); 92 | } 93 | 94 | void save(uint64_t v) 95 | { 96 | writer_.Uint64(v); 97 | } 98 | 99 | void save(double v) 100 | { 101 | writer_.Double(v); 102 | } 103 | 104 | void save(const std::string & v) 105 | { 106 | writer_.String(v.c_str(), v.length()); 107 | } 108 | 109 | void serialize_start() 110 | { 111 | serialization_trace trace(__func__, "json"); 112 | buffer_.Clear(); 113 | writer_.Reset(buffer_); 114 | } 115 | 116 | void serialize_end() 117 | { 118 | serialization_trace trace(__func__, "json"); 119 | } 120 | 121 | private: 122 | rapidjson::StringBuffer buffer_; 123 | 124 | rapidjson::Writer writer_; 125 | }; 126 | 127 | } // namespace serialization 128 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/cursorstreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_ 16 | #define RAPIDJSON_CURSORSTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | 20 | #if defined(__GNUC__) 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | 25 | #if defined(_MSC_VER) && _MSC_VER <= 1800 26 | RAPIDJSON_DIAG_PUSH 27 | RAPIDJSON_DIAG_OFF(4702) // unreachable code 28 | RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated 29 | #endif 30 | 31 | RAPIDJSON_NAMESPACE_BEGIN 32 | 33 | 34 | //! Cursor stream wrapper for counting line and column number if error exists. 35 | /*! 36 | \tparam InputStream Any stream that implements Stream Concept 37 | */ 38 | template > 39 | class CursorStreamWrapper : public GenericStreamWrapper { 40 | public: 41 | typedef typename Encoding::Ch Ch; 42 | 43 | CursorStreamWrapper(InputStream& is): 44 | GenericStreamWrapper(is), line_(1), col_(0) {} 45 | 46 | // counting line and column number 47 | Ch Take() { 48 | Ch ch = this->is_.Take(); 49 | if(ch == '\n') { 50 | line_ ++; 51 | col_ = 0; 52 | } else { 53 | col_ ++; 54 | } 55 | return ch; 56 | } 57 | 58 | //! Get the error line number, if error exists. 59 | size_t GetLine() const { return line_; } 60 | //! Get the error column number, if error exists. 61 | size_t GetColumn() const { return col_; } 62 | 63 | private: 64 | size_t line_; //!< Current Line 65 | size_t col_; //!< Current Column 66 | }; 67 | 68 | #if defined(_MSC_VER) && _MSC_VER <= 1800 69 | RAPIDJSON_DIAG_POP 70 | #endif 71 | 72 | #if defined(__GNUC__) 73 | RAPIDJSON_DIAG_POP 74 | #endif 75 | 76 | RAPIDJSON_NAMESPACE_END 77 | 78 | #endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_ 79 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/error/en.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_EN_H_ 16 | #define RAPIDJSON_ERROR_EN_H_ 17 | 18 | #include "error.h" 19 | 20 | #ifdef __clang__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(switch-enum) 23 | RAPIDJSON_DIAG_OFF(covered-switch-default) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Maps error code of parsing into error message. 29 | /*! 30 | \ingroup RAPIDJSON_ERRORS 31 | \param parseErrorCode Error code obtained in parsing. 32 | \return the error message. 33 | \note User can make a copy of this function for localization. 34 | Using switch-case is safer for future modification of error codes. 35 | */ 36 | inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { 37 | switch (parseErrorCode) { 38 | case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); 39 | 40 | case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); 41 | case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); 42 | 43 | case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); 44 | 45 | case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); 46 | case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); 47 | case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); 48 | 49 | case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); 50 | 51 | case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); 52 | case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); 53 | case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); 54 | case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); 55 | case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); 56 | 57 | case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); 58 | case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); 59 | case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); 60 | 61 | case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); 62 | case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); 63 | 64 | default: return RAPIDJSON_ERROR_STRING("Unknown error."); 65 | } 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #ifdef __clang__ 71 | RAPIDJSON_DIAG_POP 72 | #endif 73 | 74 | #endif // RAPIDJSON_ERROR_EN_H_ 75 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/error/error.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_ERROR_H_ 16 | #define RAPIDJSON_ERROR_ERROR_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #ifdef __clang__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(padded) 23 | #endif 24 | 25 | /*! \file error.h */ 26 | 27 | /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ 28 | 29 | /////////////////////////////////////////////////////////////////////////////// 30 | // RAPIDJSON_ERROR_CHARTYPE 31 | 32 | //! Character type of error messages. 33 | /*! \ingroup RAPIDJSON_ERRORS 34 | The default character type is \c char. 35 | On Windows, user can define this macro as \c TCHAR for supporting both 36 | unicode/non-unicode settings. 37 | */ 38 | #ifndef RAPIDJSON_ERROR_CHARTYPE 39 | #define RAPIDJSON_ERROR_CHARTYPE char 40 | #endif 41 | 42 | /////////////////////////////////////////////////////////////////////////////// 43 | // RAPIDJSON_ERROR_STRING 44 | 45 | //! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. 46 | /*! \ingroup RAPIDJSON_ERRORS 47 | By default this conversion macro does nothing. 48 | On Windows, user can define this macro as \c _T(x) for supporting both 49 | unicode/non-unicode settings. 50 | */ 51 | #ifndef RAPIDJSON_ERROR_STRING 52 | #define RAPIDJSON_ERROR_STRING(x) x 53 | #endif 54 | 55 | RAPIDJSON_NAMESPACE_BEGIN 56 | 57 | /////////////////////////////////////////////////////////////////////////////// 58 | // ParseErrorCode 59 | 60 | //! Error code of parsing. 61 | /*! \ingroup RAPIDJSON_ERRORS 62 | \see GenericReader::Parse, GenericReader::GetParseErrorCode 63 | */ 64 | enum ParseErrorCode { 65 | kParseErrorNone = 0, //!< No error. 66 | 67 | kParseErrorDocumentEmpty, //!< The document is empty. 68 | kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. 69 | 70 | kParseErrorValueInvalid, //!< Invalid value. 71 | 72 | kParseErrorObjectMissName, //!< Missing a name for object member. 73 | kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. 74 | kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. 75 | 76 | kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. 77 | 78 | kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. 79 | kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. 80 | kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. 81 | kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. 82 | kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. 83 | 84 | kParseErrorNumberTooBig, //!< Number too big to be stored in double. 85 | kParseErrorNumberMissFraction, //!< Miss fraction part in number. 86 | kParseErrorNumberMissExponent, //!< Miss exponent in number. 87 | 88 | kParseErrorTermination, //!< Parsing was terminated. 89 | kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. 90 | }; 91 | 92 | //! Result of parsing (wraps ParseErrorCode) 93 | /*! 94 | \ingroup RAPIDJSON_ERRORS 95 | \code 96 | Document doc; 97 | ParseResult ok = doc.Parse("[42]"); 98 | if (!ok) { 99 | fprintf(stderr, "JSON parse error: %s (%u)", 100 | GetParseError_En(ok.Code()), ok.Offset()); 101 | exit(EXIT_FAILURE); 102 | } 103 | \endcode 104 | \see GenericReader::Parse, GenericDocument::Parse 105 | */ 106 | struct ParseResult { 107 | //!! Unspecified boolean type 108 | typedef bool (ParseResult::*BooleanType)() const; 109 | public: 110 | //! Default constructor, no error. 111 | ParseResult() : code_(kParseErrorNone), offset_(0) {} 112 | //! Constructor to set an error. 113 | ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} 114 | 115 | //! Get the error code. 116 | ParseErrorCode Code() const { return code_; } 117 | //! Get the error offset, if \ref IsError(), 0 otherwise. 118 | size_t Offset() const { return offset_; } 119 | 120 | //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). 121 | operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } 122 | //! Whether the result is an error. 123 | bool IsError() const { return code_ != kParseErrorNone; } 124 | 125 | bool operator==(const ParseResult& that) const { return code_ == that.code_; } 126 | bool operator==(ParseErrorCode code) const { return code_ == code; } 127 | friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } 128 | 129 | bool operator!=(const ParseResult& that) const { return !(*this == that); } 130 | bool operator!=(ParseErrorCode code) const { return !(*this == code); } 131 | friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; } 132 | 133 | //! Reset error code. 134 | void Clear() { Set(kParseErrorNone); } 135 | //! Update error code and offset. 136 | void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } 137 | 138 | private: 139 | ParseErrorCode code_; 140 | size_t offset_; 141 | }; 142 | 143 | //! Function pointer type of GetParseError(). 144 | /*! \ingroup RAPIDJSON_ERRORS 145 | 146 | This is the prototype for \c GetParseError_X(), where \c X is a locale. 147 | User can dynamically change locale in runtime, e.g.: 148 | \code 149 | GetParseErrorFunc GetParseError = GetParseError_En; // or whatever 150 | const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); 151 | \endcode 152 | */ 153 | typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); 154 | 155 | RAPIDJSON_NAMESPACE_END 156 | 157 | #ifdef __clang__ 158 | RAPIDJSON_DIAG_POP 159 | #endif 160 | 161 | #endif // RAPIDJSON_ERROR_ERROR_H_ 162 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/filereadstream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEREADSTREAM_H_ 16 | #define RAPIDJSON_FILEREADSTREAM_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(padded) 24 | RAPIDJSON_DIAG_OFF(unreachable-code) 25 | RAPIDJSON_DIAG_OFF(missing-noreturn) 26 | #endif 27 | 28 | RAPIDJSON_NAMESPACE_BEGIN 29 | 30 | //! File byte stream for input using fread(). 31 | /*! 32 | \note implements Stream concept 33 | */ 34 | class FileReadStream { 35 | public: 36 | typedef char Ch; //!< Character type (byte). 37 | 38 | //! Constructor. 39 | /*! 40 | \param fp File pointer opened for read. 41 | \param buffer user-supplied buffer. 42 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 43 | */ 44 | FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 45 | RAPIDJSON_ASSERT(fp_ != 0); 46 | RAPIDJSON_ASSERT(bufferSize >= 4); 47 | Read(); 48 | } 49 | 50 | Ch Peek() const { return *current_; } 51 | Ch Take() { Ch c = *current_; Read(); return c; } 52 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 53 | 54 | // Not implemented 55 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 56 | void Flush() { RAPIDJSON_ASSERT(false); } 57 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 58 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 59 | 60 | // For encoding detection only. 61 | const Ch* Peek4() const { 62 | return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; 63 | } 64 | 65 | private: 66 | void Read() { 67 | if (current_ < bufferLast_) 68 | ++current_; 69 | else if (!eof_) { 70 | count_ += readCount_; 71 | readCount_ = std::fread(buffer_, 1, bufferSize_, fp_); 72 | bufferLast_ = buffer_ + readCount_ - 1; 73 | current_ = buffer_; 74 | 75 | if (readCount_ < bufferSize_) { 76 | buffer_[readCount_] = '\0'; 77 | ++bufferLast_; 78 | eof_ = true; 79 | } 80 | } 81 | } 82 | 83 | std::FILE* fp_; 84 | Ch *buffer_; 85 | size_t bufferSize_; 86 | Ch *bufferLast_; 87 | Ch *current_; 88 | size_t readCount_; 89 | size_t count_; //!< Number of characters read 90 | bool eof_; 91 | }; 92 | 93 | RAPIDJSON_NAMESPACE_END 94 | 95 | #ifdef __clang__ 96 | RAPIDJSON_DIAG_POP 97 | #endif 98 | 99 | #endif // RAPIDJSON_FILESTREAM_H_ 100 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/filewritestream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_ 16 | #define RAPIDJSON_FILEWRITESTREAM_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(unreachable-code) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Wrapper of C file stream for output using fwrite(). 29 | /*! 30 | \note implements Stream concept 31 | */ 32 | class FileWriteStream { 33 | public: 34 | typedef char Ch; //!< Character type. Only support char. 35 | 36 | FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 37 | RAPIDJSON_ASSERT(fp_ != 0); 38 | } 39 | 40 | void Put(char c) { 41 | if (current_ >= bufferEnd_) 42 | Flush(); 43 | 44 | *current_++ = c; 45 | } 46 | 47 | void PutN(char c, size_t n) { 48 | size_t avail = static_cast(bufferEnd_ - current_); 49 | while (n > avail) { 50 | std::memset(current_, c, avail); 51 | current_ += avail; 52 | Flush(); 53 | n -= avail; 54 | avail = static_cast(bufferEnd_ - current_); 55 | } 56 | 57 | if (n > 0) { 58 | std::memset(current_, c, n); 59 | current_ += n; 60 | } 61 | } 62 | 63 | void Flush() { 64 | if (current_ != buffer_) { 65 | size_t result = std::fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); 66 | if (result < static_cast(current_ - buffer_)) { 67 | // failure deliberately ignored at this time 68 | // added to avoid warn_unused_result build errors 69 | } 70 | current_ = buffer_; 71 | } 72 | } 73 | 74 | // Not implemented 75 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 76 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 77 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 78 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 79 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 80 | 81 | private: 82 | // Prohibit copy constructor & assignment operator. 83 | FileWriteStream(const FileWriteStream&); 84 | FileWriteStream& operator=(const FileWriteStream&); 85 | 86 | std::FILE* fp_; 87 | char *buffer_; 88 | char *bufferEnd_; 89 | char *current_; 90 | }; 91 | 92 | //! Implement specialized version of PutN() with memset() for better performance. 93 | template<> 94 | inline void PutN(FileWriteStream& stream, char c, size_t n) { 95 | stream.PutN(c, n); 96 | } 97 | 98 | RAPIDJSON_NAMESPACE_END 99 | 100 | #ifdef __clang__ 101 | RAPIDJSON_DIAG_POP 102 | #endif 103 | 104 | #endif // RAPIDJSON_FILESTREAM_H_ 105 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/fwd.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FWD_H_ 16 | #define RAPIDJSON_FWD_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | // encodings.h 23 | 24 | template struct UTF8; 25 | template struct UTF16; 26 | template struct UTF16BE; 27 | template struct UTF16LE; 28 | template struct UTF32; 29 | template struct UTF32BE; 30 | template struct UTF32LE; 31 | template struct ASCII; 32 | template struct AutoUTF; 33 | 34 | template 35 | struct Transcoder; 36 | 37 | // allocators.h 38 | 39 | class CrtAllocator; 40 | 41 | template 42 | class MemoryPoolAllocator; 43 | 44 | // stream.h 45 | 46 | template 47 | struct GenericStringStream; 48 | 49 | typedef GenericStringStream > StringStream; 50 | 51 | template 52 | struct GenericInsituStringStream; 53 | 54 | typedef GenericInsituStringStream > InsituStringStream; 55 | 56 | // stringbuffer.h 57 | 58 | template 59 | class GenericStringBuffer; 60 | 61 | typedef GenericStringBuffer, CrtAllocator> StringBuffer; 62 | 63 | // filereadstream.h 64 | 65 | class FileReadStream; 66 | 67 | // filewritestream.h 68 | 69 | class FileWriteStream; 70 | 71 | // memorybuffer.h 72 | 73 | template 74 | struct GenericMemoryBuffer; 75 | 76 | typedef GenericMemoryBuffer MemoryBuffer; 77 | 78 | // memorystream.h 79 | 80 | struct MemoryStream; 81 | 82 | // reader.h 83 | 84 | template 85 | struct BaseReaderHandler; 86 | 87 | template 88 | class GenericReader; 89 | 90 | typedef GenericReader, UTF8, CrtAllocator> Reader; 91 | 92 | // writer.h 93 | 94 | template 95 | class Writer; 96 | 97 | // prettywriter.h 98 | 99 | template 100 | class PrettyWriter; 101 | 102 | // document.h 103 | 104 | template 105 | struct GenericMember; 106 | 107 | template 108 | class GenericMemberIterator; 109 | 110 | template 111 | struct GenericStringRef; 112 | 113 | template 114 | class GenericValue; 115 | 116 | typedef GenericValue, MemoryPoolAllocator > Value; 117 | 118 | template 119 | class GenericDocument; 120 | 121 | typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document; 122 | 123 | // pointer.h 124 | 125 | template 126 | class GenericPointer; 127 | 128 | typedef GenericPointer Pointer; 129 | 130 | // schema.h 131 | 132 | template 133 | class IGenericRemoteSchemaDocumentProvider; 134 | 135 | template 136 | class GenericSchemaDocument; 137 | 138 | typedef GenericSchemaDocument SchemaDocument; 139 | typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; 140 | 141 | template < 142 | typename SchemaDocumentType, 143 | typename OutputHandler, 144 | typename StateAllocator> 145 | class GenericSchemaValidator; 146 | 147 | typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; 148 | 149 | RAPIDJSON_NAMESPACE_END 150 | 151 | #endif // RAPIDJSON_RAPIDJSONFWD_H_ 152 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/biginteger.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_BIGINTEGER_H_ 16 | #define RAPIDJSON_BIGINTEGER_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #if defined(_MSC_VER) && !__INTEL_COMPILER && defined(_M_AMD64) 21 | #include // for _umul128 22 | #pragma intrinsic(_umul128) 23 | #endif 24 | 25 | RAPIDJSON_NAMESPACE_BEGIN 26 | namespace internal { 27 | 28 | class BigInteger { 29 | public: 30 | typedef uint64_t Type; 31 | 32 | BigInteger(const BigInteger& rhs) : count_(rhs.count_) { 33 | std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); 34 | } 35 | 36 | explicit BigInteger(uint64_t u) : count_(1) { 37 | digits_[0] = u; 38 | } 39 | 40 | BigInteger(const char* decimals, size_t length) : count_(1) { 41 | RAPIDJSON_ASSERT(length > 0); 42 | digits_[0] = 0; 43 | size_t i = 0; 44 | const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 45 | while (length >= kMaxDigitPerIteration) { 46 | AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); 47 | length -= kMaxDigitPerIteration; 48 | i += kMaxDigitPerIteration; 49 | } 50 | 51 | if (length > 0) 52 | AppendDecimal64(decimals + i, decimals + i + length); 53 | } 54 | 55 | BigInteger& operator=(const BigInteger &rhs) 56 | { 57 | if (this != &rhs) { 58 | count_ = rhs.count_; 59 | std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); 60 | } 61 | return *this; 62 | } 63 | 64 | BigInteger& operator=(uint64_t u) { 65 | digits_[0] = u; 66 | count_ = 1; 67 | return *this; 68 | } 69 | 70 | BigInteger& operator+=(uint64_t u) { 71 | Type backup = digits_[0]; 72 | digits_[0] += u; 73 | for (size_t i = 0; i < count_ - 1; i++) { 74 | if (digits_[i] >= backup) 75 | return *this; // no carry 76 | backup = digits_[i + 1]; 77 | digits_[i + 1] += 1; 78 | } 79 | 80 | // Last carry 81 | if (digits_[count_ - 1] < backup) 82 | PushBack(1); 83 | 84 | return *this; 85 | } 86 | 87 | BigInteger& operator*=(uint64_t u) { 88 | if (u == 0) return *this = 0; 89 | if (u == 1) return *this; 90 | if (*this == 1) return *this = u; 91 | 92 | uint64_t k = 0; 93 | for (size_t i = 0; i < count_; i++) { 94 | uint64_t hi; 95 | digits_[i] = MulAdd64(digits_[i], u, k, &hi); 96 | k = hi; 97 | } 98 | 99 | if (k > 0) 100 | PushBack(k); 101 | 102 | return *this; 103 | } 104 | 105 | BigInteger& operator*=(uint32_t u) { 106 | if (u == 0) return *this = 0; 107 | if (u == 1) return *this; 108 | if (*this == 1) return *this = u; 109 | 110 | uint64_t k = 0; 111 | for (size_t i = 0; i < count_; i++) { 112 | const uint64_t c = digits_[i] >> 32; 113 | const uint64_t d = digits_[i] & 0xFFFFFFFF; 114 | const uint64_t uc = u * c; 115 | const uint64_t ud = u * d; 116 | const uint64_t p0 = ud + k; 117 | const uint64_t p1 = uc + (p0 >> 32); 118 | digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); 119 | k = p1 >> 32; 120 | } 121 | 122 | if (k > 0) 123 | PushBack(k); 124 | 125 | return *this; 126 | } 127 | 128 | BigInteger& operator<<=(size_t shift) { 129 | if (IsZero() || shift == 0) return *this; 130 | 131 | size_t offset = shift / kTypeBit; 132 | size_t interShift = shift % kTypeBit; 133 | RAPIDJSON_ASSERT(count_ + offset <= kCapacity); 134 | 135 | if (interShift == 0) { 136 | std::memmove(digits_ + offset, digits_, count_ * sizeof(Type)); 137 | count_ += offset; 138 | } 139 | else { 140 | digits_[count_] = 0; 141 | for (size_t i = count_; i > 0; i--) 142 | digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); 143 | digits_[offset] = digits_[0] << interShift; 144 | count_ += offset; 145 | if (digits_[count_]) 146 | count_++; 147 | } 148 | 149 | std::memset(digits_, 0, offset * sizeof(Type)); 150 | 151 | return *this; 152 | } 153 | 154 | bool operator==(const BigInteger& rhs) const { 155 | return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; 156 | } 157 | 158 | bool operator==(const Type rhs) const { 159 | return count_ == 1 && digits_[0] == rhs; 160 | } 161 | 162 | BigInteger& MultiplyPow5(unsigned exp) { 163 | static const uint32_t kPow5[12] = { 164 | 5, 165 | 5 * 5, 166 | 5 * 5 * 5, 167 | 5 * 5 * 5 * 5, 168 | 5 * 5 * 5 * 5 * 5, 169 | 5 * 5 * 5 * 5 * 5 * 5, 170 | 5 * 5 * 5 * 5 * 5 * 5 * 5, 171 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, 172 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, 173 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, 174 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, 175 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 176 | }; 177 | if (exp == 0) return *this; 178 | for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 179 | for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 180 | if (exp > 0) *this *= kPow5[exp - 1]; 181 | return *this; 182 | } 183 | 184 | // Compute absolute difference of this and rhs. 185 | // Assume this != rhs 186 | bool Difference(const BigInteger& rhs, BigInteger* out) const { 187 | int cmp = Compare(rhs); 188 | RAPIDJSON_ASSERT(cmp != 0); 189 | const BigInteger *a, *b; // Makes a > b 190 | bool ret; 191 | if (cmp < 0) { a = &rhs; b = this; ret = true; } 192 | else { a = this; b = &rhs; ret = false; } 193 | 194 | Type borrow = 0; 195 | for (size_t i = 0; i < a->count_; i++) { 196 | Type d = a->digits_[i] - borrow; 197 | if (i < b->count_) 198 | d -= b->digits_[i]; 199 | borrow = (d > a->digits_[i]) ? 1 : 0; 200 | out->digits_[i] = d; 201 | if (d != 0) 202 | out->count_ = i + 1; 203 | } 204 | 205 | return ret; 206 | } 207 | 208 | int Compare(const BigInteger& rhs) const { 209 | if (count_ != rhs.count_) 210 | return count_ < rhs.count_ ? -1 : 1; 211 | 212 | for (size_t i = count_; i-- > 0;) 213 | if (digits_[i] != rhs.digits_[i]) 214 | return digits_[i] < rhs.digits_[i] ? -1 : 1; 215 | 216 | return 0; 217 | } 218 | 219 | size_t GetCount() const { return count_; } 220 | Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } 221 | bool IsZero() const { return count_ == 1 && digits_[0] == 0; } 222 | 223 | private: 224 | void AppendDecimal64(const char* begin, const char* end) { 225 | uint64_t u = ParseUint64(begin, end); 226 | if (IsZero()) 227 | *this = u; 228 | else { 229 | unsigned exp = static_cast(end - begin); 230 | (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u 231 | } 232 | } 233 | 234 | void PushBack(Type digit) { 235 | RAPIDJSON_ASSERT(count_ < kCapacity); 236 | digits_[count_++] = digit; 237 | } 238 | 239 | static uint64_t ParseUint64(const char* begin, const char* end) { 240 | uint64_t r = 0; 241 | for (const char* p = begin; p != end; ++p) { 242 | RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); 243 | r = r * 10u + static_cast(*p - '0'); 244 | } 245 | return r; 246 | } 247 | 248 | // Assume a * b + k < 2^128 249 | static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { 250 | #if defined(_MSC_VER) && defined(_M_AMD64) 251 | uint64_t low = _umul128(a, b, outHigh) + k; 252 | if (low < k) 253 | (*outHigh)++; 254 | return low; 255 | #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) 256 | __extension__ typedef unsigned __int128 uint128; 257 | uint128 p = static_cast(a) * static_cast(b); 258 | p += k; 259 | *outHigh = static_cast(p >> 64); 260 | return static_cast(p); 261 | #else 262 | const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; 263 | uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; 264 | x1 += (x0 >> 32); // can't give carry 265 | x1 += x2; 266 | if (x1 < x2) 267 | x3 += (static_cast(1) << 32); 268 | uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); 269 | uint64_t hi = x3 + (x1 >> 32); 270 | 271 | lo += k; 272 | if (lo < k) 273 | hi++; 274 | *outHigh = hi; 275 | return lo; 276 | #endif 277 | } 278 | 279 | static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 280 | static const size_t kCapacity = kBitCount / sizeof(Type); 281 | static const size_t kTypeBit = sizeof(Type) * 8; 282 | 283 | Type digits_[kCapacity]; 284 | size_t count_; 285 | }; 286 | 287 | } // namespace internal 288 | RAPIDJSON_NAMESPACE_END 289 | 290 | #endif // RAPIDJSON_BIGINTEGER_H_ 291 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/dtoa.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | // This is a C++ header-only implementation of Grisu2 algorithm from the publication: 16 | // Loitsch, Florian. "Printing floating-point numbers quickly and accurately with 17 | // integers." ACM Sigplan Notices 45.6 (2010): 233-243. 18 | 19 | #ifndef RAPIDJSON_DTOA_ 20 | #define RAPIDJSON_DTOA_ 21 | 22 | #include "itoa.h" // GetDigitsLut() 23 | #include "diyfp.h" 24 | #include "ieee754.h" 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | namespace internal { 28 | 29 | #ifdef __GNUC__ 30 | RAPIDJSON_DIAG_PUSH 31 | RAPIDJSON_DIAG_OFF(effc++) 32 | RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 33 | #endif 34 | 35 | inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { 36 | while (rest < wp_w && delta - rest >= ten_kappa && 37 | (rest + ten_kappa < wp_w || /// closer 38 | wp_w - rest > rest + ten_kappa - wp_w)) { 39 | buffer[len - 1]--; 40 | rest += ten_kappa; 41 | } 42 | } 43 | 44 | inline int CountDecimalDigit32(uint32_t n) { 45 | // Simple pure C++ implementation was faster than __builtin_clz version in this situation. 46 | if (n < 10) return 1; 47 | if (n < 100) return 2; 48 | if (n < 1000) return 3; 49 | if (n < 10000) return 4; 50 | if (n < 100000) return 5; 51 | if (n < 1000000) return 6; 52 | if (n < 10000000) return 7; 53 | if (n < 100000000) return 8; 54 | // Will not reach 10 digits in DigitGen() 55 | //if (n < 1000000000) return 9; 56 | //return 10; 57 | return 9; 58 | } 59 | 60 | inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { 61 | static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; 62 | const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); 63 | const DiyFp wp_w = Mp - W; 64 | uint32_t p1 = static_cast(Mp.f >> -one.e); 65 | uint64_t p2 = Mp.f & (one.f - 1); 66 | int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] 67 | *len = 0; 68 | 69 | while (kappa > 0) { 70 | uint32_t d = 0; 71 | switch (kappa) { 72 | case 9: d = p1 / 100000000; p1 %= 100000000; break; 73 | case 8: d = p1 / 10000000; p1 %= 10000000; break; 74 | case 7: d = p1 / 1000000; p1 %= 1000000; break; 75 | case 6: d = p1 / 100000; p1 %= 100000; break; 76 | case 5: d = p1 / 10000; p1 %= 10000; break; 77 | case 4: d = p1 / 1000; p1 %= 1000; break; 78 | case 3: d = p1 / 100; p1 %= 100; break; 79 | case 2: d = p1 / 10; p1 %= 10; break; 80 | case 1: d = p1; p1 = 0; break; 81 | default:; 82 | } 83 | if (d || *len) 84 | buffer[(*len)++] = static_cast('0' + static_cast(d)); 85 | kappa--; 86 | uint64_t tmp = (static_cast(p1) << -one.e) + p2; 87 | if (tmp <= delta) { 88 | *K += kappa; 89 | GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); 90 | return; 91 | } 92 | } 93 | 94 | // kappa = 0 95 | for (;;) { 96 | p2 *= 10; 97 | delta *= 10; 98 | char d = static_cast(p2 >> -one.e); 99 | if (d || *len) 100 | buffer[(*len)++] = static_cast('0' + d); 101 | p2 &= one.f - 1; 102 | kappa--; 103 | if (p2 < delta) { 104 | *K += kappa; 105 | int index = -kappa; 106 | GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); 107 | return; 108 | } 109 | } 110 | } 111 | 112 | inline void Grisu2(double value, char* buffer, int* length, int* K) { 113 | const DiyFp v(value); 114 | DiyFp w_m, w_p; 115 | v.NormalizedBoundaries(&w_m, &w_p); 116 | 117 | const DiyFp c_mk = GetCachedPower(w_p.e, K); 118 | const DiyFp W = v.Normalize() * c_mk; 119 | DiyFp Wp = w_p * c_mk; 120 | DiyFp Wm = w_m * c_mk; 121 | Wm.f++; 122 | Wp.f--; 123 | DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); 124 | } 125 | 126 | inline char* WriteExponent(int K, char* buffer) { 127 | if (K < 0) { 128 | *buffer++ = '-'; 129 | K = -K; 130 | } 131 | 132 | if (K >= 100) { 133 | *buffer++ = static_cast('0' + static_cast(K / 100)); 134 | K %= 100; 135 | const char* d = GetDigitsLut() + K * 2; 136 | *buffer++ = d[0]; 137 | *buffer++ = d[1]; 138 | } 139 | else if (K >= 10) { 140 | const char* d = GetDigitsLut() + K * 2; 141 | *buffer++ = d[0]; 142 | *buffer++ = d[1]; 143 | } 144 | else 145 | *buffer++ = static_cast('0' + static_cast(K)); 146 | 147 | return buffer; 148 | } 149 | 150 | inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { 151 | const int kk = length + k; // 10^(kk-1) <= v < 10^kk 152 | 153 | if (0 <= k && kk <= 21) { 154 | // 1234e7 -> 12340000000 155 | for (int i = length; i < kk; i++) 156 | buffer[i] = '0'; 157 | buffer[kk] = '.'; 158 | buffer[kk + 1] = '0'; 159 | return &buffer[kk + 2]; 160 | } 161 | else if (0 < kk && kk <= 21) { 162 | // 1234e-2 -> 12.34 163 | std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); 164 | buffer[kk] = '.'; 165 | if (0 > k + maxDecimalPlaces) { 166 | // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 167 | // Remove extra trailing zeros (at least one) after truncation. 168 | for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) 169 | if (buffer[i] != '0') 170 | return &buffer[i + 1]; 171 | return &buffer[kk + 2]; // Reserve one zero 172 | } 173 | else 174 | return &buffer[length + 1]; 175 | } 176 | else if (-6 < kk && kk <= 0) { 177 | // 1234e-6 -> 0.001234 178 | const int offset = 2 - kk; 179 | std::memmove(&buffer[offset], &buffer[0], static_cast(length)); 180 | buffer[0] = '0'; 181 | buffer[1] = '.'; 182 | for (int i = 2; i < offset; i++) 183 | buffer[i] = '0'; 184 | if (length - kk > maxDecimalPlaces) { 185 | // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 186 | // Remove extra trailing zeros (at least one) after truncation. 187 | for (int i = maxDecimalPlaces + 1; i > 2; i--) 188 | if (buffer[i] != '0') 189 | return &buffer[i + 1]; 190 | return &buffer[3]; // Reserve one zero 191 | } 192 | else 193 | return &buffer[length + offset]; 194 | } 195 | else if (kk < -maxDecimalPlaces) { 196 | // Truncate to zero 197 | buffer[0] = '0'; 198 | buffer[1] = '.'; 199 | buffer[2] = '0'; 200 | return &buffer[3]; 201 | } 202 | else if (length == 1) { 203 | // 1e30 204 | buffer[1] = 'e'; 205 | return WriteExponent(kk - 1, &buffer[2]); 206 | } 207 | else { 208 | // 1234e30 -> 1.234e33 209 | std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); 210 | buffer[1] = '.'; 211 | buffer[length + 1] = 'e'; 212 | return WriteExponent(kk - 1, &buffer[0 + length + 2]); 213 | } 214 | } 215 | 216 | inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { 217 | RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); 218 | Double d(value); 219 | if (d.IsZero()) { 220 | if (d.Sign()) 221 | *buffer++ = '-'; // -0.0, Issue #289 222 | buffer[0] = '0'; 223 | buffer[1] = '.'; 224 | buffer[2] = '0'; 225 | return &buffer[3]; 226 | } 227 | else { 228 | if (value < 0) { 229 | *buffer++ = '-'; 230 | value = -value; 231 | } 232 | int length, K; 233 | Grisu2(value, buffer, &length, &K); 234 | return Prettify(buffer, length, K, maxDecimalPlaces); 235 | } 236 | } 237 | 238 | #ifdef __GNUC__ 239 | RAPIDJSON_DIAG_POP 240 | #endif 241 | 242 | } // namespace internal 243 | RAPIDJSON_NAMESPACE_END 244 | 245 | #endif // RAPIDJSON_DTOA_ 246 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/ieee754.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_IEEE754_ 16 | #define RAPIDJSON_IEEE754_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | class Double { 24 | public: 25 | Double() {} 26 | Double(double d) : d_(d) {} 27 | Double(uint64_t u) : u_(u) {} 28 | 29 | double Value() const { return d_; } 30 | uint64_t Uint64Value() const { return u_; } 31 | 32 | double NextPositiveDouble() const { 33 | RAPIDJSON_ASSERT(!Sign()); 34 | return Double(u_ + 1).Value(); 35 | } 36 | 37 | bool Sign() const { return (u_ & kSignMask) != 0; } 38 | uint64_t Significand() const { return u_ & kSignificandMask; } 39 | int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } 40 | 41 | bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } 42 | bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } 43 | bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } 44 | bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } 45 | bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } 46 | 47 | uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } 48 | int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } 49 | uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } 50 | 51 | static int EffectiveSignificandSize(int order) { 52 | if (order >= -1021) 53 | return 53; 54 | else if (order <= -1074) 55 | return 0; 56 | else 57 | return order + 1074; 58 | } 59 | 60 | private: 61 | static const int kSignificandSize = 52; 62 | static const int kExponentBias = 0x3FF; 63 | static const int kDenormalExponent = 1 - kExponentBias; 64 | static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); 65 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 66 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 67 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 68 | 69 | union { 70 | double d_; 71 | uint64_t u_; 72 | }; 73 | }; 74 | 75 | } // namespace internal 76 | RAPIDJSON_NAMESPACE_END 77 | 78 | #endif // RAPIDJSON_IEEE754_ 79 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/itoa.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ITOA_ 16 | #define RAPIDJSON_ITOA_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | inline const char* GetDigitsLut() { 24 | static const char cDigitsLut[200] = { 25 | '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', 26 | '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', 27 | '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', 28 | '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', 29 | '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', 30 | '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', 31 | '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', 32 | '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', 33 | '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', 34 | '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' 35 | }; 36 | return cDigitsLut; 37 | } 38 | 39 | inline char* u32toa(uint32_t value, char* buffer) { 40 | RAPIDJSON_ASSERT(buffer != 0); 41 | 42 | const char* cDigitsLut = GetDigitsLut(); 43 | 44 | if (value < 10000) { 45 | const uint32_t d1 = (value / 100) << 1; 46 | const uint32_t d2 = (value % 100) << 1; 47 | 48 | if (value >= 1000) 49 | *buffer++ = cDigitsLut[d1]; 50 | if (value >= 100) 51 | *buffer++ = cDigitsLut[d1 + 1]; 52 | if (value >= 10) 53 | *buffer++ = cDigitsLut[d2]; 54 | *buffer++ = cDigitsLut[d2 + 1]; 55 | } 56 | else if (value < 100000000) { 57 | // value = bbbbcccc 58 | const uint32_t b = value / 10000; 59 | const uint32_t c = value % 10000; 60 | 61 | const uint32_t d1 = (b / 100) << 1; 62 | const uint32_t d2 = (b % 100) << 1; 63 | 64 | const uint32_t d3 = (c / 100) << 1; 65 | const uint32_t d4 = (c % 100) << 1; 66 | 67 | if (value >= 10000000) 68 | *buffer++ = cDigitsLut[d1]; 69 | if (value >= 1000000) 70 | *buffer++ = cDigitsLut[d1 + 1]; 71 | if (value >= 100000) 72 | *buffer++ = cDigitsLut[d2]; 73 | *buffer++ = cDigitsLut[d2 + 1]; 74 | 75 | *buffer++ = cDigitsLut[d3]; 76 | *buffer++ = cDigitsLut[d3 + 1]; 77 | *buffer++ = cDigitsLut[d4]; 78 | *buffer++ = cDigitsLut[d4 + 1]; 79 | } 80 | else { 81 | // value = aabbbbcccc in decimal 82 | 83 | const uint32_t a = value / 100000000; // 1 to 42 84 | value %= 100000000; 85 | 86 | if (a >= 10) { 87 | const unsigned i = a << 1; 88 | *buffer++ = cDigitsLut[i]; 89 | *buffer++ = cDigitsLut[i + 1]; 90 | } 91 | else 92 | *buffer++ = static_cast('0' + static_cast(a)); 93 | 94 | const uint32_t b = value / 10000; // 0 to 9999 95 | const uint32_t c = value % 10000; // 0 to 9999 96 | 97 | const uint32_t d1 = (b / 100) << 1; 98 | const uint32_t d2 = (b % 100) << 1; 99 | 100 | const uint32_t d3 = (c / 100) << 1; 101 | const uint32_t d4 = (c % 100) << 1; 102 | 103 | *buffer++ = cDigitsLut[d1]; 104 | *buffer++ = cDigitsLut[d1 + 1]; 105 | *buffer++ = cDigitsLut[d2]; 106 | *buffer++ = cDigitsLut[d2 + 1]; 107 | *buffer++ = cDigitsLut[d3]; 108 | *buffer++ = cDigitsLut[d3 + 1]; 109 | *buffer++ = cDigitsLut[d4]; 110 | *buffer++ = cDigitsLut[d4 + 1]; 111 | } 112 | return buffer; 113 | } 114 | 115 | inline char* i32toa(int32_t value, char* buffer) { 116 | RAPIDJSON_ASSERT(buffer != 0); 117 | uint32_t u = static_cast(value); 118 | if (value < 0) { 119 | *buffer++ = '-'; 120 | u = ~u + 1; 121 | } 122 | 123 | return u32toa(u, buffer); 124 | } 125 | 126 | inline char* u64toa(uint64_t value, char* buffer) { 127 | RAPIDJSON_ASSERT(buffer != 0); 128 | const char* cDigitsLut = GetDigitsLut(); 129 | const uint64_t kTen8 = 100000000; 130 | const uint64_t kTen9 = kTen8 * 10; 131 | const uint64_t kTen10 = kTen8 * 100; 132 | const uint64_t kTen11 = kTen8 * 1000; 133 | const uint64_t kTen12 = kTen8 * 10000; 134 | const uint64_t kTen13 = kTen8 * 100000; 135 | const uint64_t kTen14 = kTen8 * 1000000; 136 | const uint64_t kTen15 = kTen8 * 10000000; 137 | const uint64_t kTen16 = kTen8 * kTen8; 138 | 139 | if (value < kTen8) { 140 | uint32_t v = static_cast(value); 141 | if (v < 10000) { 142 | const uint32_t d1 = (v / 100) << 1; 143 | const uint32_t d2 = (v % 100) << 1; 144 | 145 | if (v >= 1000) 146 | *buffer++ = cDigitsLut[d1]; 147 | if (v >= 100) 148 | *buffer++ = cDigitsLut[d1 + 1]; 149 | if (v >= 10) 150 | *buffer++ = cDigitsLut[d2]; 151 | *buffer++ = cDigitsLut[d2 + 1]; 152 | } 153 | else { 154 | // value = bbbbcccc 155 | const uint32_t b = v / 10000; 156 | const uint32_t c = v % 10000; 157 | 158 | const uint32_t d1 = (b / 100) << 1; 159 | const uint32_t d2 = (b % 100) << 1; 160 | 161 | const uint32_t d3 = (c / 100) << 1; 162 | const uint32_t d4 = (c % 100) << 1; 163 | 164 | if (value >= 10000000) 165 | *buffer++ = cDigitsLut[d1]; 166 | if (value >= 1000000) 167 | *buffer++ = cDigitsLut[d1 + 1]; 168 | if (value >= 100000) 169 | *buffer++ = cDigitsLut[d2]; 170 | *buffer++ = cDigitsLut[d2 + 1]; 171 | 172 | *buffer++ = cDigitsLut[d3]; 173 | *buffer++ = cDigitsLut[d3 + 1]; 174 | *buffer++ = cDigitsLut[d4]; 175 | *buffer++ = cDigitsLut[d4 + 1]; 176 | } 177 | } 178 | else if (value < kTen16) { 179 | const uint32_t v0 = static_cast(value / kTen8); 180 | const uint32_t v1 = static_cast(value % kTen8); 181 | 182 | const uint32_t b0 = v0 / 10000; 183 | const uint32_t c0 = v0 % 10000; 184 | 185 | const uint32_t d1 = (b0 / 100) << 1; 186 | const uint32_t d2 = (b0 % 100) << 1; 187 | 188 | const uint32_t d3 = (c0 / 100) << 1; 189 | const uint32_t d4 = (c0 % 100) << 1; 190 | 191 | const uint32_t b1 = v1 / 10000; 192 | const uint32_t c1 = v1 % 10000; 193 | 194 | const uint32_t d5 = (b1 / 100) << 1; 195 | const uint32_t d6 = (b1 % 100) << 1; 196 | 197 | const uint32_t d7 = (c1 / 100) << 1; 198 | const uint32_t d8 = (c1 % 100) << 1; 199 | 200 | if (value >= kTen15) 201 | *buffer++ = cDigitsLut[d1]; 202 | if (value >= kTen14) 203 | *buffer++ = cDigitsLut[d1 + 1]; 204 | if (value >= kTen13) 205 | *buffer++ = cDigitsLut[d2]; 206 | if (value >= kTen12) 207 | *buffer++ = cDigitsLut[d2 + 1]; 208 | if (value >= kTen11) 209 | *buffer++ = cDigitsLut[d3]; 210 | if (value >= kTen10) 211 | *buffer++ = cDigitsLut[d3 + 1]; 212 | if (value >= kTen9) 213 | *buffer++ = cDigitsLut[d4]; 214 | 215 | *buffer++ = cDigitsLut[d4 + 1]; 216 | *buffer++ = cDigitsLut[d5]; 217 | *buffer++ = cDigitsLut[d5 + 1]; 218 | *buffer++ = cDigitsLut[d6]; 219 | *buffer++ = cDigitsLut[d6 + 1]; 220 | *buffer++ = cDigitsLut[d7]; 221 | *buffer++ = cDigitsLut[d7 + 1]; 222 | *buffer++ = cDigitsLut[d8]; 223 | *buffer++ = cDigitsLut[d8 + 1]; 224 | } 225 | else { 226 | const uint32_t a = static_cast(value / kTen16); // 1 to 1844 227 | value %= kTen16; 228 | 229 | if (a < 10) 230 | *buffer++ = static_cast('0' + static_cast(a)); 231 | else if (a < 100) { 232 | const uint32_t i = a << 1; 233 | *buffer++ = cDigitsLut[i]; 234 | *buffer++ = cDigitsLut[i + 1]; 235 | } 236 | else if (a < 1000) { 237 | *buffer++ = static_cast('0' + static_cast(a / 100)); 238 | 239 | const uint32_t i = (a % 100) << 1; 240 | *buffer++ = cDigitsLut[i]; 241 | *buffer++ = cDigitsLut[i + 1]; 242 | } 243 | else { 244 | const uint32_t i = (a / 100) << 1; 245 | const uint32_t j = (a % 100) << 1; 246 | *buffer++ = cDigitsLut[i]; 247 | *buffer++ = cDigitsLut[i + 1]; 248 | *buffer++ = cDigitsLut[j]; 249 | *buffer++ = cDigitsLut[j + 1]; 250 | } 251 | 252 | const uint32_t v0 = static_cast(value / kTen8); 253 | const uint32_t v1 = static_cast(value % kTen8); 254 | 255 | const uint32_t b0 = v0 / 10000; 256 | const uint32_t c0 = v0 % 10000; 257 | 258 | const uint32_t d1 = (b0 / 100) << 1; 259 | const uint32_t d2 = (b0 % 100) << 1; 260 | 261 | const uint32_t d3 = (c0 / 100) << 1; 262 | const uint32_t d4 = (c0 % 100) << 1; 263 | 264 | const uint32_t b1 = v1 / 10000; 265 | const uint32_t c1 = v1 % 10000; 266 | 267 | const uint32_t d5 = (b1 / 100) << 1; 268 | const uint32_t d6 = (b1 % 100) << 1; 269 | 270 | const uint32_t d7 = (c1 / 100) << 1; 271 | const uint32_t d8 = (c1 % 100) << 1; 272 | 273 | *buffer++ = cDigitsLut[d1]; 274 | *buffer++ = cDigitsLut[d1 + 1]; 275 | *buffer++ = cDigitsLut[d2]; 276 | *buffer++ = cDigitsLut[d2 + 1]; 277 | *buffer++ = cDigitsLut[d3]; 278 | *buffer++ = cDigitsLut[d3 + 1]; 279 | *buffer++ = cDigitsLut[d4]; 280 | *buffer++ = cDigitsLut[d4 + 1]; 281 | *buffer++ = cDigitsLut[d5]; 282 | *buffer++ = cDigitsLut[d5 + 1]; 283 | *buffer++ = cDigitsLut[d6]; 284 | *buffer++ = cDigitsLut[d6 + 1]; 285 | *buffer++ = cDigitsLut[d7]; 286 | *buffer++ = cDigitsLut[d7 + 1]; 287 | *buffer++ = cDigitsLut[d8]; 288 | *buffer++ = cDigitsLut[d8 + 1]; 289 | } 290 | 291 | return buffer; 292 | } 293 | 294 | inline char* i64toa(int64_t value, char* buffer) { 295 | RAPIDJSON_ASSERT(buffer != 0); 296 | uint64_t u = static_cast(value); 297 | if (value < 0) { 298 | *buffer++ = '-'; 299 | u = ~u + 1; 300 | } 301 | 302 | return u64toa(u, buffer); 303 | } 304 | 305 | } // namespace internal 306 | RAPIDJSON_NAMESPACE_END 307 | 308 | #endif // RAPIDJSON_ITOA_ 309 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/meta.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_META_H_ 16 | #define RAPIDJSON_INTERNAL_META_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #ifdef __GNUC__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | 25 | #if defined(_MSC_VER) && !defined(__clang__) 26 | RAPIDJSON_DIAG_PUSH 27 | RAPIDJSON_DIAG_OFF(6334) 28 | #endif 29 | 30 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS 31 | #include 32 | #endif 33 | 34 | //@cond RAPIDJSON_INTERNAL 35 | RAPIDJSON_NAMESPACE_BEGIN 36 | namespace internal { 37 | 38 | // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching 39 | template struct Void { typedef void Type; }; 40 | 41 | /////////////////////////////////////////////////////////////////////////////// 42 | // BoolType, TrueType, FalseType 43 | // 44 | template struct BoolType { 45 | static const bool Value = Cond; 46 | typedef BoolType Type; 47 | }; 48 | typedef BoolType TrueType; 49 | typedef BoolType FalseType; 50 | 51 | 52 | /////////////////////////////////////////////////////////////////////////////// 53 | // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr 54 | // 55 | 56 | template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; 57 | template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; 58 | template struct SelectIfCond : SelectIfImpl::template Apply {}; 59 | template struct SelectIf : SelectIfCond {}; 60 | 61 | template struct AndExprCond : FalseType {}; 62 | template <> struct AndExprCond : TrueType {}; 63 | template struct OrExprCond : TrueType {}; 64 | template <> struct OrExprCond : FalseType {}; 65 | 66 | template struct BoolExpr : SelectIf::Type {}; 67 | template struct NotExpr : SelectIf::Type {}; 68 | template struct AndExpr : AndExprCond::Type {}; 69 | template struct OrExpr : OrExprCond::Type {}; 70 | 71 | 72 | /////////////////////////////////////////////////////////////////////////////// 73 | // AddConst, MaybeAddConst, RemoveConst 74 | template struct AddConst { typedef const T Type; }; 75 | template struct MaybeAddConst : SelectIfCond {}; 76 | template struct RemoveConst { typedef T Type; }; 77 | template struct RemoveConst { typedef T Type; }; 78 | 79 | 80 | /////////////////////////////////////////////////////////////////////////////// 81 | // IsSame, IsConst, IsMoreConst, IsPointer 82 | // 83 | template struct IsSame : FalseType {}; 84 | template struct IsSame : TrueType {}; 85 | 86 | template struct IsConst : FalseType {}; 87 | template struct IsConst : TrueType {}; 88 | 89 | template 90 | struct IsMoreConst 91 | : AndExpr::Type, typename RemoveConst::Type>, 92 | BoolType::Value >= IsConst::Value> >::Type {}; 93 | 94 | template struct IsPointer : FalseType {}; 95 | template struct IsPointer : TrueType {}; 96 | 97 | /////////////////////////////////////////////////////////////////////////////// 98 | // IsBaseOf 99 | // 100 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS 101 | 102 | template struct IsBaseOf 103 | : BoolType< ::std::is_base_of::value> {}; 104 | 105 | #else // simplified version adopted from Boost 106 | 107 | template struct IsBaseOfImpl { 108 | RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); 109 | RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); 110 | 111 | typedef char (&Yes)[1]; 112 | typedef char (&No) [2]; 113 | 114 | template 115 | static Yes Check(const D*, T); 116 | static No Check(const B*, int); 117 | 118 | struct Host { 119 | operator const B*() const; 120 | operator const D*(); 121 | }; 122 | 123 | enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; 124 | }; 125 | 126 | template struct IsBaseOf 127 | : OrExpr, BoolExpr > >::Type {}; 128 | 129 | #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS 130 | 131 | 132 | ////////////////////////////////////////////////////////////////////////// 133 | // EnableIf / DisableIf 134 | // 135 | template struct EnableIfCond { typedef T Type; }; 136 | template struct EnableIfCond { /* empty */ }; 137 | 138 | template struct DisableIfCond { typedef T Type; }; 139 | template struct DisableIfCond { /* empty */ }; 140 | 141 | template 142 | struct EnableIf : EnableIfCond {}; 143 | 144 | template 145 | struct DisableIf : DisableIfCond {}; 146 | 147 | // SFINAE helpers 148 | struct SfinaeTag {}; 149 | template struct RemoveSfinaeTag; 150 | template struct RemoveSfinaeTag { typedef T Type; }; 151 | 152 | #define RAPIDJSON_REMOVEFPTR_(type) \ 153 | typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ 154 | < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type 155 | 156 | #define RAPIDJSON_ENABLEIF(cond) \ 157 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 158 | ::Type * = NULL 159 | 160 | #define RAPIDJSON_DISABLEIF(cond) \ 161 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 162 | ::Type * = NULL 163 | 164 | #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ 165 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 166 | ::Type 168 | 169 | #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ 170 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 171 | ::Type 173 | 174 | } // namespace internal 175 | RAPIDJSON_NAMESPACE_END 176 | //@endcond 177 | 178 | #if defined(_MSC_VER) && !defined(__clang__) 179 | RAPIDJSON_DIAG_POP 180 | #endif 181 | 182 | #ifdef __GNUC__ 183 | RAPIDJSON_DIAG_POP 184 | #endif 185 | 186 | #endif // RAPIDJSON_INTERNAL_META_H_ 187 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/pow10.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_POW10_ 16 | #define RAPIDJSON_POW10_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Computes integer powers of 10 in double (10.0^n). 24 | /*! This function uses lookup table for fast and accurate results. 25 | \param n non-negative exponent. Must <= 308. 26 | \return 10.0^n 27 | */ 28 | inline double Pow10(int n) { 29 | static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes 30 | 1e+0, 31 | 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 32 | 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 33 | 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 34 | 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 35 | 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 36 | 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, 37 | 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, 38 | 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, 39 | 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, 40 | 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, 41 | 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, 42 | 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, 43 | 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, 44 | 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, 45 | 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, 46 | 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 47 | }; 48 | RAPIDJSON_ASSERT(n >= 0 && n <= 308); 49 | return e[n]; 50 | } 51 | 52 | } // namespace internal 53 | RAPIDJSON_NAMESPACE_END 54 | 55 | #endif // RAPIDJSON_POW10_ 56 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/stack.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STACK_H_ 16 | #define RAPIDJSON_INTERNAL_STACK_H_ 17 | 18 | #include "../allocators.h" 19 | #include "swap.h" 20 | #include 21 | 22 | #if defined(__clang__) 23 | RAPIDJSON_DIAG_PUSH 24 | RAPIDJSON_DIAG_OFF(c++98-compat) 25 | #endif 26 | 27 | RAPIDJSON_NAMESPACE_BEGIN 28 | namespace internal { 29 | 30 | /////////////////////////////////////////////////////////////////////////////// 31 | // Stack 32 | 33 | //! A type-unsafe stack for storing different types of data. 34 | /*! \tparam Allocator Allocator for allocating stack memory. 35 | */ 36 | template 37 | class Stack { 38 | public: 39 | // Optimization note: Do not allocate memory for stack_ in constructor. 40 | // Do it lazily when first Push() -> Expand() -> Resize(). 41 | Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { 42 | } 43 | 44 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 45 | Stack(Stack&& rhs) 46 | : allocator_(rhs.allocator_), 47 | ownAllocator_(rhs.ownAllocator_), 48 | stack_(rhs.stack_), 49 | stackTop_(rhs.stackTop_), 50 | stackEnd_(rhs.stackEnd_), 51 | initialCapacity_(rhs.initialCapacity_) 52 | { 53 | rhs.allocator_ = 0; 54 | rhs.ownAllocator_ = 0; 55 | rhs.stack_ = 0; 56 | rhs.stackTop_ = 0; 57 | rhs.stackEnd_ = 0; 58 | rhs.initialCapacity_ = 0; 59 | } 60 | #endif 61 | 62 | ~Stack() { 63 | Destroy(); 64 | } 65 | 66 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 67 | Stack& operator=(Stack&& rhs) { 68 | if (&rhs != this) 69 | { 70 | Destroy(); 71 | 72 | allocator_ = rhs.allocator_; 73 | ownAllocator_ = rhs.ownAllocator_; 74 | stack_ = rhs.stack_; 75 | stackTop_ = rhs.stackTop_; 76 | stackEnd_ = rhs.stackEnd_; 77 | initialCapacity_ = rhs.initialCapacity_; 78 | 79 | rhs.allocator_ = 0; 80 | rhs.ownAllocator_ = 0; 81 | rhs.stack_ = 0; 82 | rhs.stackTop_ = 0; 83 | rhs.stackEnd_ = 0; 84 | rhs.initialCapacity_ = 0; 85 | } 86 | return *this; 87 | } 88 | #endif 89 | 90 | void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { 91 | internal::Swap(allocator_, rhs.allocator_); 92 | internal::Swap(ownAllocator_, rhs.ownAllocator_); 93 | internal::Swap(stack_, rhs.stack_); 94 | internal::Swap(stackTop_, rhs.stackTop_); 95 | internal::Swap(stackEnd_, rhs.stackEnd_); 96 | internal::Swap(initialCapacity_, rhs.initialCapacity_); 97 | } 98 | 99 | void Clear() { stackTop_ = stack_; } 100 | 101 | void ShrinkToFit() { 102 | if (Empty()) { 103 | // If the stack is empty, completely deallocate the memory. 104 | Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) 105 | stack_ = 0; 106 | stackTop_ = 0; 107 | stackEnd_ = 0; 108 | } 109 | else 110 | Resize(GetSize()); 111 | } 112 | 113 | // Optimization note: try to minimize the size of this function for force inline. 114 | // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. 115 | template 116 | RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { 117 | // Expand the stack if needed 118 | if (RAPIDJSON_UNLIKELY(static_cast(sizeof(T) * count) > (stackEnd_ - stackTop_))) 119 | Expand(count); 120 | } 121 | 122 | template 123 | RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { 124 | Reserve(count); 125 | return PushUnsafe(count); 126 | } 127 | 128 | template 129 | RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { 130 | RAPIDJSON_ASSERT(stackTop_); 131 | RAPIDJSON_ASSERT(static_cast(sizeof(T) * count) <= (stackEnd_ - stackTop_)); 132 | T* ret = reinterpret_cast(stackTop_); 133 | stackTop_ += sizeof(T) * count; 134 | return ret; 135 | } 136 | 137 | template 138 | T* Pop(size_t count) { 139 | RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); 140 | stackTop_ -= count * sizeof(T); 141 | return reinterpret_cast(stackTop_); 142 | } 143 | 144 | template 145 | T* Top() { 146 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); 147 | return reinterpret_cast(stackTop_ - sizeof(T)); 148 | } 149 | 150 | template 151 | const T* Top() const { 152 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); 153 | return reinterpret_cast(stackTop_ - sizeof(T)); 154 | } 155 | 156 | template 157 | T* End() { return reinterpret_cast(stackTop_); } 158 | 159 | template 160 | const T* End() const { return reinterpret_cast(stackTop_); } 161 | 162 | template 163 | T* Bottom() { return reinterpret_cast(stack_); } 164 | 165 | template 166 | const T* Bottom() const { return reinterpret_cast(stack_); } 167 | 168 | bool HasAllocator() const { 169 | return allocator_ != 0; 170 | } 171 | 172 | Allocator& GetAllocator() { 173 | RAPIDJSON_ASSERT(allocator_); 174 | return *allocator_; 175 | } 176 | 177 | bool Empty() const { return stackTop_ == stack_; } 178 | size_t GetSize() const { return static_cast(stackTop_ - stack_); } 179 | size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } 180 | 181 | private: 182 | template 183 | void Expand(size_t count) { 184 | // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. 185 | size_t newCapacity; 186 | if (stack_ == 0) { 187 | if (!allocator_) 188 | ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); 189 | newCapacity = initialCapacity_; 190 | } else { 191 | newCapacity = GetCapacity(); 192 | newCapacity += (newCapacity + 1) / 2; 193 | } 194 | size_t newSize = GetSize() + sizeof(T) * count; 195 | if (newCapacity < newSize) 196 | newCapacity = newSize; 197 | 198 | Resize(newCapacity); 199 | } 200 | 201 | void Resize(size_t newCapacity) { 202 | const size_t size = GetSize(); // Backup the current size 203 | stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); 204 | stackTop_ = stack_ + size; 205 | stackEnd_ = stack_ + newCapacity; 206 | } 207 | 208 | void Destroy() { 209 | Allocator::Free(stack_); 210 | RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack 211 | } 212 | 213 | // Prohibit copy constructor & assignment operator. 214 | Stack(const Stack&); 215 | Stack& operator=(const Stack&); 216 | 217 | Allocator* allocator_; 218 | Allocator* ownAllocator_; 219 | char *stack_; 220 | char *stackTop_; 221 | char *stackEnd_; 222 | size_t initialCapacity_; 223 | }; 224 | 225 | } // namespace internal 226 | RAPIDJSON_NAMESPACE_END 227 | 228 | #if defined(__clang__) 229 | RAPIDJSON_DIAG_POP 230 | #endif 231 | 232 | #endif // RAPIDJSON_STACK_H_ 233 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/strfunc.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ 16 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ 17 | 18 | #include "../stream.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | namespace internal { 23 | 24 | //! Custom strlen() which works on different character types. 25 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 26 | \param s Null-terminated input string. 27 | \return Number of characters in the string. 28 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 29 | */ 30 | template 31 | inline SizeType StrLen(const Ch* s) { 32 | RAPIDJSON_ASSERT(s != 0); 33 | const Ch* p = s; 34 | while (*p) ++p; 35 | return SizeType(p - s); 36 | } 37 | 38 | template <> 39 | inline SizeType StrLen(const char* s) { 40 | return SizeType(std::strlen(s)); 41 | } 42 | 43 | template <> 44 | inline SizeType StrLen(const wchar_t* s) { 45 | return SizeType(std::wcslen(s)); 46 | } 47 | 48 | //! Returns number of code points in a encoded string. 49 | template 50 | bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { 51 | RAPIDJSON_ASSERT(s != 0); 52 | RAPIDJSON_ASSERT(outCount != 0); 53 | GenericStringStream is(s); 54 | const typename Encoding::Ch* end = s + length; 55 | SizeType count = 0; 56 | while (is.src_ < end) { 57 | unsigned codepoint; 58 | if (!Encoding::Decode(is, &codepoint)) 59 | return false; 60 | count++; 61 | } 62 | *outCount = count; 63 | return true; 64 | } 65 | 66 | } // namespace internal 67 | RAPIDJSON_NAMESPACE_END 68 | 69 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 70 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/strtod.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_STRTOD_ 16 | #define RAPIDJSON_STRTOD_ 17 | 18 | #include "ieee754.h" 19 | #include "biginteger.h" 20 | #include "diyfp.h" 21 | #include "pow10.h" 22 | #include 23 | #include 24 | 25 | RAPIDJSON_NAMESPACE_BEGIN 26 | namespace internal { 27 | 28 | inline double FastPath(double significand, int exp) { 29 | if (exp < -308) 30 | return 0.0; 31 | else if (exp >= 0) 32 | return significand * internal::Pow10(exp); 33 | else 34 | return significand / internal::Pow10(-exp); 35 | } 36 | 37 | inline double StrtodNormalPrecision(double d, int p) { 38 | if (p < -308) { 39 | // Prevent expSum < -308, making Pow10(p) = 0 40 | d = FastPath(d, -308); 41 | d = FastPath(d, p + 308); 42 | } 43 | else 44 | d = FastPath(d, p); 45 | return d; 46 | } 47 | 48 | template 49 | inline T Min3(T a, T b, T c) { 50 | T m = a; 51 | if (m > b) m = b; 52 | if (m > c) m = c; 53 | return m; 54 | } 55 | 56 | inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { 57 | const Double db(b); 58 | const uint64_t bInt = db.IntegerSignificand(); 59 | const int bExp = db.IntegerExponent(); 60 | const int hExp = bExp - 1; 61 | 62 | int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; 63 | 64 | // Adjust for decimal exponent 65 | if (dExp >= 0) { 66 | dS_Exp2 += dExp; 67 | dS_Exp5 += dExp; 68 | } 69 | else { 70 | bS_Exp2 -= dExp; 71 | bS_Exp5 -= dExp; 72 | hS_Exp2 -= dExp; 73 | hS_Exp5 -= dExp; 74 | } 75 | 76 | // Adjust for binary exponent 77 | if (bExp >= 0) 78 | bS_Exp2 += bExp; 79 | else { 80 | dS_Exp2 -= bExp; 81 | hS_Exp2 -= bExp; 82 | } 83 | 84 | // Adjust for half ulp exponent 85 | if (hExp >= 0) 86 | hS_Exp2 += hExp; 87 | else { 88 | dS_Exp2 -= hExp; 89 | bS_Exp2 -= hExp; 90 | } 91 | 92 | // Remove common power of two factor from all three scaled values 93 | int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); 94 | dS_Exp2 -= common_Exp2; 95 | bS_Exp2 -= common_Exp2; 96 | hS_Exp2 -= common_Exp2; 97 | 98 | BigInteger dS = d; 99 | dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); 100 | 101 | BigInteger bS(bInt); 102 | bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); 103 | 104 | BigInteger hS(1); 105 | hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); 106 | 107 | BigInteger delta(0); 108 | dS.Difference(bS, &delta); 109 | 110 | return delta.Compare(hS); 111 | } 112 | 113 | inline bool StrtodFast(double d, int p, double* result) { 114 | // Use fast path for string-to-double conversion if possible 115 | // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ 116 | if (p > 22 && p < 22 + 16) { 117 | // Fast Path Cases In Disguise 118 | d *= internal::Pow10(p - 22); 119 | p = 22; 120 | } 121 | 122 | if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 123 | *result = FastPath(d, p); 124 | return true; 125 | } 126 | else 127 | return false; 128 | } 129 | 130 | // Compute an approximation and see if it is within 1/2 ULP 131 | inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) { 132 | uint64_t significand = 0; 133 | int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 134 | for (; i < dLen; i++) { 135 | if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || 136 | (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) 137 | break; 138 | significand = significand * 10u + static_cast(decimals[i] - '0'); 139 | } 140 | 141 | if (i < dLen && decimals[i] >= '5') // Rounding 142 | significand++; 143 | 144 | int remaining = dLen - i; 145 | const int kUlpShift = 3; 146 | const int kUlp = 1 << kUlpShift; 147 | int64_t error = (remaining == 0) ? 0 : kUlp / 2; 148 | 149 | DiyFp v(significand, 0); 150 | v = v.Normalize(); 151 | error <<= -v.e; 152 | 153 | dExp += remaining; 154 | 155 | int actualExp; 156 | DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); 157 | if (actualExp != dExp) { 158 | static const DiyFp kPow10[] = { 159 | DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1 160 | DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2 161 | DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3 162 | DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4 163 | DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5 164 | DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6 165 | DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7 166 | }; 167 | int adjustment = dExp - actualExp; 168 | RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8); 169 | v = v * kPow10[adjustment - 1]; 170 | if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit 171 | error += kUlp / 2; 172 | } 173 | 174 | v = v * cachedPower; 175 | 176 | error += kUlp + (error == 0 ? 0 : 1); 177 | 178 | const int oldExp = v.e; 179 | v = v.Normalize(); 180 | error <<= oldExp - v.e; 181 | 182 | const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); 183 | int precisionSize = 64 - effectiveSignificandSize; 184 | if (precisionSize + kUlpShift >= 64) { 185 | int scaleExp = (precisionSize + kUlpShift) - 63; 186 | v.f >>= scaleExp; 187 | v.e += scaleExp; 188 | error = (error >> scaleExp) + 1 + kUlp; 189 | precisionSize -= scaleExp; 190 | } 191 | 192 | DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); 193 | const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; 194 | const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; 195 | if (precisionBits >= halfWay + static_cast(error)) { 196 | rounded.f++; 197 | if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) 198 | rounded.f >>= 1; 199 | rounded.e++; 200 | } 201 | } 202 | 203 | *result = rounded.ToDouble(); 204 | 205 | return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); 206 | } 207 | 208 | inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) { 209 | RAPIDJSON_ASSERT(dLen >= 0); 210 | const BigInteger dInt(decimals, static_cast(dLen)); 211 | Double a(approx); 212 | int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); 213 | if (cmp < 0) 214 | return a.Value(); // within half ULP 215 | else if (cmp == 0) { 216 | // Round towards even 217 | if (a.Significand() & 1) 218 | return a.NextPositiveDouble(); 219 | else 220 | return a.Value(); 221 | } 222 | else // adjustment 223 | return a.NextPositiveDouble(); 224 | } 225 | 226 | inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { 227 | RAPIDJSON_ASSERT(d >= 0.0); 228 | RAPIDJSON_ASSERT(length >= 1); 229 | 230 | double result = 0.0; 231 | if (StrtodFast(d, p, &result)) 232 | return result; 233 | 234 | RAPIDJSON_ASSERT(length <= INT_MAX); 235 | int dLen = static_cast(length); 236 | 237 | RAPIDJSON_ASSERT(length >= decimalPosition); 238 | RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX); 239 | int dExpAdjust = static_cast(length - decimalPosition); 240 | 241 | RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust); 242 | int dExp = exp - dExpAdjust; 243 | 244 | // Make sure length+dExp does not overflow 245 | RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen); 246 | 247 | // Trim leading zeros 248 | while (dLen > 0 && *decimals == '0') { 249 | dLen--; 250 | decimals++; 251 | } 252 | 253 | // Trim trailing zeros 254 | while (dLen > 0 && decimals[dLen - 1] == '0') { 255 | dLen--; 256 | dExp++; 257 | } 258 | 259 | if (dLen == 0) { // Buffer only contains zeros. 260 | return 0.0; 261 | } 262 | 263 | // Trim right-most digits 264 | const int kMaxDecimalDigit = 767 + 1; 265 | if (dLen > kMaxDecimalDigit) { 266 | dExp += dLen - kMaxDecimalDigit; 267 | dLen = kMaxDecimalDigit; 268 | } 269 | 270 | // If too small, underflow to zero. 271 | // Any x <= 10^-324 is interpreted as zero. 272 | if (dLen + dExp <= -324) 273 | return 0.0; 274 | 275 | // If too large, overflow to infinity. 276 | // Any x >= 10^309 is interpreted as +infinity. 277 | if (dLen + dExp > 309) 278 | return std::numeric_limits::infinity(); 279 | 280 | if (StrtodDiyFp(decimals, dLen, dExp, &result)) 281 | return result; 282 | 283 | // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison 284 | return StrtodBigInteger(result, decimals, dLen, dExp); 285 | } 286 | 287 | } // namespace internal 288 | RAPIDJSON_NAMESPACE_END 289 | 290 | #endif // RAPIDJSON_STRTOD_ 291 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/internal/swap.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_SWAP_H_ 16 | #define RAPIDJSON_INTERNAL_SWAP_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #if defined(__clang__) 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(c++98-compat) 23 | #endif 24 | 25 | RAPIDJSON_NAMESPACE_BEGIN 26 | namespace internal { 27 | 28 | //! Custom swap() to avoid dependency on C++ header 29 | /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. 30 | \note This has the same semantics as std::swap(). 31 | */ 32 | template 33 | inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { 34 | T tmp = a; 35 | a = b; 36 | b = tmp; 37 | } 38 | 39 | } // namespace internal 40 | RAPIDJSON_NAMESPACE_END 41 | 42 | #if defined(__clang__) 43 | RAPIDJSON_DIAG_POP 44 | #endif 45 | 46 | #endif // RAPIDJSON_INTERNAL_SWAP_H_ 47 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/istreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ISTREAMWRAPPER_H_ 16 | #define RAPIDJSON_ISTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(padded) 24 | #elif defined(_MSC_VER) 25 | RAPIDJSON_DIAG_PUSH 26 | RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized 27 | #endif 28 | 29 | RAPIDJSON_NAMESPACE_BEGIN 30 | 31 | //! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. 32 | /*! 33 | The classes can be wrapped including but not limited to: 34 | 35 | - \c std::istringstream 36 | - \c std::stringstream 37 | - \c std::wistringstream 38 | - \c std::wstringstream 39 | - \c std::ifstream 40 | - \c std::fstream 41 | - \c std::wifstream 42 | - \c std::wfstream 43 | 44 | \tparam StreamType Class derived from \c std::basic_istream. 45 | */ 46 | 47 | template 48 | class BasicIStreamWrapper { 49 | public: 50 | typedef typename StreamType::char_type Ch; 51 | 52 | //! Constructor. 53 | /*! 54 | \param stream stream opened for read. 55 | */ 56 | BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 57 | Read(); 58 | } 59 | 60 | //! Constructor. 61 | /*! 62 | \param stream stream opened for read. 63 | \param buffer user-supplied buffer. 64 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 65 | */ 66 | BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 67 | RAPIDJSON_ASSERT(bufferSize >= 4); 68 | Read(); 69 | } 70 | 71 | Ch Peek() const { return *current_; } 72 | Ch Take() { Ch c = *current_; Read(); return c; } 73 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 74 | 75 | // Not implemented 76 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 77 | void Flush() { RAPIDJSON_ASSERT(false); } 78 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 79 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 80 | 81 | // For encoding detection only. 82 | const Ch* Peek4() const { 83 | return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; 84 | } 85 | 86 | private: 87 | BasicIStreamWrapper(); 88 | BasicIStreamWrapper(const BasicIStreamWrapper&); 89 | BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); 90 | 91 | void Read() { 92 | if (current_ < bufferLast_) 93 | ++current_; 94 | else if (!eof_) { 95 | count_ += readCount_; 96 | readCount_ = bufferSize_; 97 | bufferLast_ = buffer_ + readCount_ - 1; 98 | current_ = buffer_; 99 | 100 | if (!stream_.read(buffer_, static_cast(bufferSize_))) { 101 | readCount_ = static_cast(stream_.gcount()); 102 | *(bufferLast_ = buffer_ + readCount_) = '\0'; 103 | eof_ = true; 104 | } 105 | } 106 | } 107 | 108 | StreamType &stream_; 109 | Ch peekBuffer_[4], *buffer_; 110 | size_t bufferSize_; 111 | Ch *bufferLast_; 112 | Ch *current_; 113 | size_t readCount_; 114 | size_t count_; //!< Number of characters read 115 | bool eof_; 116 | }; 117 | 118 | typedef BasicIStreamWrapper IStreamWrapper; 119 | typedef BasicIStreamWrapper WIStreamWrapper; 120 | 121 | #if defined(__clang__) || defined(_MSC_VER) 122 | RAPIDJSON_DIAG_POP 123 | #endif 124 | 125 | RAPIDJSON_NAMESPACE_END 126 | 127 | #endif // RAPIDJSON_ISTREAMWRAPPER_H_ 128 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/memorybuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYBUFFER_H_ 16 | #define RAPIDJSON_MEMORYBUFFER_H_ 17 | 18 | #include "stream.h" 19 | #include "internal/stack.h" 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Represents an in-memory output byte stream. 24 | /*! 25 | This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. 26 | 27 | It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. 28 | 29 | Differences between MemoryBuffer and StringBuffer: 30 | 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 31 | 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. 32 | 33 | \tparam Allocator type for allocating memory buffer. 34 | \note implements Stream concept 35 | */ 36 | template 37 | struct GenericMemoryBuffer { 38 | typedef char Ch; // byte 39 | 40 | GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 41 | 42 | void Put(Ch c) { *stack_.template Push() = c; } 43 | void Flush() {} 44 | 45 | void Clear() { stack_.Clear(); } 46 | void ShrinkToFit() { stack_.ShrinkToFit(); } 47 | Ch* Push(size_t count) { return stack_.template Push(count); } 48 | void Pop(size_t count) { stack_.template Pop(count); } 49 | 50 | const Ch* GetBuffer() const { 51 | return stack_.template Bottom(); 52 | } 53 | 54 | size_t GetSize() const { return stack_.GetSize(); } 55 | 56 | static const size_t kDefaultCapacity = 256; 57 | mutable internal::Stack stack_; 58 | }; 59 | 60 | typedef GenericMemoryBuffer<> MemoryBuffer; 61 | 62 | //! Implement specialized version of PutN() with memset() for better performance. 63 | template<> 64 | inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { 65 | std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 71 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/memorystream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYSTREAM_H_ 16 | #define RAPIDJSON_MEMORYSTREAM_H_ 17 | 18 | #include "stream.h" 19 | 20 | #ifdef __clang__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(unreachable-code) 23 | RAPIDJSON_DIAG_OFF(missing-noreturn) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Represents an in-memory input byte stream. 29 | /*! 30 | This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. 31 | 32 | It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. 33 | 34 | Differences between MemoryStream and StringStream: 35 | 1. StringStream has encoding but MemoryStream is a byte stream. 36 | 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. 37 | 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). 38 | \note implements Stream concept 39 | */ 40 | struct MemoryStream { 41 | typedef char Ch; // byte 42 | 43 | MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} 44 | 45 | Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } 46 | Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } 47 | size_t Tell() const { return static_cast(src_ - begin_); } 48 | 49 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 50 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 51 | void Flush() { RAPIDJSON_ASSERT(false); } 52 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 53 | 54 | // For encoding detection only. 55 | const Ch* Peek4() const { 56 | return Tell() + 4 <= size_ ? src_ : 0; 57 | } 58 | 59 | const Ch* src_; //!< Current read position. 60 | const Ch* begin_; //!< Original head of the string. 61 | const Ch* end_; //!< End of stream. 62 | size_t size_; //!< Size of the stream. 63 | }; 64 | 65 | RAPIDJSON_NAMESPACE_END 66 | 67 | #ifdef __clang__ 68 | RAPIDJSON_DIAG_POP 69 | #endif 70 | 71 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 72 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/msinttypes/inttypes.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant inttypes.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2013 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. Neither the name of the product nor the names of its contributors may 17 | // be used to endorse or promote products derived from this software 18 | // without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // 31 | /////////////////////////////////////////////////////////////////////////////// 32 | 33 | // The above software in this distribution may have been modified by 34 | // THL A29 Limited ("Tencent Modifications"). 35 | // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. 36 | 37 | #ifndef _MSC_VER // [ 38 | #error "Use this header only with Microsoft Visual C++ compilers!" 39 | #endif // _MSC_VER ] 40 | 41 | #ifndef _MSC_INTTYPES_H_ // [ 42 | #define _MSC_INTTYPES_H_ 43 | 44 | #if _MSC_VER > 1000 45 | #pragma once 46 | #endif 47 | 48 | #include "stdint.h" 49 | 50 | // miloyip: VC supports inttypes.h since VC2013 51 | #if _MSC_VER >= 1800 52 | #include 53 | #else 54 | 55 | // 7.8 Format conversion of integer types 56 | 57 | typedef struct { 58 | intmax_t quot; 59 | intmax_t rem; 60 | } imaxdiv_t; 61 | 62 | // 7.8.1 Macros for format specifiers 63 | 64 | #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 65 | 66 | // The fprintf macros for signed integers are: 67 | #define PRId8 "d" 68 | #define PRIi8 "i" 69 | #define PRIdLEAST8 "d" 70 | #define PRIiLEAST8 "i" 71 | #define PRIdFAST8 "d" 72 | #define PRIiFAST8 "i" 73 | 74 | #define PRId16 "hd" 75 | #define PRIi16 "hi" 76 | #define PRIdLEAST16 "hd" 77 | #define PRIiLEAST16 "hi" 78 | #define PRIdFAST16 "hd" 79 | #define PRIiFAST16 "hi" 80 | 81 | #define PRId32 "I32d" 82 | #define PRIi32 "I32i" 83 | #define PRIdLEAST32 "I32d" 84 | #define PRIiLEAST32 "I32i" 85 | #define PRIdFAST32 "I32d" 86 | #define PRIiFAST32 "I32i" 87 | 88 | #define PRId64 "I64d" 89 | #define PRIi64 "I64i" 90 | #define PRIdLEAST64 "I64d" 91 | #define PRIiLEAST64 "I64i" 92 | #define PRIdFAST64 "I64d" 93 | #define PRIiFAST64 "I64i" 94 | 95 | #define PRIdMAX "I64d" 96 | #define PRIiMAX "I64i" 97 | 98 | #define PRIdPTR "Id" 99 | #define PRIiPTR "Ii" 100 | 101 | // The fprintf macros for unsigned integers are: 102 | #define PRIo8 "o" 103 | #define PRIu8 "u" 104 | #define PRIx8 "x" 105 | #define PRIX8 "X" 106 | #define PRIoLEAST8 "o" 107 | #define PRIuLEAST8 "u" 108 | #define PRIxLEAST8 "x" 109 | #define PRIXLEAST8 "X" 110 | #define PRIoFAST8 "o" 111 | #define PRIuFAST8 "u" 112 | #define PRIxFAST8 "x" 113 | #define PRIXFAST8 "X" 114 | 115 | #define PRIo16 "ho" 116 | #define PRIu16 "hu" 117 | #define PRIx16 "hx" 118 | #define PRIX16 "hX" 119 | #define PRIoLEAST16 "ho" 120 | #define PRIuLEAST16 "hu" 121 | #define PRIxLEAST16 "hx" 122 | #define PRIXLEAST16 "hX" 123 | #define PRIoFAST16 "ho" 124 | #define PRIuFAST16 "hu" 125 | #define PRIxFAST16 "hx" 126 | #define PRIXFAST16 "hX" 127 | 128 | #define PRIo32 "I32o" 129 | #define PRIu32 "I32u" 130 | #define PRIx32 "I32x" 131 | #define PRIX32 "I32X" 132 | #define PRIoLEAST32 "I32o" 133 | #define PRIuLEAST32 "I32u" 134 | #define PRIxLEAST32 "I32x" 135 | #define PRIXLEAST32 "I32X" 136 | #define PRIoFAST32 "I32o" 137 | #define PRIuFAST32 "I32u" 138 | #define PRIxFAST32 "I32x" 139 | #define PRIXFAST32 "I32X" 140 | 141 | #define PRIo64 "I64o" 142 | #define PRIu64 "I64u" 143 | #define PRIx64 "I64x" 144 | #define PRIX64 "I64X" 145 | #define PRIoLEAST64 "I64o" 146 | #define PRIuLEAST64 "I64u" 147 | #define PRIxLEAST64 "I64x" 148 | #define PRIXLEAST64 "I64X" 149 | #define PRIoFAST64 "I64o" 150 | #define PRIuFAST64 "I64u" 151 | #define PRIxFAST64 "I64x" 152 | #define PRIXFAST64 "I64X" 153 | 154 | #define PRIoMAX "I64o" 155 | #define PRIuMAX "I64u" 156 | #define PRIxMAX "I64x" 157 | #define PRIXMAX "I64X" 158 | 159 | #define PRIoPTR "Io" 160 | #define PRIuPTR "Iu" 161 | #define PRIxPTR "Ix" 162 | #define PRIXPTR "IX" 163 | 164 | // The fscanf macros for signed integers are: 165 | #define SCNd8 "d" 166 | #define SCNi8 "i" 167 | #define SCNdLEAST8 "d" 168 | #define SCNiLEAST8 "i" 169 | #define SCNdFAST8 "d" 170 | #define SCNiFAST8 "i" 171 | 172 | #define SCNd16 "hd" 173 | #define SCNi16 "hi" 174 | #define SCNdLEAST16 "hd" 175 | #define SCNiLEAST16 "hi" 176 | #define SCNdFAST16 "hd" 177 | #define SCNiFAST16 "hi" 178 | 179 | #define SCNd32 "ld" 180 | #define SCNi32 "li" 181 | #define SCNdLEAST32 "ld" 182 | #define SCNiLEAST32 "li" 183 | #define SCNdFAST32 "ld" 184 | #define SCNiFAST32 "li" 185 | 186 | #define SCNd64 "I64d" 187 | #define SCNi64 "I64i" 188 | #define SCNdLEAST64 "I64d" 189 | #define SCNiLEAST64 "I64i" 190 | #define SCNdFAST64 "I64d" 191 | #define SCNiFAST64 "I64i" 192 | 193 | #define SCNdMAX "I64d" 194 | #define SCNiMAX "I64i" 195 | 196 | #ifdef _WIN64 // [ 197 | # define SCNdPTR "I64d" 198 | # define SCNiPTR "I64i" 199 | #else // _WIN64 ][ 200 | # define SCNdPTR "ld" 201 | # define SCNiPTR "li" 202 | #endif // _WIN64 ] 203 | 204 | // The fscanf macros for unsigned integers are: 205 | #define SCNo8 "o" 206 | #define SCNu8 "u" 207 | #define SCNx8 "x" 208 | #define SCNX8 "X" 209 | #define SCNoLEAST8 "o" 210 | #define SCNuLEAST8 "u" 211 | #define SCNxLEAST8 "x" 212 | #define SCNXLEAST8 "X" 213 | #define SCNoFAST8 "o" 214 | #define SCNuFAST8 "u" 215 | #define SCNxFAST8 "x" 216 | #define SCNXFAST8 "X" 217 | 218 | #define SCNo16 "ho" 219 | #define SCNu16 "hu" 220 | #define SCNx16 "hx" 221 | #define SCNX16 "hX" 222 | #define SCNoLEAST16 "ho" 223 | #define SCNuLEAST16 "hu" 224 | #define SCNxLEAST16 "hx" 225 | #define SCNXLEAST16 "hX" 226 | #define SCNoFAST16 "ho" 227 | #define SCNuFAST16 "hu" 228 | #define SCNxFAST16 "hx" 229 | #define SCNXFAST16 "hX" 230 | 231 | #define SCNo32 "lo" 232 | #define SCNu32 "lu" 233 | #define SCNx32 "lx" 234 | #define SCNX32 "lX" 235 | #define SCNoLEAST32 "lo" 236 | #define SCNuLEAST32 "lu" 237 | #define SCNxLEAST32 "lx" 238 | #define SCNXLEAST32 "lX" 239 | #define SCNoFAST32 "lo" 240 | #define SCNuFAST32 "lu" 241 | #define SCNxFAST32 "lx" 242 | #define SCNXFAST32 "lX" 243 | 244 | #define SCNo64 "I64o" 245 | #define SCNu64 "I64u" 246 | #define SCNx64 "I64x" 247 | #define SCNX64 "I64X" 248 | #define SCNoLEAST64 "I64o" 249 | #define SCNuLEAST64 "I64u" 250 | #define SCNxLEAST64 "I64x" 251 | #define SCNXLEAST64 "I64X" 252 | #define SCNoFAST64 "I64o" 253 | #define SCNuFAST64 "I64u" 254 | #define SCNxFAST64 "I64x" 255 | #define SCNXFAST64 "I64X" 256 | 257 | #define SCNoMAX "I64o" 258 | #define SCNuMAX "I64u" 259 | #define SCNxMAX "I64x" 260 | #define SCNXMAX "I64X" 261 | 262 | #ifdef _WIN64 // [ 263 | # define SCNoPTR "I64o" 264 | # define SCNuPTR "I64u" 265 | # define SCNxPTR "I64x" 266 | # define SCNXPTR "I64X" 267 | #else // _WIN64 ][ 268 | # define SCNoPTR "lo" 269 | # define SCNuPTR "lu" 270 | # define SCNxPTR "lx" 271 | # define SCNXPTR "lX" 272 | #endif // _WIN64 ] 273 | 274 | #endif // __STDC_FORMAT_MACROS ] 275 | 276 | // 7.8.2 Functions for greatest-width integer types 277 | 278 | // 7.8.2.1 The imaxabs function 279 | #define imaxabs _abs64 280 | 281 | // 7.8.2.2 The imaxdiv function 282 | 283 | // This is modified version of div() function from Microsoft's div.c found 284 | // in %MSVC.NET%\crt\src\div.c 285 | #ifdef STATIC_IMAXDIV // [ 286 | static 287 | #else // STATIC_IMAXDIV ][ 288 | _inline 289 | #endif // STATIC_IMAXDIV ] 290 | imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) 291 | { 292 | imaxdiv_t result; 293 | 294 | result.quot = numer / denom; 295 | result.rem = numer % denom; 296 | 297 | if (numer < 0 && result.rem > 0) { 298 | // did division wrong; must fix up 299 | ++result.quot; 300 | result.rem -= denom; 301 | } 302 | 303 | return result; 304 | } 305 | 306 | // 7.8.2.3 The strtoimax and strtoumax functions 307 | #define strtoimax _strtoi64 308 | #define strtoumax _strtoui64 309 | 310 | // 7.8.2.4 The wcstoimax and wcstoumax functions 311 | #define wcstoimax _wcstoi64 312 | #define wcstoumax _wcstoui64 313 | 314 | #endif // _MSC_VER >= 1800 315 | 316 | #endif // _MSC_INTTYPES_H_ ] 317 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/msinttypes/stdint.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant stdint.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2013 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. Neither the name of the product nor the names of its contributors may 17 | // be used to endorse or promote products derived from this software 18 | // without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // 31 | /////////////////////////////////////////////////////////////////////////////// 32 | 33 | // The above software in this distribution may have been modified by 34 | // THL A29 Limited ("Tencent Modifications"). 35 | // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. 36 | 37 | #ifndef _MSC_VER // [ 38 | #error "Use this header only with Microsoft Visual C++ compilers!" 39 | #endif // _MSC_VER ] 40 | 41 | #ifndef _MSC_STDINT_H_ // [ 42 | #define _MSC_STDINT_H_ 43 | 44 | #if _MSC_VER > 1000 45 | #pragma once 46 | #endif 47 | 48 | // miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. 49 | #if _MSC_VER >= 1600 // [ 50 | #include 51 | 52 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 53 | 54 | #undef INT8_C 55 | #undef INT16_C 56 | #undef INT32_C 57 | #undef INT64_C 58 | #undef UINT8_C 59 | #undef UINT16_C 60 | #undef UINT32_C 61 | #undef UINT64_C 62 | 63 | // 7.18.4.1 Macros for minimum-width integer constants 64 | 65 | #define INT8_C(val) val##i8 66 | #define INT16_C(val) val##i16 67 | #define INT32_C(val) val##i32 68 | #define INT64_C(val) val##i64 69 | 70 | #define UINT8_C(val) val##ui8 71 | #define UINT16_C(val) val##ui16 72 | #define UINT32_C(val) val##ui32 73 | #define UINT64_C(val) val##ui64 74 | 75 | // 7.18.4.2 Macros for greatest-width integer constants 76 | // These #ifndef's are needed to prevent collisions with . 77 | // Check out Issue 9 for the details. 78 | #ifndef INTMAX_C // [ 79 | # define INTMAX_C INT64_C 80 | #endif // INTMAX_C ] 81 | #ifndef UINTMAX_C // [ 82 | # define UINTMAX_C UINT64_C 83 | #endif // UINTMAX_C ] 84 | 85 | #endif // __STDC_CONSTANT_MACROS ] 86 | 87 | #else // ] _MSC_VER >= 1700 [ 88 | 89 | #include 90 | 91 | // For Visual Studio 6 in C++ mode and for many Visual Studio versions when 92 | // compiling for ARM we have to wrap include with 'extern "C++" {}' 93 | // or compiler would give many errors like this: 94 | // error C2733: second C linkage of overloaded function 'wmemchr' not allowed 95 | #if defined(__cplusplus) && !defined(_M_ARM) 96 | extern "C" { 97 | #endif 98 | # include 99 | #if defined(__cplusplus) && !defined(_M_ARM) 100 | } 101 | #endif 102 | 103 | // Define _W64 macros to mark types changing their size, like intptr_t. 104 | #ifndef _W64 105 | # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 106 | # define _W64 __w64 107 | # else 108 | # define _W64 109 | # endif 110 | #endif 111 | 112 | 113 | // 7.18.1 Integer types 114 | 115 | // 7.18.1.1 Exact-width integer types 116 | 117 | // Visual Studio 6 and Embedded Visual C++ 4 doesn't 118 | // realize that, e.g. char has the same size as __int8 119 | // so we give up on __intX for them. 120 | #if (_MSC_VER < 1300) 121 | typedef signed char int8_t; 122 | typedef signed short int16_t; 123 | typedef signed int int32_t; 124 | typedef unsigned char uint8_t; 125 | typedef unsigned short uint16_t; 126 | typedef unsigned int uint32_t; 127 | #else 128 | typedef signed __int8 int8_t; 129 | typedef signed __int16 int16_t; 130 | typedef signed __int32 int32_t; 131 | typedef unsigned __int8 uint8_t; 132 | typedef unsigned __int16 uint16_t; 133 | typedef unsigned __int32 uint32_t; 134 | #endif 135 | typedef signed __int64 int64_t; 136 | typedef unsigned __int64 uint64_t; 137 | 138 | 139 | // 7.18.1.2 Minimum-width integer types 140 | typedef int8_t int_least8_t; 141 | typedef int16_t int_least16_t; 142 | typedef int32_t int_least32_t; 143 | typedef int64_t int_least64_t; 144 | typedef uint8_t uint_least8_t; 145 | typedef uint16_t uint_least16_t; 146 | typedef uint32_t uint_least32_t; 147 | typedef uint64_t uint_least64_t; 148 | 149 | // 7.18.1.3 Fastest minimum-width integer types 150 | typedef int8_t int_fast8_t; 151 | typedef int16_t int_fast16_t; 152 | typedef int32_t int_fast32_t; 153 | typedef int64_t int_fast64_t; 154 | typedef uint8_t uint_fast8_t; 155 | typedef uint16_t uint_fast16_t; 156 | typedef uint32_t uint_fast32_t; 157 | typedef uint64_t uint_fast64_t; 158 | 159 | // 7.18.1.4 Integer types capable of holding object pointers 160 | #ifdef _WIN64 // [ 161 | typedef signed __int64 intptr_t; 162 | typedef unsigned __int64 uintptr_t; 163 | #else // _WIN64 ][ 164 | typedef _W64 signed int intptr_t; 165 | typedef _W64 unsigned int uintptr_t; 166 | #endif // _WIN64 ] 167 | 168 | // 7.18.1.5 Greatest-width integer types 169 | typedef int64_t intmax_t; 170 | typedef uint64_t uintmax_t; 171 | 172 | 173 | // 7.18.2 Limits of specified-width integer types 174 | 175 | #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 176 | 177 | // 7.18.2.1 Limits of exact-width integer types 178 | #define INT8_MIN ((int8_t)_I8_MIN) 179 | #define INT8_MAX _I8_MAX 180 | #define INT16_MIN ((int16_t)_I16_MIN) 181 | #define INT16_MAX _I16_MAX 182 | #define INT32_MIN ((int32_t)_I32_MIN) 183 | #define INT32_MAX _I32_MAX 184 | #define INT64_MIN ((int64_t)_I64_MIN) 185 | #define INT64_MAX _I64_MAX 186 | #define UINT8_MAX _UI8_MAX 187 | #define UINT16_MAX _UI16_MAX 188 | #define UINT32_MAX _UI32_MAX 189 | #define UINT64_MAX _UI64_MAX 190 | 191 | // 7.18.2.2 Limits of minimum-width integer types 192 | #define INT_LEAST8_MIN INT8_MIN 193 | #define INT_LEAST8_MAX INT8_MAX 194 | #define INT_LEAST16_MIN INT16_MIN 195 | #define INT_LEAST16_MAX INT16_MAX 196 | #define INT_LEAST32_MIN INT32_MIN 197 | #define INT_LEAST32_MAX INT32_MAX 198 | #define INT_LEAST64_MIN INT64_MIN 199 | #define INT_LEAST64_MAX INT64_MAX 200 | #define UINT_LEAST8_MAX UINT8_MAX 201 | #define UINT_LEAST16_MAX UINT16_MAX 202 | #define UINT_LEAST32_MAX UINT32_MAX 203 | #define UINT_LEAST64_MAX UINT64_MAX 204 | 205 | // 7.18.2.3 Limits of fastest minimum-width integer types 206 | #define INT_FAST8_MIN INT8_MIN 207 | #define INT_FAST8_MAX INT8_MAX 208 | #define INT_FAST16_MIN INT16_MIN 209 | #define INT_FAST16_MAX INT16_MAX 210 | #define INT_FAST32_MIN INT32_MIN 211 | #define INT_FAST32_MAX INT32_MAX 212 | #define INT_FAST64_MIN INT64_MIN 213 | #define INT_FAST64_MAX INT64_MAX 214 | #define UINT_FAST8_MAX UINT8_MAX 215 | #define UINT_FAST16_MAX UINT16_MAX 216 | #define UINT_FAST32_MAX UINT32_MAX 217 | #define UINT_FAST64_MAX UINT64_MAX 218 | 219 | // 7.18.2.4 Limits of integer types capable of holding object pointers 220 | #ifdef _WIN64 // [ 221 | # define INTPTR_MIN INT64_MIN 222 | # define INTPTR_MAX INT64_MAX 223 | # define UINTPTR_MAX UINT64_MAX 224 | #else // _WIN64 ][ 225 | # define INTPTR_MIN INT32_MIN 226 | # define INTPTR_MAX INT32_MAX 227 | # define UINTPTR_MAX UINT32_MAX 228 | #endif // _WIN64 ] 229 | 230 | // 7.18.2.5 Limits of greatest-width integer types 231 | #define INTMAX_MIN INT64_MIN 232 | #define INTMAX_MAX INT64_MAX 233 | #define UINTMAX_MAX UINT64_MAX 234 | 235 | // 7.18.3 Limits of other integer types 236 | 237 | #ifdef _WIN64 // [ 238 | # define PTRDIFF_MIN _I64_MIN 239 | # define PTRDIFF_MAX _I64_MAX 240 | #else // _WIN64 ][ 241 | # define PTRDIFF_MIN _I32_MIN 242 | # define PTRDIFF_MAX _I32_MAX 243 | #endif // _WIN64 ] 244 | 245 | #define SIG_ATOMIC_MIN INT_MIN 246 | #define SIG_ATOMIC_MAX INT_MAX 247 | 248 | #ifndef SIZE_MAX // [ 249 | # ifdef _WIN64 // [ 250 | # define SIZE_MAX _UI64_MAX 251 | # else // _WIN64 ][ 252 | # define SIZE_MAX _UI32_MAX 253 | # endif // _WIN64 ] 254 | #endif // SIZE_MAX ] 255 | 256 | // WCHAR_MIN and WCHAR_MAX are also defined in 257 | #ifndef WCHAR_MIN // [ 258 | # define WCHAR_MIN 0 259 | #endif // WCHAR_MIN ] 260 | #ifndef WCHAR_MAX // [ 261 | # define WCHAR_MAX _UI16_MAX 262 | #endif // WCHAR_MAX ] 263 | 264 | #define WINT_MIN 0 265 | #define WINT_MAX _UI16_MAX 266 | 267 | #endif // __STDC_LIMIT_MACROS ] 268 | 269 | 270 | // 7.18.4 Limits of other integer types 271 | 272 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 273 | 274 | // 7.18.4.1 Macros for minimum-width integer constants 275 | 276 | #define INT8_C(val) val##i8 277 | #define INT16_C(val) val##i16 278 | #define INT32_C(val) val##i32 279 | #define INT64_C(val) val##i64 280 | 281 | #define UINT8_C(val) val##ui8 282 | #define UINT16_C(val) val##ui16 283 | #define UINT32_C(val) val##ui32 284 | #define UINT64_C(val) val##ui64 285 | 286 | // 7.18.4.2 Macros for greatest-width integer constants 287 | // These #ifndef's are needed to prevent collisions with . 288 | // Check out Issue 9 for the details. 289 | #ifndef INTMAX_C // [ 290 | # define INTMAX_C INT64_C 291 | #endif // INTMAX_C ] 292 | #ifndef UINTMAX_C // [ 293 | # define UINTMAX_C UINT64_C 294 | #endif // UINTMAX_C ] 295 | 296 | #endif // __STDC_CONSTANT_MACROS ] 297 | 298 | #endif // _MSC_VER >= 1600 ] 299 | 300 | #endif // _MSC_STDINT_H_ ] 301 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/ostreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_OSTREAMWRAPPER_H_ 16 | #define RAPIDJSON_OSTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(padded) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. 29 | /*! 30 | The classes can be wrapped including but not limited to: 31 | 32 | - \c std::ostringstream 33 | - \c std::stringstream 34 | - \c std::wpstringstream 35 | - \c std::wstringstream 36 | - \c std::ifstream 37 | - \c std::fstream 38 | - \c std::wofstream 39 | - \c std::wfstream 40 | 41 | \tparam StreamType Class derived from \c std::basic_ostream. 42 | */ 43 | 44 | template 45 | class BasicOStreamWrapper { 46 | public: 47 | typedef typename StreamType::char_type Ch; 48 | BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} 49 | 50 | void Put(Ch c) { 51 | stream_.put(c); 52 | } 53 | 54 | void Flush() { 55 | stream_.flush(); 56 | } 57 | 58 | // Not implemented 59 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 60 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 61 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 62 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 63 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 64 | 65 | private: 66 | BasicOStreamWrapper(const BasicOStreamWrapper&); 67 | BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); 68 | 69 | StreamType& stream_; 70 | }; 71 | 72 | typedef BasicOStreamWrapper OStreamWrapper; 73 | typedef BasicOStreamWrapper WOStreamWrapper; 74 | 75 | #ifdef __clang__ 76 | RAPIDJSON_DIAG_POP 77 | #endif 78 | 79 | RAPIDJSON_NAMESPACE_END 80 | 81 | #endif // RAPIDJSON_OSTREAMWRAPPER_H_ 82 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/stream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "rapidjson.h" 16 | 17 | #ifndef RAPIDJSON_STREAM_H_ 18 | #define RAPIDJSON_STREAM_H_ 19 | 20 | #include "encodings.h" 21 | 22 | RAPIDJSON_NAMESPACE_BEGIN 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // Stream 26 | 27 | /*! \class rapidjson::Stream 28 | \brief Concept for reading and writing characters. 29 | 30 | For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). 31 | 32 | For write-only stream, only need to implement Put() and Flush(). 33 | 34 | \code 35 | concept Stream { 36 | typename Ch; //!< Character type of the stream. 37 | 38 | //! Read the current character from stream without moving the read cursor. 39 | Ch Peek() const; 40 | 41 | //! Read the current character from stream and moving the read cursor to next character. 42 | Ch Take(); 43 | 44 | //! Get the current read cursor. 45 | //! \return Number of characters read from start. 46 | size_t Tell(); 47 | 48 | //! Begin writing operation at the current read pointer. 49 | //! \return The begin writer pointer. 50 | Ch* PutBegin(); 51 | 52 | //! Write a character. 53 | void Put(Ch c); 54 | 55 | //! Flush the buffer. 56 | void Flush(); 57 | 58 | //! End the writing operation. 59 | //! \param begin The begin write pointer returned by PutBegin(). 60 | //! \return Number of characters written. 61 | size_t PutEnd(Ch* begin); 62 | } 63 | \endcode 64 | */ 65 | 66 | //! Provides additional information for stream. 67 | /*! 68 | By using traits pattern, this type provides a default configuration for stream. 69 | For custom stream, this type can be specialized for other configuration. 70 | See TEST(Reader, CustomStringStream) in readertest.cpp for example. 71 | */ 72 | template 73 | struct StreamTraits { 74 | //! Whether to make local copy of stream for optimization during parsing. 75 | /*! 76 | By default, for safety, streams do not use local copy optimization. 77 | Stream that can be copied fast should specialize this, like StreamTraits. 78 | */ 79 | enum { copyOptimization = 0 }; 80 | }; 81 | 82 | //! Reserve n characters for writing to a stream. 83 | template 84 | inline void PutReserve(Stream& stream, size_t count) { 85 | (void)stream; 86 | (void)count; 87 | } 88 | 89 | //! Write character to a stream, presuming buffer is reserved. 90 | template 91 | inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { 92 | stream.Put(c); 93 | } 94 | 95 | //! Put N copies of a character to a stream. 96 | template 97 | inline void PutN(Stream& stream, Ch c, size_t n) { 98 | PutReserve(stream, n); 99 | for (size_t i = 0; i < n; i++) 100 | PutUnsafe(stream, c); 101 | } 102 | 103 | /////////////////////////////////////////////////////////////////////////////// 104 | // GenericStreamWrapper 105 | 106 | //! A Stream Wrapper 107 | /*! \tThis string stream is a wrapper for any stream by just forwarding any 108 | \treceived message to the origin stream. 109 | \note implements Stream concept 110 | */ 111 | 112 | #if defined(_MSC_VER) && _MSC_VER <= 1800 113 | RAPIDJSON_DIAG_PUSH 114 | RAPIDJSON_DIAG_OFF(4702) // unreachable code 115 | RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated 116 | #endif 117 | 118 | template > 119 | class GenericStreamWrapper { 120 | public: 121 | typedef typename Encoding::Ch Ch; 122 | GenericStreamWrapper(InputStream& is): is_(is) {} 123 | 124 | Ch Peek() const { return is_.Peek(); } 125 | Ch Take() { return is_.Take(); } 126 | size_t Tell() { return is_.Tell(); } 127 | Ch* PutBegin() { return is_.PutBegin(); } 128 | void Put(Ch ch) { is_.Put(ch); } 129 | void Flush() { is_.Flush(); } 130 | size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); } 131 | 132 | // wrapper for MemoryStream 133 | const Ch* Peek4() const { return is_.Peek4(); } 134 | 135 | // wrapper for AutoUTFInputStream 136 | UTFType GetType() const { return is_.GetType(); } 137 | bool HasBOM() const { return is_.HasBOM(); } 138 | 139 | protected: 140 | InputStream& is_; 141 | }; 142 | 143 | #if defined(_MSC_VER) && _MSC_VER <= 1800 144 | RAPIDJSON_DIAG_POP 145 | #endif 146 | 147 | /////////////////////////////////////////////////////////////////////////////// 148 | // StringStream 149 | 150 | //! Read-only string stream. 151 | /*! \note implements Stream concept 152 | */ 153 | template 154 | struct GenericStringStream { 155 | typedef typename Encoding::Ch Ch; 156 | 157 | GenericStringStream(const Ch *src) : src_(src), head_(src) {} 158 | 159 | Ch Peek() const { return *src_; } 160 | Ch Take() { return *src_++; } 161 | size_t Tell() const { return static_cast(src_ - head_); } 162 | 163 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 164 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 165 | void Flush() { RAPIDJSON_ASSERT(false); } 166 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 167 | 168 | const Ch* src_; //!< Current read position. 169 | const Ch* head_; //!< Original head of the string. 170 | }; 171 | 172 | template 173 | struct StreamTraits > { 174 | enum { copyOptimization = 1 }; 175 | }; 176 | 177 | //! String stream with UTF8 encoding. 178 | typedef GenericStringStream > StringStream; 179 | 180 | /////////////////////////////////////////////////////////////////////////////// 181 | // InsituStringStream 182 | 183 | //! A read-write string stream. 184 | /*! This string stream is particularly designed for in-situ parsing. 185 | \note implements Stream concept 186 | */ 187 | template 188 | struct GenericInsituStringStream { 189 | typedef typename Encoding::Ch Ch; 190 | 191 | GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} 192 | 193 | // Read 194 | Ch Peek() { return *src_; } 195 | Ch Take() { return *src_++; } 196 | size_t Tell() { return static_cast(src_ - head_); } 197 | 198 | // Write 199 | void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } 200 | 201 | Ch* PutBegin() { return dst_ = src_; } 202 | size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } 203 | void Flush() {} 204 | 205 | Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } 206 | void Pop(size_t count) { dst_ -= count; } 207 | 208 | Ch* src_; 209 | Ch* dst_; 210 | Ch* head_; 211 | }; 212 | 213 | template 214 | struct StreamTraits > { 215 | enum { copyOptimization = 1 }; 216 | }; 217 | 218 | //! Insitu string stream with UTF8 encoding. 219 | typedef GenericInsituStringStream > InsituStringStream; 220 | 221 | RAPIDJSON_NAMESPACE_END 222 | 223 | #endif // RAPIDJSON_STREAM_H_ 224 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidjson/stringbuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_STRINGBUFFER_H_ 16 | #define RAPIDJSON_STRINGBUFFER_H_ 17 | 18 | #include "stream.h" 19 | #include "internal/stack.h" 20 | 21 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 22 | #include // std::move 23 | #endif 24 | 25 | #include "internal/stack.h" 26 | 27 | #if defined(__clang__) 28 | RAPIDJSON_DIAG_PUSH 29 | RAPIDJSON_DIAG_OFF(c++98-compat) 30 | #endif 31 | 32 | RAPIDJSON_NAMESPACE_BEGIN 33 | 34 | //! Represents an in-memory output stream. 35 | /*! 36 | \tparam Encoding Encoding of the stream. 37 | \tparam Allocator type for allocating memory buffer. 38 | \note implements Stream concept 39 | */ 40 | template 41 | class GenericStringBuffer { 42 | public: 43 | typedef typename Encoding::Ch Ch; 44 | 45 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 46 | 47 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 48 | GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} 49 | GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { 50 | if (&rhs != this) 51 | stack_ = std::move(rhs.stack_); 52 | return *this; 53 | } 54 | #endif 55 | 56 | void Put(Ch c) { *stack_.template Push() = c; } 57 | void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } 58 | void Flush() {} 59 | 60 | void Clear() { stack_.Clear(); } 61 | void ShrinkToFit() { 62 | // Push and pop a null terminator. This is safe. 63 | *stack_.template Push() = '\0'; 64 | stack_.ShrinkToFit(); 65 | stack_.template Pop(1); 66 | } 67 | 68 | void Reserve(size_t count) { stack_.template Reserve(count); } 69 | Ch* Push(size_t count) { return stack_.template Push(count); } 70 | Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } 71 | void Pop(size_t count) { stack_.template Pop(count); } 72 | 73 | const Ch* GetString() const { 74 | // Push and pop a null terminator. This is safe. 75 | *stack_.template Push() = '\0'; 76 | stack_.template Pop(1); 77 | 78 | return stack_.template Bottom(); 79 | } 80 | 81 | //! Get the size of string in bytes in the string buffer. 82 | size_t GetSize() const { return stack_.GetSize(); } 83 | 84 | //! Get the length of string in Ch in the string buffer. 85 | size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } 86 | 87 | static const size_t kDefaultCapacity = 256; 88 | mutable internal::Stack stack_; 89 | 90 | private: 91 | // Prohibit copy constructor & assignment operator. 92 | GenericStringBuffer(const GenericStringBuffer&); 93 | GenericStringBuffer& operator=(const GenericStringBuffer&); 94 | }; 95 | 96 | //! String buffer with UTF8 encoding 97 | typedef GenericStringBuffer > StringBuffer; 98 | 99 | template 100 | inline void PutReserve(GenericStringBuffer& stream, size_t count) { 101 | stream.Reserve(count); 102 | } 103 | 104 | template 105 | inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { 106 | stream.PutUnsafe(c); 107 | } 108 | 109 | //! Implement specialized version of PutN() with memset() for better performance. 110 | template<> 111 | inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { 112 | std::memset(stream.stack_.Push(n), c, n * sizeof(c)); 113 | } 114 | 115 | RAPIDJSON_NAMESPACE_END 116 | 117 | #if defined(__clang__) 118 | RAPIDJSON_DIAG_POP 119 | #endif 120 | 121 | #endif // RAPIDJSON_STRINGBUFFER_H_ 122 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidxml/rapidxml_iterators.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDXML_ITERATORS_HPP_INCLUDED 2 | #define RAPIDXML_ITERATORS_HPP_INCLUDED 3 | 4 | // Copyright (C) 2006, 2009 Marcin Kalicinski 5 | // Version 1.13 6 | // Revision $DateTime: 2009/05/13 01:46:17 $ 7 | //! \file rapidxml_iterators.hpp This file contains rapidxml iterators 8 | 9 | #include "rapidxml.hpp" 10 | 11 | namespace rapidxml 12 | { 13 | 14 | //! Iterator of child nodes of xml_node 15 | template 16 | class node_iterator 17 | { 18 | 19 | public: 20 | 21 | typedef typename xml_node value_type; 22 | typedef typename xml_node &reference; 23 | typedef typename xml_node *pointer; 24 | typedef std::ptrdiff_t difference_type; 25 | typedef std::bidirectional_iterator_tag iterator_category; 26 | 27 | node_iterator() 28 | : m_node(0) 29 | { 30 | } 31 | 32 | node_iterator(xml_node *node) 33 | : m_node(node->first_node()) 34 | { 35 | } 36 | 37 | reference operator *() const 38 | { 39 | assert(m_node); 40 | return *m_node; 41 | } 42 | 43 | pointer operator->() const 44 | { 45 | assert(m_node); 46 | return m_node; 47 | } 48 | 49 | node_iterator& operator++() 50 | { 51 | assert(m_node); 52 | m_node = m_node->next_sibling(); 53 | return *this; 54 | } 55 | 56 | node_iterator operator++(int) 57 | { 58 | node_iterator tmp = *this; 59 | ++this; 60 | return tmp; 61 | } 62 | 63 | node_iterator& operator--() 64 | { 65 | assert(m_node && m_node->previous_sibling()); 66 | m_node = m_node->previous_sibling(); 67 | return *this; 68 | } 69 | 70 | node_iterator operator--(int) 71 | { 72 | node_iterator tmp = *this; 73 | ++this; 74 | return tmp; 75 | } 76 | 77 | bool operator ==(const node_iterator &rhs) 78 | { 79 | return m_node == rhs.m_node; 80 | } 81 | 82 | bool operator !=(const node_iterator &rhs) 83 | { 84 | return m_node != rhs.m_node; 85 | } 86 | 87 | private: 88 | 89 | xml_node *m_node; 90 | 91 | }; 92 | 93 | //! Iterator of child attributes of xml_node 94 | template 95 | class attribute_iterator 96 | { 97 | 98 | public: 99 | 100 | typedef typename xml_attribute value_type; 101 | typedef typename xml_attribute &reference; 102 | typedef typename xml_attribute *pointer; 103 | typedef std::ptrdiff_t difference_type; 104 | typedef std::bidirectional_iterator_tag iterator_category; 105 | 106 | attribute_iterator() 107 | : m_attribute(0) 108 | { 109 | } 110 | 111 | attribute_iterator(xml_node *node) 112 | : m_attribute(node->first_attribute()) 113 | { 114 | } 115 | 116 | reference operator *() const 117 | { 118 | assert(m_attribute); 119 | return *m_attribute; 120 | } 121 | 122 | pointer operator->() const 123 | { 124 | assert(m_attribute); 125 | return m_attribute; 126 | } 127 | 128 | attribute_iterator& operator++() 129 | { 130 | assert(m_attribute); 131 | m_attribute = m_attribute->next_attribute(); 132 | return *this; 133 | } 134 | 135 | attribute_iterator operator++(int) 136 | { 137 | attribute_iterator tmp = *this; 138 | ++this; 139 | return tmp; 140 | } 141 | 142 | attribute_iterator& operator--() 143 | { 144 | assert(m_attribute && m_attribute->previous_attribute()); 145 | m_attribute = m_attribute->previous_attribute(); 146 | return *this; 147 | } 148 | 149 | attribute_iterator operator--(int) 150 | { 151 | attribute_iterator tmp = *this; 152 | ++this; 153 | return tmp; 154 | } 155 | 156 | bool operator ==(const attribute_iterator &rhs) 157 | { 158 | return m_attribute == rhs.m_attribute; 159 | } 160 | 161 | bool operator !=(const attribute_iterator &rhs) 162 | { 163 | return m_attribute != rhs.m_attribute; 164 | } 165 | 166 | private: 167 | 168 | xml_attribute *m_attribute; 169 | 170 | }; 171 | 172 | } 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /include/serialization/detail/rapidxml/rapidxml_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDXML_UTILS_HPP_INCLUDED 2 | #define RAPIDXML_UTILS_HPP_INCLUDED 3 | 4 | // Copyright (C) 2006, 2009 Marcin Kalicinski 5 | // Version 1.13 6 | // Revision $DateTime: 2009/05/13 01:46:17 $ 7 | //! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful 8 | //! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. 9 | 10 | #include "rapidxml.hpp" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace rapidxml 17 | { 18 | 19 | //! Represents data loaded from a file 20 | template 21 | class file 22 | { 23 | 24 | public: 25 | 26 | //! Loads file into the memory. Data will be automatically destroyed by the destructor. 27 | //! \param filename Filename to load. 28 | file(const char *filename) 29 | { 30 | using namespace std; 31 | 32 | // Open stream 33 | basic_ifstream stream(filename, ios::binary); 34 | if (!stream) 35 | throw runtime_error(string("cannot open file ") + filename); 36 | stream.unsetf(ios::skipws); 37 | 38 | // Determine stream size 39 | stream.seekg(0, ios::end); 40 | size_t size = stream.tellg(); 41 | stream.seekg(0); 42 | 43 | // Load data and add terminating 0 44 | m_data.resize(size + 1); 45 | stream.read(&m_data.front(), static_cast(size)); 46 | m_data[size] = 0; 47 | } 48 | 49 | //! Loads file into the memory. Data will be automatically destroyed by the destructor 50 | //! \param stream Stream to load from 51 | file(std::basic_istream &stream) 52 | { 53 | using namespace std; 54 | 55 | // Load data and add terminating 0 56 | stream.unsetf(ios::skipws); 57 | m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); 58 | if (stream.fail() || stream.bad()) 59 | throw runtime_error("error reading stream"); 60 | m_data.push_back(0); 61 | } 62 | 63 | //! Gets file data. 64 | //! \return Pointer to data of file. 65 | Ch *data() 66 | { 67 | return &m_data.front(); 68 | } 69 | 70 | //! Gets file data. 71 | //! \return Pointer to data of file. 72 | const Ch *data() const 73 | { 74 | return &m_data.front(); 75 | } 76 | 77 | //! Gets file data size. 78 | //! \return Size of file data, in characters. 79 | std::size_t size() const 80 | { 81 | return m_data.size(); 82 | } 83 | 84 | private: 85 | 86 | std::vector m_data; // File data 87 | 88 | }; 89 | 90 | //! Counts children of node. Time complexity is O(n). 91 | //! \return Number of children of node 92 | template 93 | inline std::size_t count_children(xml_node *node) 94 | { 95 | xml_node *child = node->first_node(); 96 | std::size_t count = 0; 97 | while (child) 98 | { 99 | ++count; 100 | child = child->next_sibling(); 101 | } 102 | return count; 103 | } 104 | 105 | //! Counts attributes of node. Time complexity is O(n). 106 | //! \return Number of attributes of node 107 | template 108 | inline std::size_t count_attributes(xml_node *node) 109 | { 110 | xml_attribute *attr = node->first_attribute(); 111 | std::size_t count = 0; 112 | while (attr) 113 | { 114 | ++count; 115 | attr = attr->next_attribute(); 116 | } 117 | return count; 118 | } 119 | 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /include/serialization/detail/serialization_error.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace serialization 7 | { 8 | 9 | class serialization_error: public std::exception 10 | { 11 | 12 | public: 13 | serialization_error(const char *what, const char *where) 14 | : m_what(what) 15 | , m_where(where) 16 | { 17 | } 18 | 19 | const char *what() const throw() 20 | { 21 | return m_what; 22 | } 23 | 24 | const char *where() const 25 | { 26 | return m_where; 27 | } 28 | 29 | private: 30 | const char *m_what; 31 | const char *m_where; 32 | }; 33 | 34 | inline void throw_serialization_error(const char * where, const char * what) 35 | { 36 | throw serialization_error(what, where); 37 | } 38 | 39 | } // namespace serialization 40 | -------------------------------------------------------------------------------- /include/serialization/detail/serialization_helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "config.h" 7 | #include "serialization_error.h" 8 | 9 | namespace serialization 10 | { 11 | 12 | namespace detail 13 | { 14 | 15 | template 16 | inline auto serialize_helper(Archive & ar, const Object & obj, int) -> decltype(obj.serialize_impl(ar), void()) 17 | { 18 | serialization_trace trace(__func__, __FILE__, __LINE__); 19 | ar.save_object_start(); 20 | obj.serialize_impl(ar); 21 | ar.save_object_end(); 22 | } 23 | 24 | template 25 | inline auto serialize_helper(Archive & ar, const Object & obj, long) -> decltype(void()) 26 | { 27 | serialization_trace trace(__func__, __FILE__, __LINE__); 28 | ar.save(obj); 29 | } 30 | 31 | template 32 | inline auto unserialize_helper(const Archive & ar, Object & obj, int) -> decltype(obj.unserialize_impl(ar), void()) 33 | { 34 | serialization_trace trace(__func__, __FILE__, __LINE__); 35 | ar.load_object_start(); 36 | obj.unserialize_impl(ar); 37 | ar.load_object_end(); 38 | } 39 | 40 | template 41 | inline auto unserialize_helper(const Archive & ar, Object & obj, long) -> decltype(void()) 42 | { 43 | serialization_trace trace(__func__, __FILE__, __LINE__); 44 | ar.load(obj); 45 | } 46 | 47 | } // namespace detail 48 | 49 | template 50 | inline void serialize_helper(Archive & ar, const Object & obj) 51 | { 52 | serialization_trace trace(__func__, __FILE__, __LINE__); 53 | detail::serialize_helper(ar, obj, 0); 54 | } 55 | 56 | template 57 | inline void unserialize_helper(const Archive & ar, Object & obj) 58 | { 59 | serialization_trace trace(__func__, __FILE__, __LINE__); 60 | detail::unserialize_helper(ar, obj, 0); 61 | } 62 | 63 | 64 | // for container 65 | 66 | template 67 | inline void serialize_container_helper(Archive & ar, const T & v) 68 | { 69 | serialization_trace trace(__func__, __FILE__, __LINE__); 70 | 71 | ar.save_sequence_start(v.size()); 72 | for(const auto & i : v) 73 | { 74 | ar.save_sequence_item_start(); 75 | serialize_helper(ar, i); 76 | ar.save_sequence_item_end(); 77 | } 78 | ar.save_sequence_end(); 79 | } 80 | 81 | //pair 82 | template 83 | inline void serialize_helper(Archive & ar, const std::pair & in) 84 | { 85 | serialization_trace trace(__func__, __FILE__, __LINE__); 86 | ar.save_object_start(); 87 | 88 | ar.save_key_start("first"); 89 | serialize_helper(ar, in.first); 90 | ar.save_key_end("first"); 91 | 92 | ar.save_key_start("second"); 93 | serialize_helper(ar, in.second); 94 | ar.save_key_end("first"); 95 | 96 | ar.save_object_end(); 97 | } 98 | 99 | //list 100 | template 101 | inline void serialize_helper(Archive & ar, const std::list & v) 102 | { 103 | serialization_trace trace(__func__, __FILE__, __LINE__); 104 | serialize_container_helper(ar, v); 105 | } 106 | 107 | //vector 108 | template 109 | inline void serialize_helper(Archive & ar, const std::vector & v) 110 | { 111 | serialization_trace trace(__func__, __FILE__, __LINE__); 112 | serialize_container_helper(ar, v); 113 | } 114 | 115 | //array 116 | template 117 | inline void serialize_helper(Archive & ar, const T(&v)[N]) 118 | { 119 | serialization_trace trace(__func__, __FILE__, __LINE__); 120 | serialize_container_helper(ar, v); 121 | } 122 | 123 | //map 124 | template 125 | inline void serialize_helper(Archive & ar, const std::map & v) 126 | { 127 | serialization_trace trace(__func__, __FILE__, __LINE__); 128 | serialize_container_helper(ar, v); 129 | } 130 | 131 | //pair 132 | template 133 | inline void unserialize_helper(const Archive & ar, std::pair & v) 134 | { 135 | serialization_trace trace(__func__, __FILE__, __LINE__); 136 | ar.load_object_start(); 137 | 138 | ar.load_key_start("first"); 139 | unserialize_helper(ar, v.first); 140 | ar.load_key_end("first"); 141 | 142 | ar.load_key_start("second"); 143 | unserialize_helper(ar, v.second); 144 | ar.load_key_end("second"); 145 | 146 | ar.load_object_end(); 147 | } 148 | 149 | //list 150 | template 151 | inline void unserialize_helper(const Archive & ar, std::list & v) 152 | { 153 | serialization_trace trace(__func__, __FILE__, __LINE__); 154 | 155 | for(size_type i = 0; ar.load_sequence_start(i); ++i) 156 | { 157 | T tmp; 158 | unserialize_helper(ar, tmp); 159 | v.push_back(std::move(tmp)); 160 | ar.load_sequence_end(); 161 | } 162 | } 163 | 164 | //vector 165 | template 166 | inline void unserialize_helper(const Archive & ar, std::vector & v) 167 | { 168 | serialization_trace trace(__func__, __FILE__, __LINE__); 169 | 170 | auto size = ar.load_sequence_start(); 171 | v.reserve(size); 172 | for(size_type i = 0; i < size; ++i) 173 | { 174 | ar.load_sequence_item_start(i); 175 | T tmp; 176 | unserialize_helper(ar, tmp); 177 | v.push_back(std::move(tmp)); 178 | ar.load_sequence_item_end(); 179 | } 180 | 181 | ar.load_sequence_end(); 182 | } 183 | 184 | //array 185 | template 186 | inline void unserialize_helper(const Archive & ar, T (&v)[N]) 187 | { 188 | serialization_trace trace(__func__, __FILE__, __LINE__); 189 | 190 | auto size = ar.load_sequence_start(); 191 | if(size != N) 192 | throw_serialization_error("array", "size error"); 193 | 194 | for(size_type i = 0; i < size; ++i) 195 | { 196 | ar.load_sequence_item_start(i); 197 | unserialize_helper(ar, v[i]); 198 | ar.load_sequence_item_end(); 199 | } 200 | ar.load_sequence_end(); 201 | } 202 | 203 | //map 204 | template 205 | inline void unserialize_helper(const Archive & ar, std::map & v) 206 | { 207 | serialization_trace trace(__func__, __FILE__, __LINE__); 208 | 209 | auto size = ar.load_sequence_start(); 210 | for(size_type i = 0; i < size; ++i) 211 | { 212 | ar.load_sequence_item_start(i); 213 | typename std::pair tmp; 214 | unserialize_helper(ar, tmp); 215 | *std::insert_iterator>(v, v.end()) = std::move(tmp); 216 | ar.load_sequence_item_end(); 217 | } 218 | ar.load_sequence_end(); 219 | } 220 | 221 | } // namespace serialization 222 | -------------------------------------------------------------------------------- /include/serialization/detail/serialization_unpack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serialization_helper.h" 4 | 5 | #if __cplusplus > 201402L 6 | #include 7 | #endif 8 | 9 | namespace serialization 10 | { 11 | 12 | template 13 | inline void serialize_unpack(Argument && arg, Archive& ar) 14 | { 15 | serialization_trace trace(__func__, __FILE__, __LINE__); 16 | } 17 | 18 | template 19 | inline void serialize_unpack(Argument && arg, Archive & ar, T && front, Args && ... next) 20 | { 21 | serialization_trace trace(__func__, __FILE__, __LINE__); 22 | 23 | auto key = *arg; 24 | ar.save_key_start(key); 25 | serialize_helper(ar, front); 26 | ar.save_key_end(key); 27 | 28 | serialize_unpack(++arg, ar, std::forward(next)...); 29 | } 30 | 31 | #if __cplusplus > 201402L 32 | // optional 33 | template 34 | inline void serialize_unpack(Argument && arg, Archive & ar, const std::optional & front, Args && ... next) 35 | { 36 | serialization_trace trace(__func__, __FILE__, __LINE__); 37 | if(front) 38 | { 39 | auto key = *arg; 40 | ar.save_key_start(key); 41 | serialize_helper(ar, *front); 42 | ar.save_key_end(key); 43 | } 44 | serialize_unpack(++arg, ar, std::forward(next)...); 45 | } 46 | #endif 47 | 48 | template 49 | inline void unserialize_unpack(Argument && arg, const Archive& ar) 50 | { 51 | serialization_trace trace(__func__, __FILE__, __LINE__); 52 | } 53 | 54 | template 55 | inline void unserialize_unpack(Argument && arg, const Archive & ar, T && front, Args&& ... next) 56 | { 57 | serialization_trace trace(__func__, __FILE__, __LINE__); 58 | 59 | auto key = *arg; 60 | ar.load_key_start(key); 61 | unserialize_helper(ar, front); 62 | ar.load_key_end(key); 63 | 64 | unserialize_unpack(++arg, ar, std::forward(next)...); 65 | } 66 | 67 | #if __cplusplus > 201402L 68 | // optional 69 | template 70 | inline void unserialize_unpack(Argument && arg, const Archive & ar, std::optional & front, Args&& ... next) 71 | { 72 | serialization_trace trace(__func__, __FILE__, __LINE__); 73 | 74 | auto key = *arg; 75 | 76 | if(ar.load_key_start_optional(key)) 77 | { 78 | T tmp; 79 | unserialize_helper(ar, tmp); 80 | front.emplace(std::move(tmp)); 81 | ar.load_key_end(key); 82 | } 83 | 84 | unserialize_unpack(++arg, ar, std::forward(next)...); 85 | } 86 | #endif 87 | 88 | } //namespace serialization 89 | 90 | -------------------------------------------------------------------------------- /include/serialization/detail/xml_iarchive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace serialization 13 | { 14 | 15 | class xml_iarchive 16 | { 17 | public: 18 | xml_iarchive() 19 | { 20 | } 21 | 22 | void load_data(char * data) 23 | { 24 | document_.clear(); 25 | try 26 | { 27 | document_.parse<0>(data); 28 | } 29 | catch(const rapidxml::parse_error & e) 30 | { 31 | throw_serialization_error("xml parse", e.what()); 32 | } 33 | } 34 | 35 | void load_key_start(const char * key) const 36 | { 37 | serialization_trace trace(__func__, key); 38 | 39 | auto node = stack_.top()->first_node(key); 40 | if(node == nullptr) 41 | throw_serialization_error("expect key", key); 42 | stack_.push(node); 43 | } 44 | 45 | bool load_key_start_optional(const char * key) const 46 | { 47 | serialization_trace trace(__func__, key); 48 | 49 | auto node = stack_.top()->first_node(key); 50 | if(node == nullptr) 51 | { 52 | return false; 53 | } 54 | stack_.push(node); 55 | return true; 56 | } 57 | 58 | void load_key_end(const char * key) const 59 | { 60 | serialization_trace trace(__func__, key); 61 | stack_.pop(); 62 | } 63 | 64 | void load_object_start() const 65 | { 66 | } 67 | 68 | void load_object_end() const 69 | { 70 | } 71 | 72 | size_type load_sequence_start() const 73 | { 74 | serialization_trace trace(__func__, "xml"); 75 | auto node = stack_.top()->first_node("sequence"); 76 | if(node == nullptr) 77 | { 78 | throw_serialization_error(__func__, "expect sequence"); 79 | } 80 | auto attr = node->first_attribute("size"); 81 | if(attr == nullptr) 82 | { 83 | throw_serialization_error(__func__, "expect sequence size"); 84 | } 85 | 86 | char *end = attr->value(); 87 | size_type size = std::strtoull(attr->value(), &end, 10); 88 | if(end - attr->value() != attr->value_size()) 89 | { 90 | throw_serialization_error(__func__, "bad sequence size"); 91 | } 92 | 93 | stack_.push(node); 94 | node = (size == 0 ? nullptr : stack_.top()->first_node("item")); 95 | stack_.push(node); 96 | 97 | return size; 98 | } 99 | 100 | void load_sequence_end() const 101 | { 102 | serialization_trace trace(__func__, "xml"); 103 | stack_.pop(); 104 | stack_.pop(); 105 | } 106 | 107 | bool load_sequence_item_start(size_type i) const 108 | { 109 | serialization_trace trace(__func__, "xml"); 110 | 111 | if(stack_.top() == nullptr) 112 | { 113 | throw_serialization_error("load sequence item", "xml"); 114 | } 115 | return true; 116 | } 117 | 118 | void load_sequence_item_end() const 119 | { 120 | serialization_trace trace(__func__, "json"); 121 | stack_.top() = stack_.top()->next_sibling("item"); 122 | } 123 | 124 | template 125 | void load(T & v) const 126 | { 127 | std::stringstream ss; 128 | ss << stack_.top()->value(); 129 | ss >> v; 130 | if(!ss.eof()) 131 | { 132 | throw_serialization_error("load ", "xml"); 133 | } 134 | } 135 | 136 | void load(std::string & v) const 137 | { 138 | v = stack_.top()->value(); 139 | } 140 | 141 | void load(bool & v) const 142 | { 143 | if(std::strcmp(stack_.top()->value(), "true")) 144 | { 145 | v = true; 146 | } 147 | else if(std::strcmp(stack_.top()->value(), "false")) 148 | { 149 | v = false; 150 | } 151 | throw_serialization_error("load ", "xml"); 152 | } 153 | 154 | void unserialize_start() const 155 | { 156 | serialization_trace trace(__func__, "xml"); 157 | stack_ = std::stack *> {}; 158 | auto node = document_.first_node("serialization"); 159 | if(node == nullptr) 160 | throw_serialization_error("serilization root", "xml"); 161 | stack_.push(node); 162 | } 163 | 164 | void unserialize_end() const 165 | { 166 | serialization_trace trace(__func__, "xml"); 167 | } 168 | 169 | private: 170 | rapidxml::xml_document<> document_; 171 | 172 | mutable std::stack * > stack_; 173 | }; 174 | 175 | } // namespace serialization 176 | -------------------------------------------------------------------------------- /include/serialization/detail/xml_oarchive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace serialization 11 | { 12 | 13 | class xml_oarchive 14 | { 15 | public: 16 | xml_oarchive() 17 | { 18 | } 19 | 20 | const char * data() const 21 | { 22 | return str_.data(); 23 | } 24 | 25 | std::size_t size() const 26 | { 27 | return str_.size(); 28 | } 29 | 30 | void save_key_start(const char * key) 31 | { 32 | serialization_trace trace(__func__, key); 33 | auto node = document_.allocate_node(rapidxml::node_element, key); 34 | current_->append_node(node); 35 | current_ = node; 36 | } 37 | 38 | void save_key_end(const char * key) 39 | { 40 | serialization_trace trace(__func__, key); 41 | current_ = current_->parent(); 42 | } 43 | 44 | void save_object_start() 45 | { 46 | } 47 | 48 | void save_object_end() 49 | { 50 | } 51 | 52 | void save_sequence_start(size_type size) 53 | { 54 | serialization_trace trace(__func__, "xml"); 55 | auto node = document_.allocate_node(rapidxml::node_element, "sequence"); 56 | auto attr = document_.allocate_attribute("size", document_.allocate_string(std::to_string(size).c_str())); 57 | node->append_attribute(attr); 58 | current_->append_node(node); 59 | current_ = node; 60 | } 61 | 62 | void save_sequence_end() 63 | { 64 | serialization_trace trace(__func__, "xml"); 65 | current_ = current_->parent(); 66 | } 67 | 68 | void save_sequence_item_start() 69 | { 70 | serialization_trace trace(__func__, "xml"); 71 | auto node = document_.allocate_node(rapidxml::node_element, "item"); 72 | current_->append_node(node); 73 | current_ = node; 74 | } 75 | 76 | void save_sequence_item_end() 77 | { 78 | serialization_trace trace(__func__, "xml"); 79 | current_ = current_->parent(); 80 | } 81 | 82 | void save(int v) 83 | { 84 | char buffer[64]; 85 | const char* end = rapidjson::internal::i64toa(v, buffer); 86 | current_->value(document_.allocate_string(buffer, end - buffer), end - buffer); 87 | } 88 | 89 | void save(uint v) 90 | { 91 | char buffer[64]; 92 | const char* end = rapidjson::internal::u64toa(v, buffer); 93 | current_->value(document_.allocate_string(buffer, end - buffer), end - buffer); 94 | } 95 | 96 | void save(int64_t v) 97 | { 98 | char buffer[64]; 99 | const char* end = rapidjson::internal::i64toa(v, buffer); 100 | current_->value(document_.allocate_string(buffer, end - buffer), end - buffer); 101 | } 102 | 103 | void save(uint64_t v) 104 | { 105 | char buffer[64]; 106 | const char* end = rapidjson::internal::u64toa(v, buffer); 107 | current_->value(document_.allocate_string(buffer, end - buffer), end - buffer); 108 | } 109 | 110 | void save(double v) 111 | { 112 | char buffer[64]; 113 | const char* end = rapidjson::internal::dtoa(v, buffer); 114 | current_->value(document_.allocate_string(buffer, end - buffer), end - buffer); 115 | } 116 | 117 | void save(const std::string & v) 118 | { 119 | current_->value(v.c_str(), v.size()); 120 | } 121 | 122 | void save(bool v) 123 | { 124 | if(v) 125 | { 126 | current_->value("true"); 127 | } 128 | else 129 | { 130 | current_->value("false"); 131 | } 132 | } 133 | 134 | void serialize_start() 135 | { 136 | serialization_trace trace(__func__, "xml"); 137 | document_.clear(); 138 | current_ = document_.allocate_node(rapidxml::node_element, "serialization"); 139 | document_.append_node(current_); 140 | str_.clear(); 141 | } 142 | 143 | void serialize_end() 144 | { 145 | serialization_trace trace(__func__, "xml"); 146 | rapidxml::print(std::back_inserter(str_), document_, rapidxml::print_no_indenting); 147 | } 148 | 149 | private: 150 | rapidxml::xml_document<> document_; 151 | 152 | rapidxml::xml_node<> *current_; 153 | 154 | std::string str_; 155 | }; 156 | 157 | } // namespace serialization 158 | -------------------------------------------------------------------------------- /include/serialization/serialization.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define SERIALIZATION_DEFINE_META_FUNC(...) \ 15 | template \ 16 | void serialize_impl(Archive & ar) const \ 17 | { \ 18 | serialization::serialization_trace trace(__func__, __FILE__, __LINE__); \ 19 | static_assert(std::tuple_size::type >::value == std::tuple_size::value , "serialization meta data size error"); \ 20 | serialization::serialize_unpack(serialization_meta().begin(), ar, ##__VA_ARGS__); \ 21 | } \ 22 | \ 23 | template \ 24 | void unserialize_impl(const Archive & ar) \ 25 | { \ 26 | serialization::serialization_trace trace(__func__, __FILE__, __LINE__); \ 27 | static_assert(std::tuple_size::type >::value == std::tuple_size::value , "serialization meta data size error"); \ 28 | serialization::unserialize_unpack(serialization_meta().begin(), ar, ##__VA_ARGS__);\ 29 | } 30 | 31 | #define SERIALIZATION_DEFINE(...) \ 32 | SERIALIZATION_DEFINE_META_DATA_HELPER(__VA_ARGS__) \ 33 | SERIALIZATION_DEFINE_META_FUNC(__VA_ARGS__) 34 | 35 | namespace serialization 36 | { 37 | 38 | template 39 | void serialize(Archive & ar, const Value & v) 40 | { 41 | ar.serialize_start(); 42 | serialization::serialize_helper(ar, v); 43 | ar.serialize_end(); 44 | } 45 | 46 | template 47 | void unserialize(const Archive & ar, Value & v) 48 | { 49 | ar.unserialize_start(); 50 | serialization::unserialize_helper(ar, v); 51 | ar.unserialize_end(); 52 | } 53 | 54 | } // namespace serialization 55 | 56 | -------------------------------------------------------------------------------- /serialization2.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avplayer/serialization2/313e28dae72ea37cd09bda889aee01579f7888fc/serialization2.dia -------------------------------------------------------------------------------- /serialization2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avplayer/serialization2/313e28dae72ea37cd09bda889aee01579f7888fc/serialization2.png -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | project(unittest) 4 | 5 | find_package(GTest REQUIRED) 6 | 7 | include_directories(../include 8 | ${GTEST_INCLUDE_DIRS} 9 | ) 10 | 11 | set(UNITTEST_SOURCES 12 | jsontest.cpp 13 | xmltest.cpp 14 | unittest.cpp 15 | ) 16 | 17 | add_executable(unittest 18 | ${UNITTEST_SOURCES} 19 | ) 20 | 21 | target_link_libraries(unittest ${GTEST_BOTH_LIBRARIES} ) 22 | 23 | add_test(NAME unittest 24 | COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest 25 | WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} 26 | ) 27 | 28 | -------------------------------------------------------------------------------- /test/jsontest.cpp: -------------------------------------------------------------------------------- 1 | #include "unittest.h" 2 | 3 | #include 4 | #include 5 | 6 | struct TestInt 7 | { 8 | int value; 9 | bool operator==(const TestInt & other) const { return value == other.value; } 10 | SERIALIZATION_DEFINE(value); 11 | }; 12 | 13 | struct TestUint 14 | { 15 | uint value; 16 | bool operator==(const TestUint & other) const { return value == other.value; } 17 | SERIALIZATION_DEFINE(value); 18 | }; 19 | 20 | struct TestInt32 21 | { 22 | int32_t value; 23 | bool operator==(const TestInt32 & other) const { return value == other.value; } 24 | SERIALIZATION_DEFINE(value); 25 | }; 26 | 27 | struct TestUint32 28 | { 29 | uint32_t value; 30 | bool operator==(const TestUint32 & other) const { return value == other.value; } 31 | SERIALIZATION_DEFINE(value); 32 | }; 33 | 34 | struct TestInt64 35 | { 36 | int64_t value; 37 | bool operator==(const TestInt64 & other) const { return value == other.value; } 38 | SERIALIZATION_DEFINE(value); 39 | }; 40 | 41 | struct TestUint64 42 | { 43 | uint64_t value; 44 | bool operator==(const TestUint64 & other) const { return value == other.value; } 45 | SERIALIZATION_DEFINE(value); 46 | }; 47 | 48 | struct TestDouble 49 | { 50 | double value; 51 | SERIALIZATION_DEFINE(value); 52 | }; 53 | 54 | struct TestString 55 | { 56 | std::string value; 57 | bool operator==(const TestString & other) const { return value == other.value; } 58 | SERIALIZATION_DEFINE(value); 59 | }; 60 | 61 | template 62 | void check_serialize(const T & v) 63 | { 64 | T v2; 65 | try 66 | { 67 | // serialize 68 | serialization::json_oarchive oa; 69 | serialization::serialize(oa, v); 70 | 71 | // unserialize 72 | serialization::json_iarchive ia; 73 | ia.load_data(oa.data()); 74 | serialization::unserialize(ia, v2); 75 | } 76 | catch (serialization::serialization_error & err) 77 | { 78 | std::cout << "serialization error: " << err.where() << ":" << err.what() << std::endl; 79 | } 80 | 81 | EXPECT_EQ(v, v2); 82 | } 83 | 84 | template 85 | void check_unserialize(const char * str) 86 | { 87 | T v; 88 | serialization::json_oarchive oa; 89 | try 90 | { 91 | // unserialize 92 | serialization::json_iarchive ia; 93 | ia.load_data(str); 94 | serialization::unserialize(ia, v); 95 | 96 | // serialize 97 | serialization::serialize(oa, v); 98 | } 99 | catch (serialization::serialization_error & err) 100 | { 101 | std::cout << "serialization error: " << err.where() << ":" << err.what() << std::endl; 102 | } 103 | 104 | EXPECT_STREQ(str, oa.data()); 105 | } 106 | 107 | template 108 | void test_integer() 109 | { 110 | typedef decltype(T::value) int_type; 111 | int_type gap = std::numeric_limits::max()/int_type{997}; 112 | for(int_type i = std::numeric_limits::min(); i < std::numeric_limits::max() - gap; i += gap) 113 | { 114 | if(i > std::numeric_limits::max() - gap) 115 | i = std::numeric_limits::max(); 116 | 117 | T a{i}; 118 | //std::cout << i << ","; 119 | check_serialize(a); 120 | } 121 | //std::cout << std::endl; 122 | } 123 | 124 | TEST(test_json, test_int) 125 | { 126 | test_integer(); 127 | } 128 | 129 | TEST(test_json, test_uint) 130 | { 131 | test_integer(); 132 | } 133 | 134 | TEST(test_json, test_int32) 135 | { 136 | test_integer(); 137 | } 138 | 139 | TEST(test_json, test_uint32) 140 | { 141 | test_integer(); 142 | } 143 | 144 | TEST(test_json, test_int64) 145 | { 146 | test_integer(); 147 | } 148 | 149 | TEST(test_json, test_uint64) 150 | { 151 | test_integer(); 152 | } 153 | 154 | TEST(test_json, test_double) 155 | { 156 | TestDouble a,b; 157 | // int can convert to double 158 | TestInt c; 159 | double values[10] = { 0, 2, 16, -4, 1.2, 4.3, 5.555, 6.3333, 1.3333333, -1212.122132111}; 160 | for(int i = 0; i < 10; ++i) 161 | { 162 | try 163 | { 164 | // serialize 165 | serialization::json_oarchive oa; 166 | if(i < 4) 167 | { 168 | c.value = values[i]; 169 | serialization::serialize(oa, c); 170 | } 171 | else 172 | { 173 | a.value = values[i]; 174 | serialization::serialize(oa, a); 175 | } 176 | // unserialize 177 | serialization::json_iarchive ia; 178 | //std::cout << oa.data() << std::endl; 179 | ia.load_data(oa.data()); 180 | serialization::unserialize(ia, b); 181 | } 182 | catch (serialization::serialization_error & err) 183 | { 184 | std::cout << "serialization error: " << err.where() << ":" << err.what() << std::endl; 185 | } 186 | 187 | if(i < 4) 188 | { 189 | EXPECT_NEAR(c.value, b.value, 0.0); 190 | } 191 | else 192 | { 193 | EXPECT_NEAR(a.value, b.value, 0.0); 194 | } 195 | } 196 | } 197 | 198 | TEST(test_json, test_string) 199 | { 200 | TestString a,b; 201 | const char * values[] = { "", "asadasdas\"", R"(!@#$%&^*&*_++_**&^%$%#@#!~!{}:"?>> 4 | 5 | -------------------------------------------------------------------------------- /test/xmltest.cpp: -------------------------------------------------------------------------------- 1 | #include "unittest.h" 2 | 3 | #include 4 | #include 5 | 6 | struct TestInt 7 | { 8 | int value; 9 | bool operator==(const TestInt & other) const { return value == other.value; } 10 | SERIALIZATION_DEFINE(value); 11 | }; 12 | 13 | struct TestUint 14 | { 15 | uint value; 16 | bool operator==(const TestUint & other) const { return value == other.value; } 17 | SERIALIZATION_DEFINE(value); 18 | }; 19 | 20 | struct TestInt32 21 | { 22 | int32_t value; 23 | bool operator==(const TestInt32 & other) const { return value == other.value; } 24 | SERIALIZATION_DEFINE(value); 25 | }; 26 | 27 | struct TestUint32 28 | { 29 | uint32_t value; 30 | bool operator==(const TestUint32 & other) const { return value == other.value; } 31 | SERIALIZATION_DEFINE(value); 32 | }; 33 | 34 | struct TestInt64 35 | { 36 | int64_t value; 37 | bool operator==(const TestInt64 & other) const { return value == other.value; } 38 | SERIALIZATION_DEFINE(value); 39 | }; 40 | 41 | struct TestUint64 42 | { 43 | uint64_t value; 44 | bool operator==(const TestUint64 & other) const { return value == other.value; } 45 | SERIALIZATION_DEFINE(value); 46 | }; 47 | 48 | struct TestDouble 49 | { 50 | double value; 51 | SERIALIZATION_DEFINE(value); 52 | }; 53 | 54 | struct TestString 55 | { 56 | std::string value; 57 | bool operator==(const TestString & other) const { return value == other.value; } 58 | SERIALIZATION_DEFINE(value); 59 | }; 60 | 61 | template 62 | void check_serialize(const T & v) 63 | { 64 | T v2; 65 | try 66 | { 67 | // serialize 68 | serialization::xml_oarchive oa; 69 | serialization::serialize(oa, v); 70 | 71 | // unserialize 72 | std::string str = oa.data(); 73 | serialization::xml_iarchive ia; 74 | ia.load_data(&str[0]); 75 | serialization::unserialize(ia, v2); 76 | } 77 | catch (serialization::serialization_error & err) 78 | { 79 | std::cout << "serialization error: " << err.where() << ":" << err.what() << std::endl; 80 | } 81 | 82 | EXPECT_EQ(v, v2); 83 | } 84 | 85 | template 86 | void test_integer() 87 | { 88 | typedef decltype(T::value) int_type; 89 | int_type gap = std::numeric_limits::max()/int_type{997}; 90 | for(int_type i = std::numeric_limits::min(); i < std::numeric_limits::max() - gap; i += gap) 91 | { 92 | if(i > std::numeric_limits::max() - gap) 93 | i = std::numeric_limits::max(); 94 | 95 | T a{i}; 96 | //std::cout << i << ","; 97 | check_serialize(a); 98 | } 99 | //std::cout << std::endl; 100 | } 101 | 102 | TEST(test_xml, test_int) 103 | { 104 | test_integer(); 105 | } 106 | 107 | TEST(test_xml, test_uint) 108 | { 109 | test_integer(); 110 | } 111 | 112 | TEST(test_xml, test_int32) 113 | { 114 | test_integer(); 115 | } 116 | 117 | TEST(test_xml, test_uint32) 118 | { 119 | test_integer(); 120 | } 121 | 122 | TEST(test_xml, test_int64) 123 | { 124 | test_integer(); 125 | } 126 | 127 | TEST(test_xml, test_uint64) 128 | { 129 | test_integer(); 130 | } 131 | 132 | TEST(test_xml, test_double) 133 | { 134 | TestDouble a,b; 135 | // int can convert to double 136 | TestInt c; 137 | double values[10] = { 0, 2, 16, -4, 1.2, 4.3, 5.555, 6.3333, 1.3333333, -1212.122132111}; 138 | for(int i = 0; i < 10; ++i) 139 | { 140 | try 141 | { 142 | // serialize 143 | serialization::xml_oarchive oa; 144 | if(i < 4) 145 | { 146 | c.value = values[i]; 147 | serialization::serialize(oa, c); 148 | } 149 | else 150 | { 151 | a.value = values[i]; 152 | serialization::serialize(oa, a); 153 | } 154 | // unserialize 155 | serialization::xml_iarchive ia; 156 | std::string str = oa.data(); 157 | //std::cout << oa.data() << std::endl; 158 | ia.load_data(&str[0]); 159 | serialization::unserialize(ia, b); 160 | } 161 | catch (serialization::serialization_error & err) 162 | { 163 | std::cout << "serialization error: " << err.where() << ":" << err.what() << std::endl; 164 | } 165 | 166 | if(i < 4) 167 | { 168 | EXPECT_NEAR(c.value, b.value, 0.0); 169 | } 170 | else 171 | { 172 | EXPECT_NEAR(a.value, b.value, 0.0); 173 | } 174 | } 175 | } 176 | 177 | TEST(test_xml, test_string) 178 | { 179 | TestString a,b; 180 | const char * values[] = { "", "asadasdas\"", R"(!@#$%&^*&*_++_**&^%$%#@#!~!{}:"?>>