├── .gitattributes
├── .github
└── workflows
│ └── build-cmake.yml
├── .gitignore
├── .gitmodules
├── .idea
└── cmake.xml
├── CMakeLists.txt
├── Header
└── 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
│ ├── clzll.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
│ ├── uri.h
│ └── writer.h
├── README.md
├── README_zh-cn.md
├── fetchSDK.cmd
├── license
├── prepare_libraries.cmd
└── src
├── AntiToolbox.cpp
├── Resource.rc
├── Version.h
├── base64.cpp
├── base64.h
├── dllmain.cpp
├── framework.h
└── resource.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/workflows/build-cmake.yml:
--------------------------------------------------------------------------------
1 | name: Build(CMake)
2 |
3 | on: [push, pull_request]
4 |
5 | env:
6 | PLUGIN_NAME: AntiToolbox
7 | VERSION_FILE_PATH: src/Version.h
8 | BUILD_CONFIGURATION: Release
9 | BUILD_TYPE: Release
10 | SDK_DIR: ./SDK
11 | BDS_VERSION: 1.20.0.01
12 |
13 | jobs:
14 | build:
15 | runs-on: windows-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 | with:
20 | fetch-depth: 0
21 | submodules: 'true'
22 |
23 | # - name: Get information from Version.h file (TODO)
24 | # working-directory: ${{env.GITHUB_WORKSPACE}}
25 | # id: ver
26 | # run: |
27 | # pwd
28 | # shell: bash
29 |
30 | - name: Download Server
31 | working-directory: ${{env.GITHUB_WORKSPACE}}
32 | run: |
33 | mkdir -p ${{ env.SDK_DIR }}/tools/Server
34 | # ServerLink=$(cat 'Scripts/LINK.txt')
35 | ServerLink=https://minecraft.azureedge.net/bin-win/bedrock-server-${{ env.BDS_VERSION }}.zip
36 | curl -L -o ${{ env.SDK_DIR }}/tools/Server/server.zip "$ServerLink"
37 | unzip ${{ env.SDK_DIR }}/tools/Server/server.zip -d ${{ env.SDK_DIR }}/tools/Server/ > /dev/null
38 | shell: bash
39 |
40 | - name: Build Library
41 | working-directory: ${{env.GITHUB_WORKSPACE}}
42 | run: |
43 | cd ${{ env.SDK_DIR }}\tools
44 | PeEditor.exe -l --pdb Server\bedrock_server.pdb -o ..\lib
45 | shell: cmd
46 |
47 | - name: Change PLUGIN_VERSION_STATUS_BETA
48 | working-directory: ${{env.GITHUB_WORKSPACE}}
49 | if: false == startsWith(github.ref, 'refs/tags/')
50 | run: |
51 | sed -r -i 's/#define\s+PLUGIN_VERSION_STATUS\s+PLUGIN_VERSION_\w+/#define PLUGIN_VERSION_STATUS PLUGIN_VERSION_BETA/' ${{env.VERSION_FILE_PATH}}
52 | sed -r -i 's/#define\s+PLUGIN_VERSION_BUILD\s+.*/#define PLUGIN_VERSION_BUILD ${{ github.run_number }}\r/' ${{env.VERSION_FILE_PATH}}
53 | shell: bash
54 |
55 | - name: Change PLUGIN_VERSION_STATUS_RELEASE
56 | working-directory: ${{env.GITHUB_WORKSPACE}}
57 | if: startsWith(github.ref, 'refs/tags/')
58 | run: |
59 | sed -r -i 's/#define\s+PLUGIN_VERSION_STATUS\s+PLUGIN_VERSION_\w+/#define PLUGIN_VERSION_STATUS PLUGIN_VERSION_RELEASE/' ${{env.VERSION_FILE_PATH}}
60 | sed -r -i 's/#define\s+PLUGIN_VERSION_BUILD\s+.*/#define PLUGIN_VERSION_BUILD ${{ github.run_number }}\r/' ${{env.VERSION_FILE_PATH}}
61 | shell: bash
62 |
63 | - name: Configure CMake
64 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
65 |
66 | - name: Build
67 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
68 |
69 | - name: copy dll and pdb files
70 | working-directory: ${{env.GITHUB_WORKSPACE}}
71 | run: |
72 | mkdir output/
73 | mkdir output/${{env.PLUGIN_NAME}}/
74 | cp -f build/Release/*.dll output/${{env.PLUGIN_NAME}}/
75 | mkdir output/PDB/
76 | cp -f build/Release/*.pdb output/PDB/
77 | # mkdir output/${{env.PLUGIN_NAME}}/${{env.PLUGIN_NAME}}/
78 | # cp -r Data/* output/${{env.PLUGIN_NAME}}/${{env.PLUGIN_NAME}}/
79 | shell: bash
80 |
81 | - name: Pack Release
82 | working-directory: ${{env.GITHUB_WORKSPACE}}
83 | if: startsWith(github.ref, 'refs/tags/')
84 | run: |
85 | Compress-Archive -Path output\${{env.PLUGIN_NAME}}\ ${{env.PLUGIN_NAME}}.zip
86 | Compress-Archive -Path output\PDB\ PDB.zip
87 |
88 | - name: Upload PLUGIN
89 | uses: actions/upload-artifact@v3.1.1
90 | with:
91 | name: ${{env.PLUGIN_NAME}}-actions-${{ github.run_number }}
92 | path: ${{ github.workspace }}\output\${{env.PLUGIN_NAME}}
93 |
94 | - name: Upload PDB
95 | uses: actions/upload-artifact@v3.1.1
96 | with:
97 | name: PDB-actions-${{ github.run_number }}
98 | path: ${{ github.workspace }}\output\PDB
99 |
100 | - name: Create New Release
101 | uses: softprops/action-gh-release@v0.1.13
102 | if: startsWith(github.ref, 'refs/tags/')
103 | with:
104 | files: |
105 | ${{ github.workspace }}\${{env.PLUGIN_NAME}}.zip
106 | ${{ github.workspace }}\PDB.zip
107 | env:
108 | GITHUB_REPOSITORY: ${{env.GITHUB_ACTION_REPOSITORY}}
109 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | **/x64/
3 | **/*.user
4 | **/.vscode/
5 |
6 | **/bedrock_server_api.lib
7 | **/bedrock_server_var.lib
8 |
9 | /.idea/*
10 | !/.idea/cmake.xml
11 | /cmake-build-*
12 | build/*
13 | /out/*
14 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "SDK"]
2 | path = SDK
3 | url = https://github.com/LiteLDev/SDK-CPP.git
4 | branch = main
5 |
--------------------------------------------------------------------------------
/.idea/cmake.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.21)
2 | project(AntiToolbox)
3 |
4 | set(CMAKE_CXX_STANDARD 20)
5 | set(CMAKE_BUILD_TYPE Release)
6 |
7 | file(GLOB SRC_FILES
8 | ${PROJECT_SOURCE_DIR}/src/*.cpp
9 | ${PROJECT_SOURCE_DIR}/src/*.h
10 | )
11 |
12 | add_definitions(-D"NDEBUG" -D"LLMONEY_EXPORTS" -D"_CRT_SECURE_NO_WARNINGS" -D"_WINDOWS"
13 | -D"_USRDLL" -D"_AMD64_" -D"NOMINMAX" -D"_WINDLL" -D"_UNICODE" -D"UNICODE")
14 |
15 | add_compile_options(
16 | /permissive- /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Zc:inline /fp:precise
17 | /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /std:c++17 /FC /EHsc /nologo /diagnostics:column /utf-8
18 | )
19 |
20 | add_link_options(
21 | /MANIFEST /LTCG:incremental /NXCOMPAT /DEBUG /DLL /MACHINE:X64 /OPT:REF /INCREMENTAL:NO /SUBSYSTEM:WINDOWS
22 | /MANIFESTUAC:NO /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /DELAYLOAD:"bedrock_server.dll" /TLBID:1
23 | )
24 |
25 | add_library(AntiToolbox SHARED ${SRC_FILES})
26 | target_link_libraries(AntiToolbox "${PROJECT_SOURCE_DIR}/SDK/lib/LiteLoader.lib"
27 | "${PROJECT_SOURCE_DIR}/SDK/lib/bedrock_server_api.lib"
28 | "${PROJECT_SOURCE_DIR}/SDK/lib/bedrock_server_var.lib"
29 | "${PROJECT_SOURCE_DIR}/SDK/lib/SymDBHelper.lib")
30 |
31 | include_directories(${PROJECT_SOURCE_DIR}/SDK/include)
32 | include_directories(${PROJECT_SOURCE_DIR}/SDK/include/llapi)
33 | include_directories(${PROJECT_SOURCE_DIR}/Header)
34 |
35 | add_custom_command(TARGET AntiToolbox PRE_BUILD
36 | COMMAND cmd /c ${PROJECT_SOURCE_DIR}/prepare_libraries.cmd ${PROJECT_SOURCE_DIR}
37 | COMMENT "Preparing Library"
38 | )
39 |
--------------------------------------------------------------------------------
/Header/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.
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 |
--------------------------------------------------------------------------------
/Header/rapidjson/encodedstream.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.
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_ENCODEDSTREAM_H_
16 | #define RAPIDJSON_ENCODEDSTREAM_H_
17 |
18 | #include "stream.h"
19 | #include "memorystream.h"
20 |
21 | #ifdef __GNUC__
22 | RAPIDJSON_DIAG_PUSH
23 | RAPIDJSON_DIAG_OFF(effc++)
24 | #endif
25 |
26 | #ifdef __clang__
27 | RAPIDJSON_DIAG_PUSH
28 | RAPIDJSON_DIAG_OFF(padded)
29 | #endif
30 |
31 | RAPIDJSON_NAMESPACE_BEGIN
32 |
33 | //! Input byte stream wrapper with a statically bound encoding.
34 | /*!
35 | \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
36 | \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
37 | */
38 | template
39 | class EncodedInputStream {
40 | RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
41 | public:
42 | typedef typename Encoding::Ch Ch;
43 |
44 | EncodedInputStream(InputByteStream& is) : is_(is) {
45 | current_ = Encoding::TakeBOM(is_);
46 | }
47 |
48 | Ch Peek() const { return current_; }
49 | Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
50 | size_t Tell() const { return is_.Tell(); }
51 |
52 | // Not implemented
53 | void Put(Ch) { RAPIDJSON_ASSERT(false); }
54 | void Flush() { RAPIDJSON_ASSERT(false); }
55 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
56 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
57 |
58 | private:
59 | EncodedInputStream(const EncodedInputStream&);
60 | EncodedInputStream& operator=(const EncodedInputStream&);
61 |
62 | InputByteStream& is_;
63 | Ch current_;
64 | };
65 |
66 | //! Specialized for UTF8 MemoryStream.
67 | template <>
68 | class EncodedInputStream, MemoryStream> {
69 | public:
70 | typedef UTF8<>::Ch Ch;
71 |
72 | EncodedInputStream(MemoryStream& is) : is_(is) {
73 | if (static_cast(is_.Peek()) == 0xEFu) is_.Take();
74 | if (static_cast(is_.Peek()) == 0xBBu) is_.Take();
75 | if (static_cast(is_.Peek()) == 0xBFu) is_.Take();
76 | }
77 | Ch Peek() const { return is_.Peek(); }
78 | Ch Take() { return is_.Take(); }
79 | size_t Tell() const { return is_.Tell(); }
80 |
81 | // Not implemented
82 | void Put(Ch) {}
83 | void Flush() {}
84 | Ch* PutBegin() { return 0; }
85 | size_t PutEnd(Ch*) { return 0; }
86 |
87 | MemoryStream& is_;
88 |
89 | private:
90 | EncodedInputStream(const EncodedInputStream&);
91 | EncodedInputStream& operator=(const EncodedInputStream&);
92 | };
93 |
94 | //! Output byte stream wrapper with statically bound encoding.
95 | /*!
96 | \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
97 | \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
98 | */
99 | template
100 | class EncodedOutputStream {
101 | RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
102 | public:
103 | typedef typename Encoding::Ch Ch;
104 |
105 | EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
106 | if (putBOM)
107 | Encoding::PutBOM(os_);
108 | }
109 |
110 | void Put(Ch c) { Encoding::Put(os_, c); }
111 | void Flush() { os_.Flush(); }
112 |
113 | // Not implemented
114 | Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
115 | Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
116 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
117 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
118 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
119 |
120 | private:
121 | EncodedOutputStream(const EncodedOutputStream&);
122 | EncodedOutputStream& operator=(const EncodedOutputStream&);
123 |
124 | OutputByteStream& os_;
125 | };
126 |
127 | #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x
128 |
129 | //! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
130 | /*!
131 | \tparam CharType Type of character for reading.
132 | \tparam InputByteStream type of input byte stream to be wrapped.
133 | */
134 | template
135 | class AutoUTFInputStream {
136 | RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
137 | public:
138 | typedef CharType Ch;
139 |
140 | //! Constructor.
141 | /*!
142 | \param is input stream to be wrapped.
143 | \param type UTF encoding type if it is not detected from the stream.
144 | */
145 | AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
146 | RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
147 | DetectType();
148 | static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
149 | takeFunc_ = f[type_];
150 | current_ = takeFunc_(*is_);
151 | }
152 |
153 | UTFType GetType() const { return type_; }
154 | bool HasBOM() const { return hasBOM_; }
155 |
156 | Ch Peek() const { return current_; }
157 | Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
158 | size_t Tell() const { return is_->Tell(); }
159 |
160 | // Not implemented
161 | void Put(Ch) { RAPIDJSON_ASSERT(false); }
162 | void Flush() { RAPIDJSON_ASSERT(false); }
163 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
164 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
165 |
166 | private:
167 | AutoUTFInputStream(const AutoUTFInputStream&);
168 | AutoUTFInputStream& operator=(const AutoUTFInputStream&);
169 |
170 | // Detect encoding type with BOM or RFC 4627
171 | void DetectType() {
172 | // BOM (Byte Order Mark):
173 | // 00 00 FE FF UTF-32BE
174 | // FF FE 00 00 UTF-32LE
175 | // FE FF UTF-16BE
176 | // FF FE UTF-16LE
177 | // EF BB BF UTF-8
178 |
179 | const unsigned char* c = reinterpret_cast(is_->Peek4());
180 | if (!c)
181 | return;
182 |
183 | unsigned bom = static_cast(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
184 | hasBOM_ = false;
185 | if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
186 | else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
187 | else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
188 | else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
189 | else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
190 |
191 | // RFC 4627: Section 3
192 | // "Since the first two characters of a JSON text will always be ASCII
193 | // characters [RFC0020], it is possible to determine whether an octet
194 | // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
195 | // at the pattern of nulls in the first four octets."
196 | // 00 00 00 xx UTF-32BE
197 | // 00 xx 00 xx UTF-16BE
198 | // xx 00 00 00 UTF-32LE
199 | // xx 00 xx 00 UTF-16LE
200 | // xx xx xx xx UTF-8
201 |
202 | if (!hasBOM_) {
203 | int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
204 | switch (pattern) {
205 | case 0x08: type_ = kUTF32BE; break;
206 | case 0x0A: type_ = kUTF16BE; break;
207 | case 0x01: type_ = kUTF32LE; break;
208 | case 0x05: type_ = kUTF16LE; break;
209 | case 0x0F: type_ = kUTF8; break;
210 | default: break; // Use type defined by user.
211 | }
212 | }
213 |
214 | // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
215 | if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
216 | if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
217 | }
218 |
219 | typedef Ch (*TakeFunc)(InputByteStream& is);
220 | InputByteStream* is_;
221 | UTFType type_;
222 | Ch current_;
223 | TakeFunc takeFunc_;
224 | bool hasBOM_;
225 | };
226 |
227 | //! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
228 | /*!
229 | \tparam CharType Type of character for writing.
230 | \tparam OutputByteStream type of output byte stream to be wrapped.
231 | */
232 | template
233 | class AutoUTFOutputStream {
234 | RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
235 | public:
236 | typedef CharType Ch;
237 |
238 | //! Constructor.
239 | /*!
240 | \param os output stream to be wrapped.
241 | \param type UTF encoding type.
242 | \param putBOM Whether to write BOM at the beginning of the stream.
243 | */
244 | AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
245 | RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
246 |
247 | // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
248 | if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
249 | if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
250 |
251 | static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
252 | putFunc_ = f[type_];
253 |
254 | if (putBOM)
255 | PutBOM();
256 | }
257 |
258 | UTFType GetType() const { return type_; }
259 |
260 | void Put(Ch c) { putFunc_(*os_, c); }
261 | void Flush() { os_->Flush(); }
262 |
263 | // Not implemented
264 | Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
265 | Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
266 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
267 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
268 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
269 |
270 | private:
271 | AutoUTFOutputStream(const AutoUTFOutputStream&);
272 | AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
273 |
274 | void PutBOM() {
275 | typedef void (*PutBOMFunc)(OutputByteStream&);
276 | static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
277 | f[type_](*os_);
278 | }
279 |
280 | typedef void (*PutFunc)(OutputByteStream&, Ch);
281 |
282 | OutputByteStream* os_;
283 | UTFType type_;
284 | PutFunc putFunc_;
285 | };
286 |
287 | #undef RAPIDJSON_ENCODINGS_FUNC
288 |
289 | RAPIDJSON_NAMESPACE_END
290 |
291 | #ifdef __clang__
292 | RAPIDJSON_DIAG_POP
293 | #endif
294 |
295 | #ifdef __GNUC__
296 | RAPIDJSON_DIAG_POP
297 | #endif
298 |
299 | #endif // RAPIDJSON_FILESTREAM_H_
300 |
--------------------------------------------------------------------------------
/Header/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.
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 | //! Maps error code of validation into error message.
69 | /*!
70 | \ingroup RAPIDJSON_ERRORS
71 | \param validateErrorCode Error code obtained from validator.
72 | \return the error message.
73 | \note User can make a copy of this function for localization.
74 | Using switch-case is safer for future modification of error codes.
75 | */
76 | inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
77 | switch (validateErrorCode) {
78 | case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
79 | case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
80 |
81 | case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
82 | case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
83 | case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
84 | case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
85 | case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
86 |
87 | case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
88 | case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
89 | case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
90 |
91 | case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
92 | case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
93 | case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
94 | case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
95 |
96 | case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
97 | case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
98 | case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
99 | case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
100 | case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
101 | case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
102 |
103 | case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
104 | case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
105 |
106 | case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
107 | case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'.");
108 | case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
109 | case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
110 | case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
111 |
112 | default: return RAPIDJSON_ERROR_STRING("Unknown error.");
113 | }
114 | }
115 |
116 | RAPIDJSON_NAMESPACE_END
117 |
118 | #ifdef __clang__
119 | RAPIDJSON_DIAG_POP
120 | #endif
121 |
122 | #endif // RAPIDJSON_ERROR_EN_H_
123 |
--------------------------------------------------------------------------------
/Header/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.
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 | ///////////////////////////////////////////////////////////////////////////////
156 | // ValidateErrorCode
157 |
158 | //! Error codes when validating.
159 | /*! \ingroup RAPIDJSON_ERRORS
160 | \see GenericSchemaValidator
161 | */
162 | enum ValidateErrorCode {
163 | kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set.
164 | kValidateErrorNone = 0, //!< No error.
165 |
166 | kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value.
167 | kValidateErrorMaximum, //!< Number is greater than the 'maximum' value.
168 | kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value.
169 | kValidateErrorMinimum, //!< Number is less than the 'minimum' value.
170 | kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value.
171 |
172 | kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value.
173 | kValidateErrorMinLength, //!< String is longer than the 'maxLength' value.
174 | kValidateErrorPattern, //!< String does not match the 'pattern' regular expression.
175 |
176 | kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value.
177 | kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value.
178 | kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true.
179 | kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema.
180 |
181 | kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value.
182 | kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value.
183 | kValidateErrorRequired, //!< Object is missing one or more members required by the schema.
184 | kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema.
185 | kValidateErrorPatternProperties, //!< See other errors.
186 | kValidateErrorDependencies, //!< Object has missing property or schema dependencies.
187 |
188 | kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values
189 | kValidateErrorType, //!< Property has a type that is not allowed by the schema..
190 |
191 | kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'.
192 | kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'.
193 | kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'.
194 | kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'.
195 | kValidateErrorNot //!< Property matched the sub-schema specified by 'not'.
196 | };
197 |
198 | //! Function pointer type of GetValidateError().
199 | /*! \ingroup RAPIDJSON_ERRORS
200 |
201 | This is the prototype for \c GetValidateError_X(), where \c X is a locale.
202 | User can dynamically change locale in runtime, e.g.:
203 | \code
204 | GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever
205 | const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode());
206 | \endcode
207 | */
208 | typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode);
209 |
210 | RAPIDJSON_NAMESPACE_END
211 |
212 | #ifdef __clang__
213 | RAPIDJSON_DIAG_POP
214 | #endif
215 |
216 | #endif // RAPIDJSON_ERROR_ERROR_H_
217 |
--------------------------------------------------------------------------------
/Header/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.
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 |
--------------------------------------------------------------------------------
/Header/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.
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 |
--------------------------------------------------------------------------------
/Header/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.
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 | class 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 |
--------------------------------------------------------------------------------
/Header/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.
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) && !defined(__INTEL_COMPILER) && defined(_M_AMD64)
21 | #include // for _umul128
22 | #if !defined(_ARM64EC_)
23 | #pragma intrinsic(_umul128)
24 | #else
25 | #pragma comment(lib,"softintrin")
26 | #endif
27 | #endif
28 |
29 | RAPIDJSON_NAMESPACE_BEGIN
30 | namespace internal {
31 |
32 | class BigInteger {
33 | public:
34 | typedef uint64_t Type;
35 |
36 | BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
37 | std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
38 | }
39 |
40 | explicit BigInteger(uint64_t u) : count_(1) {
41 | digits_[0] = u;
42 | }
43 |
44 | template
45 | BigInteger(const Ch* decimals, size_t length) : count_(1) {
46 | RAPIDJSON_ASSERT(length > 0);
47 | digits_[0] = 0;
48 | size_t i = 0;
49 | const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
50 | while (length >= kMaxDigitPerIteration) {
51 | AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
52 | length -= kMaxDigitPerIteration;
53 | i += kMaxDigitPerIteration;
54 | }
55 |
56 | if (length > 0)
57 | AppendDecimal64(decimals + i, decimals + i + length);
58 | }
59 |
60 | BigInteger& operator=(const BigInteger &rhs)
61 | {
62 | if (this != &rhs) {
63 | count_ = rhs.count_;
64 | std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
65 | }
66 | return *this;
67 | }
68 |
69 | BigInteger& operator=(uint64_t u) {
70 | digits_[0] = u;
71 | count_ = 1;
72 | return *this;
73 | }
74 |
75 | BigInteger& operator+=(uint64_t u) {
76 | Type backup = digits_[0];
77 | digits_[0] += u;
78 | for (size_t i = 0; i < count_ - 1; i++) {
79 | if (digits_[i] >= backup)
80 | return *this; // no carry
81 | backup = digits_[i + 1];
82 | digits_[i + 1] += 1;
83 | }
84 |
85 | // Last carry
86 | if (digits_[count_ - 1] < backup)
87 | PushBack(1);
88 |
89 | return *this;
90 | }
91 |
92 | BigInteger& operator*=(uint64_t u) {
93 | if (u == 0) return *this = 0;
94 | if (u == 1) return *this;
95 | if (*this == 1) return *this = u;
96 |
97 | uint64_t k = 0;
98 | for (size_t i = 0; i < count_; i++) {
99 | uint64_t hi;
100 | digits_[i] = MulAdd64(digits_[i], u, k, &hi);
101 | k = hi;
102 | }
103 |
104 | if (k > 0)
105 | PushBack(k);
106 |
107 | return *this;
108 | }
109 |
110 | BigInteger& operator*=(uint32_t u) {
111 | if (u == 0) return *this = 0;
112 | if (u == 1) return *this;
113 | if (*this == 1) return *this = u;
114 |
115 | uint64_t k = 0;
116 | for (size_t i = 0; i < count_; i++) {
117 | const uint64_t c = digits_[i] >> 32;
118 | const uint64_t d = digits_[i] & 0xFFFFFFFF;
119 | const uint64_t uc = u * c;
120 | const uint64_t ud = u * d;
121 | const uint64_t p0 = ud + k;
122 | const uint64_t p1 = uc + (p0 >> 32);
123 | digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
124 | k = p1 >> 32;
125 | }
126 |
127 | if (k > 0)
128 | PushBack(k);
129 |
130 | return *this;
131 | }
132 |
133 | BigInteger& operator<<=(size_t shift) {
134 | if (IsZero() || shift == 0) return *this;
135 |
136 | size_t offset = shift / kTypeBit;
137 | size_t interShift = shift % kTypeBit;
138 | RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
139 |
140 | if (interShift == 0) {
141 | std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
142 | count_ += offset;
143 | }
144 | else {
145 | digits_[count_] = 0;
146 | for (size_t i = count_; i > 0; i--)
147 | digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
148 | digits_[offset] = digits_[0] << interShift;
149 | count_ += offset;
150 | if (digits_[count_])
151 | count_++;
152 | }
153 |
154 | std::memset(digits_, 0, offset * sizeof(Type));
155 |
156 | return *this;
157 | }
158 |
159 | bool operator==(const BigInteger& rhs) const {
160 | return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
161 | }
162 |
163 | bool operator==(const Type rhs) const {
164 | return count_ == 1 && digits_[0] == rhs;
165 | }
166 |
167 | BigInteger& MultiplyPow5(unsigned exp) {
168 | static const uint32_t kPow5[12] = {
169 | 5,
170 | 5 * 5,
171 | 5 * 5 * 5,
172 | 5 * 5 * 5 * 5,
173 | 5 * 5 * 5 * 5 * 5,
174 | 5 * 5 * 5 * 5 * 5 * 5,
175 | 5 * 5 * 5 * 5 * 5 * 5 * 5,
176 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
177 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
178 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
179 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
180 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
181 | };
182 | if (exp == 0) return *this;
183 | for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
184 | for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13
185 | if (exp > 0) *this *= kPow5[exp - 1];
186 | return *this;
187 | }
188 |
189 | // Compute absolute difference of this and rhs.
190 | // Assume this != rhs
191 | bool Difference(const BigInteger& rhs, BigInteger* out) const {
192 | int cmp = Compare(rhs);
193 | RAPIDJSON_ASSERT(cmp != 0);
194 | const BigInteger *a, *b; // Makes a > b
195 | bool ret;
196 | if (cmp < 0) { a = &rhs; b = this; ret = true; }
197 | else { a = this; b = &rhs; ret = false; }
198 |
199 | Type borrow = 0;
200 | for (size_t i = 0; i < a->count_; i++) {
201 | Type d = a->digits_[i] - borrow;
202 | if (i < b->count_)
203 | d -= b->digits_[i];
204 | borrow = (d > a->digits_[i]) ? 1 : 0;
205 | out->digits_[i] = d;
206 | if (d != 0)
207 | out->count_ = i + 1;
208 | }
209 |
210 | return ret;
211 | }
212 |
213 | int Compare(const BigInteger& rhs) const {
214 | if (count_ != rhs.count_)
215 | return count_ < rhs.count_ ? -1 : 1;
216 |
217 | for (size_t i = count_; i-- > 0;)
218 | if (digits_[i] != rhs.digits_[i])
219 | return digits_[i] < rhs.digits_[i] ? -1 : 1;
220 |
221 | return 0;
222 | }
223 |
224 | size_t GetCount() const { return count_; }
225 | Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
226 | bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
227 |
228 | private:
229 | template
230 | void AppendDecimal64(const Ch* begin, const Ch* end) {
231 | uint64_t u = ParseUint64(begin, end);
232 | if (IsZero())
233 | *this = u;
234 | else {
235 | unsigned exp = static_cast(end - begin);
236 | (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
237 | }
238 | }
239 |
240 | void PushBack(Type digit) {
241 | RAPIDJSON_ASSERT(count_ < kCapacity);
242 | digits_[count_++] = digit;
243 | }
244 |
245 | template
246 | static uint64_t ParseUint64(const Ch* begin, const Ch* end) {
247 | uint64_t r = 0;
248 | for (const Ch* p = begin; p != end; ++p) {
249 | RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9'));
250 | r = r * 10u + static_cast(*p - Ch('0'));
251 | }
252 | return r;
253 | }
254 |
255 | // Assume a * b + k < 2^128
256 | static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
257 | #if defined(_MSC_VER) && defined(_M_AMD64)
258 | uint64_t low = _umul128(a, b, outHigh) + k;
259 | if (low < k)
260 | (*outHigh)++;
261 | return low;
262 | #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
263 | __extension__ typedef unsigned __int128 uint128;
264 | uint128 p = static_cast(a) * static_cast(b);
265 | p += k;
266 | *outHigh = static_cast(p >> 64);
267 | return static_cast(p);
268 | #else
269 | const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
270 | uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
271 | x1 += (x0 >> 32); // can't give carry
272 | x1 += x2;
273 | if (x1 < x2)
274 | x3 += (static_cast(1) << 32);
275 | uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
276 | uint64_t hi = x3 + (x1 >> 32);
277 |
278 | lo += k;
279 | if (lo < k)
280 | hi++;
281 | *outHigh = hi;
282 | return lo;
283 | #endif
284 | }
285 |
286 | static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
287 | static const size_t kCapacity = kBitCount / sizeof(Type);
288 | static const size_t kTypeBit = sizeof(Type) * 8;
289 |
290 | Type digits_[kCapacity];
291 | size_t count_;
292 | };
293 |
294 | } // namespace internal
295 | RAPIDJSON_NAMESPACE_END
296 |
297 | #endif // RAPIDJSON_BIGINTEGER_H_
298 |
--------------------------------------------------------------------------------
/Header/rapidjson/internal/clzll.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.
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_CLZLL_H_
16 | #define RAPIDJSON_CLZLL_H_
17 |
18 | #include "../rapidjson.h"
19 |
20 | #if defined(_MSC_VER) && !defined(UNDER_CE)
21 | #include
22 | #if defined(_WIN64)
23 | #pragma intrinsic(_BitScanReverse64)
24 | #else
25 | #pragma intrinsic(_BitScanReverse)
26 | #endif
27 | #endif
28 |
29 | RAPIDJSON_NAMESPACE_BEGIN
30 | namespace internal {
31 |
32 | inline uint32_t clzll(uint64_t x) {
33 | // Passing 0 to __builtin_clzll is UB in GCC and results in an
34 | // infinite loop in the software implementation.
35 | RAPIDJSON_ASSERT(x != 0);
36 |
37 | #if defined(_MSC_VER) && !defined(UNDER_CE)
38 | unsigned long r = 0;
39 | #if defined(_WIN64)
40 | _BitScanReverse64(&r, x);
41 | #else
42 | // Scan the high 32 bits.
43 | if (_BitScanReverse(&r, static_cast(x >> 32)))
44 | return 63 - (r + 32);
45 |
46 | // Scan the low 32 bits.
47 | _BitScanReverse(&r, static_cast(x & 0xFFFFFFFF));
48 | #endif // _WIN64
49 |
50 | return 63 - r;
51 | #elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
52 | // __builtin_clzll wrapper
53 | return static_cast(__builtin_clzll(x));
54 | #else
55 | // naive version
56 | uint32_t r = 0;
57 | while (!(x & (static_cast(1) << 63))) {
58 | x <<= 1;
59 | ++r;
60 | }
61 |
62 | return r;
63 | #endif // _MSC_VER
64 | }
65 |
66 | #define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
67 |
68 | } // namespace internal
69 | RAPIDJSON_NAMESPACE_END
70 |
71 | #endif // RAPIDJSON_CLZLL_H_
72 |
--------------------------------------------------------------------------------
/Header/rapidjson/internal/diyfp.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.
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_DIYFP_H_
20 | #define RAPIDJSON_DIYFP_H_
21 |
22 | #include "../rapidjson.h"
23 | #include "clzll.h"
24 | #include
25 |
26 | #if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
27 | #include
28 | #if !defined(_ARM64EC_)
29 | #pragma intrinsic(_umul128)
30 | #else
31 | #pragma comment(lib,"softintrin")
32 | #endif
33 | #endif
34 |
35 | RAPIDJSON_NAMESPACE_BEGIN
36 | namespace internal {
37 |
38 | #ifdef __GNUC__
39 | RAPIDJSON_DIAG_PUSH
40 | RAPIDJSON_DIAG_OFF(effc++)
41 | #endif
42 |
43 | #ifdef __clang__
44 | RAPIDJSON_DIAG_PUSH
45 | RAPIDJSON_DIAG_OFF(padded)
46 | #endif
47 |
48 | struct DiyFp {
49 | DiyFp() : f(), e() {}
50 |
51 | DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
52 |
53 | explicit DiyFp(double d) {
54 | union {
55 | double d;
56 | uint64_t u64;
57 | } u = { d };
58 |
59 | int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize);
60 | uint64_t significand = (u.u64 & kDpSignificandMask);
61 | if (biased_e != 0) {
62 | f = significand + kDpHiddenBit;
63 | e = biased_e - kDpExponentBias;
64 | }
65 | else {
66 | f = significand;
67 | e = kDpMinExponent + 1;
68 | }
69 | }
70 |
71 | DiyFp operator-(const DiyFp& rhs) const {
72 | return DiyFp(f - rhs.f, e);
73 | }
74 |
75 | DiyFp operator*(const DiyFp& rhs) const {
76 | #if defined(_MSC_VER) && defined(_M_AMD64)
77 | uint64_t h;
78 | uint64_t l = _umul128(f, rhs.f, &h);
79 | if (l & (uint64_t(1) << 63)) // rounding
80 | h++;
81 | return DiyFp(h, e + rhs.e + 64);
82 | #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
83 | __extension__ typedef unsigned __int128 uint128;
84 | uint128 p = static_cast(f) * static_cast(rhs.f);
85 | uint64_t h = static_cast(p >> 64);
86 | uint64_t l = static_cast(p);
87 | if (l & (uint64_t(1) << 63)) // rounding
88 | h++;
89 | return DiyFp(h, e + rhs.e + 64);
90 | #else
91 | const uint64_t M32 = 0xFFFFFFFF;
92 | const uint64_t a = f >> 32;
93 | const uint64_t b = f & M32;
94 | const uint64_t c = rhs.f >> 32;
95 | const uint64_t d = rhs.f & M32;
96 | const uint64_t ac = a * c;
97 | const uint64_t bc = b * c;
98 | const uint64_t ad = a * d;
99 | const uint64_t bd = b * d;
100 | uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
101 | tmp += 1U << 31; /// mult_round
102 | return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
103 | #endif
104 | }
105 |
106 | DiyFp Normalize() const {
107 | int s = static_cast(clzll(f));
108 | return DiyFp(f << s, e - s);
109 | }
110 |
111 | DiyFp NormalizeBoundary() const {
112 | DiyFp res = *this;
113 | while (!(res.f & (kDpHiddenBit << 1))) {
114 | res.f <<= 1;
115 | res.e--;
116 | }
117 | res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
118 | res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
119 | return res;
120 | }
121 |
122 | void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
123 | DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
124 | DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
125 | mi.f <<= mi.e - pl.e;
126 | mi.e = pl.e;
127 | *plus = pl;
128 | *minus = mi;
129 | }
130 |
131 | double ToDouble() const {
132 | union {
133 | double d;
134 | uint64_t u64;
135 | }u;
136 | RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
137 | if (e < kDpDenormalExponent) {
138 | // Underflow.
139 | return 0.0;
140 | }
141 | if (e >= kDpMaxExponent) {
142 | // Overflow.
143 | return std::numeric_limits::infinity();
144 | }
145 | const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
146 | static_cast(e + kDpExponentBias);
147 | u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
148 | return u.d;
149 | }
150 |
151 | static const int kDiySignificandSize = 64;
152 | static const int kDpSignificandSize = 52;
153 | static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
154 | static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
155 | static const int kDpMinExponent = -kDpExponentBias;
156 | static const int kDpDenormalExponent = -kDpExponentBias + 1;
157 | static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
158 | static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
159 | static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
160 |
161 | uint64_t f;
162 | int e;
163 | };
164 |
165 | inline DiyFp GetCachedPowerByIndex(size_t index) {
166 | // 10^-348, 10^-340, ..., 10^340
167 | static const uint64_t kCachedPowers_F[] = {
168 | RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
169 | RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
170 | RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
171 | RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
172 | RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
173 | RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
174 | RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
175 | RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
176 | RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
177 | RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
178 | RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
179 | RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
180 | RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
181 | RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
182 | RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
183 | RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
184 | RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
185 | RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
186 | RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
187 | RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
188 | RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
189 | RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
190 | RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
191 | RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
192 | RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
193 | RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
194 | RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
195 | RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
196 | RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
197 | RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
198 | RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
199 | RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
200 | RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
201 | RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
202 | RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
203 | RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
204 | RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
205 | RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
206 | RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
207 | RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
208 | RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
209 | RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
210 | RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
211 | RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
212 | };
213 | static const int16_t kCachedPowers_E[] = {
214 | -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
215 | -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
216 | -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
217 | -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
218 | -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
219 | 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
220 | 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
221 | 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
222 | 907, 933, 960, 986, 1013, 1039, 1066
223 | };
224 | RAPIDJSON_ASSERT(index < 87);
225 | return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
226 | }
227 |
228 | inline DiyFp GetCachedPower(int e, int* K) {
229 |
230 | //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374;
231 | double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
232 | int k = static_cast(dk);
233 | if (dk - k > 0.0)
234 | k++;
235 |
236 | unsigned index = static_cast((k >> 3) + 1);
237 | *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table
238 |
239 | return GetCachedPowerByIndex(index);
240 | }
241 |
242 | inline DiyFp GetCachedPower10(int exp, int *outExp) {
243 | RAPIDJSON_ASSERT(exp >= -348);
244 | unsigned index = static_cast(exp + 348) / 8u;
245 | *outExp = -348 + static_cast(index) * 8;
246 | return GetCachedPowerByIndex(index);
247 | }
248 |
249 | #ifdef __GNUC__
250 | RAPIDJSON_DIAG_POP
251 | #endif
252 |
253 | #ifdef __clang__
254 | RAPIDJSON_DIAG_POP
255 | RAPIDJSON_DIAG_OFF(padded)
256 | #endif
257 |
258 | } // namespace internal
259 | RAPIDJSON_NAMESPACE_END
260 |
261 | #endif // RAPIDJSON_DIYFP_H_
262 |
--------------------------------------------------------------------------------
/Header/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.
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 uint64_t kPow10[] = { 1U, 10U, 100U, 1000U, 10000U, 100000U, 1000000U, 10000000U, 100000000U,
62 | 1000000000U, 10000000000U, 100000000000U, 1000000000000U,
63 | 10000000000000U, 100000000000000U, 1000000000000000U,
64 | 10000000000000000U, 100000000000000000U, 1000000000000000000U,
65 | 10000000000000000000U };
66 | const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
67 | const DiyFp wp_w = Mp - W;
68 | uint32_t p1 = static_cast(Mp.f >> -one.e);
69 | uint64_t p2 = Mp.f & (one.f - 1);
70 | int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
71 | *len = 0;
72 |
73 | while (kappa > 0) {
74 | uint32_t d = 0;
75 | switch (kappa) {
76 | case 9: d = p1 / 100000000; p1 %= 100000000; break;
77 | case 8: d = p1 / 10000000; p1 %= 10000000; break;
78 | case 7: d = p1 / 1000000; p1 %= 1000000; break;
79 | case 6: d = p1 / 100000; p1 %= 100000; break;
80 | case 5: d = p1 / 10000; p1 %= 10000; break;
81 | case 4: d = p1 / 1000; p1 %= 1000; break;
82 | case 3: d = p1 / 100; p1 %= 100; break;
83 | case 2: d = p1 / 10; p1 %= 10; break;
84 | case 1: d = p1; p1 = 0; break;
85 | default:;
86 | }
87 | if (d || *len)
88 | buffer[(*len)++] = static_cast('0' + static_cast(d));
89 | kappa--;
90 | uint64_t tmp = (static_cast(p1) << -one.e) + p2;
91 | if (tmp <= delta) {
92 | *K += kappa;
93 | GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f);
94 | return;
95 | }
96 | }
97 |
98 | // kappa = 0
99 | for (;;) {
100 | p2 *= 10;
101 | delta *= 10;
102 | char d = static_cast(p2 >> -one.e);
103 | if (d || *len)
104 | buffer[(*len)++] = static_cast('0' + d);
105 | p2 &= one.f - 1;
106 | kappa--;
107 | if (p2 < delta) {
108 | *K += kappa;
109 | int index = -kappa;
110 | GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0));
111 | return;
112 | }
113 | }
114 | }
115 |
116 | inline void Grisu2(double value, char* buffer, int* length, int* K) {
117 | const DiyFp v(value);
118 | DiyFp w_m, w_p;
119 | v.NormalizedBoundaries(&w_m, &w_p);
120 |
121 | const DiyFp c_mk = GetCachedPower(w_p.e, K);
122 | const DiyFp W = v.Normalize() * c_mk;
123 | DiyFp Wp = w_p * c_mk;
124 | DiyFp Wm = w_m * c_mk;
125 | Wm.f++;
126 | Wp.f--;
127 | DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
128 | }
129 |
130 | inline char* WriteExponent(int K, char* buffer) {
131 | if (K < 0) {
132 | *buffer++ = '-';
133 | K = -K;
134 | }
135 |
136 | if (K >= 100) {
137 | *buffer++ = static_cast('0' + static_cast(K / 100));
138 | K %= 100;
139 | const char* d = GetDigitsLut() + K * 2;
140 | *buffer++ = d[0];
141 | *buffer++ = d[1];
142 | }
143 | else if (K >= 10) {
144 | const char* d = GetDigitsLut() + K * 2;
145 | *buffer++ = d[0];
146 | *buffer++ = d[1];
147 | }
148 | else
149 | *buffer++ = static_cast('0' + static_cast(K));
150 |
151 | return buffer;
152 | }
153 |
154 | inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
155 | const int kk = length + k; // 10^(kk-1) <= v < 10^kk
156 |
157 | if (0 <= k && kk <= 21) {
158 | // 1234e7 -> 12340000000
159 | for (int i = length; i < kk; i++)
160 | buffer[i] = '0';
161 | buffer[kk] = '.';
162 | buffer[kk + 1] = '0';
163 | return &buffer[kk + 2];
164 | }
165 | else if (0 < kk && kk <= 21) {
166 | // 1234e-2 -> 12.34
167 | std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk));
168 | buffer[kk] = '.';
169 | if (0 > k + maxDecimalPlaces) {
170 | // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
171 | // Remove extra trailing zeros (at least one) after truncation.
172 | for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
173 | if (buffer[i] != '0')
174 | return &buffer[i + 1];
175 | return &buffer[kk + 2]; // Reserve one zero
176 | }
177 | else
178 | return &buffer[length + 1];
179 | }
180 | else if (-6 < kk && kk <= 0) {
181 | // 1234e-6 -> 0.001234
182 | const int offset = 2 - kk;
183 | std::memmove(&buffer[offset], &buffer[0], static_cast(length));
184 | buffer[0] = '0';
185 | buffer[1] = '.';
186 | for (int i = 2; i < offset; i++)
187 | buffer[i] = '0';
188 | if (length - kk > maxDecimalPlaces) {
189 | // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
190 | // Remove extra trailing zeros (at least one) after truncation.
191 | for (int i = maxDecimalPlaces + 1; i > 2; i--)
192 | if (buffer[i] != '0')
193 | return &buffer[i + 1];
194 | return &buffer[3]; // Reserve one zero
195 | }
196 | else
197 | return &buffer[length + offset];
198 | }
199 | else if (kk < -maxDecimalPlaces) {
200 | // Truncate to zero
201 | buffer[0] = '0';
202 | buffer[1] = '.';
203 | buffer[2] = '0';
204 | return &buffer[3];
205 | }
206 | else if (length == 1) {
207 | // 1e30
208 | buffer[1] = 'e';
209 | return WriteExponent(kk - 1, &buffer[2]);
210 | }
211 | else {
212 | // 1234e30 -> 1.234e33
213 | std::memmove(&buffer[2], &buffer[1], static_cast(length - 1));
214 | buffer[1] = '.';
215 | buffer[length + 1] = 'e';
216 | return WriteExponent(kk - 1, &buffer[0 + length + 2]);
217 | }
218 | }
219 |
220 | inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
221 | RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
222 | Double d(value);
223 | if (d.IsZero()) {
224 | if (d.Sign())
225 | *buffer++ = '-'; // -0.0, Issue #289
226 | buffer[0] = '0';
227 | buffer[1] = '.';
228 | buffer[2] = '0';
229 | return &buffer[3];
230 | }
231 | else {
232 | if (value < 0) {
233 | *buffer++ = '-';
234 | value = -value;
235 | }
236 | int length, K;
237 | Grisu2(value, buffer, &length, &K);
238 | return Prettify(buffer, length, K, maxDecimalPlaces);
239 | }
240 | }
241 |
242 | #ifdef __GNUC__
243 | RAPIDJSON_DIAG_POP
244 | #endif
245 |
246 | } // namespace internal
247 | RAPIDJSON_NAMESPACE_END
248 |
249 | #endif // RAPIDJSON_DTOA_
250 |
--------------------------------------------------------------------------------
/Header/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.
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 |
--------------------------------------------------------------------------------
/Header/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.
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 |
--------------------------------------------------------------------------------
/Header/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.
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 |
--------------------------------------------------------------------------------
/Header/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.
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 |
--------------------------------------------------------------------------------
/Header/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.
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 |
--------------------------------------------------------------------------------
/Header/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.
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 | //! Custom strcmpn() which works on different character types.
49 | /*! \tparam Ch Character type (e.g. char, wchar_t, short)
50 | \param s1 Null-terminated input string.
51 | \param s2 Null-terminated input string.
52 | \return 0 if equal
53 | */
54 | template
55 | inline int StrCmp(const Ch* s1, const Ch* s2) {
56 | RAPIDJSON_ASSERT(s1 != 0);
57 | RAPIDJSON_ASSERT(s2 != 0);
58 | while(*s1 && (*s1 == *s2)) { s1++; s2++; }
59 | return static_cast(*s1) < static_cast(*s2) ? -1 : static_cast(*s1) > static_cast(*s2);
60 | }
61 |
62 | //! Returns number of code points in a encoded string.
63 | template
64 | bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
65 | RAPIDJSON_ASSERT(s != 0);
66 | RAPIDJSON_ASSERT(outCount != 0);
67 | GenericStringStream is(s);
68 | const typename Encoding::Ch* end = s + length;
69 | SizeType count = 0;
70 | while (is.src_ < end) {
71 | unsigned codepoint;
72 | if (!Encoding::Decode(is, &codepoint))
73 | return false;
74 | count++;
75 | }
76 | *outCount = count;
77 | return true;
78 | }
79 |
80 | } // namespace internal
81 | RAPIDJSON_NAMESPACE_END
82 |
83 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_
84 |
--------------------------------------------------------------------------------
/Header/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.
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 | template
132 | inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) {
133 | uint64_t significand = 0;
134 | int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
135 | for (; i < dLen; i++) {
136 | if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
137 | (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5')))
138 | break;
139 | significand = significand * 10u + static_cast(decimals[i] - Ch('0'));
140 | }
141 |
142 | if (i < dLen && decimals[i] >= Ch('5')) // Rounding
143 | significand++;
144 |
145 | int remaining = dLen - i;
146 | const int kUlpShift = 3;
147 | const int kUlp = 1 << kUlpShift;
148 | int64_t error = (remaining == 0) ? 0 : kUlp / 2;
149 |
150 | DiyFp v(significand, 0);
151 | v = v.Normalize();
152 | error <<= -v.e;
153 |
154 | dExp += remaining;
155 |
156 | int actualExp;
157 | DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
158 | if (actualExp != dExp) {
159 | static const DiyFp kPow10[] = {
160 | DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1
161 | DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2
162 | DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3
163 | DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4
164 | DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5
165 | DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6
166 | DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7
167 | };
168 | int adjustment = dExp - actualExp;
169 | RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8);
170 | v = v * kPow10[adjustment - 1];
171 | if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit
172 | error += kUlp / 2;
173 | }
174 |
175 | v = v * cachedPower;
176 |
177 | error += kUlp + (error == 0 ? 0 : 1);
178 |
179 | const int oldExp = v.e;
180 | v = v.Normalize();
181 | error <<= oldExp - v.e;
182 |
183 | const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
184 | int precisionSize = 64 - effectiveSignificandSize;
185 | if (precisionSize + kUlpShift >= 64) {
186 | int scaleExp = (precisionSize + kUlpShift) - 63;
187 | v.f >>= scaleExp;
188 | v.e += scaleExp;
189 | error = (error >> scaleExp) + 1 + kUlp;
190 | precisionSize -= scaleExp;
191 | }
192 |
193 | DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
194 | const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
195 | const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
196 | if (precisionBits >= halfWay + static_cast(error)) {
197 | rounded.f++;
198 | if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
199 | rounded.f >>= 1;
200 | rounded.e++;
201 | }
202 | }
203 |
204 | *result = rounded.ToDouble();
205 |
206 | return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error);
207 | }
208 |
209 | template
210 | inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) {
211 | RAPIDJSON_ASSERT(dLen >= 0);
212 | const BigInteger dInt(decimals, static_cast(dLen));
213 | Double a(approx);
214 | int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
215 | if (cmp < 0)
216 | return a.Value(); // within half ULP
217 | else if (cmp == 0) {
218 | // Round towards even
219 | if (a.Significand() & 1)
220 | return a.NextPositiveDouble();
221 | else
222 | return a.Value();
223 | }
224 | else // adjustment
225 | return a.NextPositiveDouble();
226 | }
227 |
228 | template
229 | inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) {
230 | RAPIDJSON_ASSERT(d >= 0.0);
231 | RAPIDJSON_ASSERT(length >= 1);
232 |
233 | double result = 0.0;
234 | if (StrtodFast(d, p, &result))
235 | return result;
236 |
237 | RAPIDJSON_ASSERT(length <= INT_MAX);
238 | int dLen = static_cast(length);
239 |
240 | RAPIDJSON_ASSERT(length >= decimalPosition);
241 | RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX);
242 | int dExpAdjust = static_cast(length - decimalPosition);
243 |
244 | RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust);
245 | int dExp = exp - dExpAdjust;
246 |
247 | // Make sure length+dExp does not overflow
248 | RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen);
249 |
250 | // Trim leading zeros
251 | while (dLen > 0 && *decimals == '0') {
252 | dLen--;
253 | decimals++;
254 | }
255 |
256 | // Trim trailing zeros
257 | while (dLen > 0 && decimals[dLen - 1] == '0') {
258 | dLen--;
259 | dExp++;
260 | }
261 |
262 | if (dLen == 0) { // Buffer only contains zeros.
263 | return 0.0;
264 | }
265 |
266 | // Trim right-most digits
267 | const int kMaxDecimalDigit = 767 + 1;
268 | if (dLen > kMaxDecimalDigit) {
269 | dExp += dLen - kMaxDecimalDigit;
270 | dLen = kMaxDecimalDigit;
271 | }
272 |
273 | // If too small, underflow to zero.
274 | // Any x <= 10^-324 is interpreted as zero.
275 | if (dLen + dExp <= -324)
276 | return 0.0;
277 |
278 | // If too large, overflow to infinity.
279 | // Any x >= 10^309 is interpreted as +infinity.
280 | if (dLen + dExp > 309)
281 | return std::numeric_limits