├── .gitattributes
├── .gitignore
├── C++ XenForo Loader.sln
├── C++ XenForo Loader.vcxproj
├── C++ XenForo Loader.vcxproj.filters
├── README.md
├── configmanager
├── configmanager.cpp
└── configmanager.hpp
├── main.cpp
├── rapidjson
├── allocators.h
├── document.h
├── encodedstream.h
├── encodings.h
├── error
│ ├── en.h
│ └── error.h
├── filereadstream.h
├── filewritestream.h
├── fwd.h
├── internal
│ ├── biginteger.h
│ ├── diyfp.h
│ ├── dtoa.h
│ ├── ieee754.h
│ ├── itoa.h
│ ├── meta.h
│ ├── pow10.h
│ ├── regex.h
│ ├── stack.h
│ ├── strfunc.h
│ ├── strtod.h
│ └── swap.h
├── istreamwrapper.h
├── memorybuffer.h
├── memorystream.h
├── msinttypes
│ ├── inttypes.h
│ └── stdint.h
├── ostreamwrapper.h
├── pointer.h
├── prettywriter.h
├── rapidjson.h
├── reader.h
├── schema.h
├── stream.h
├── stringbuffer.h
└── writer.h
├── request
└── request.hpp
├── utils
├── utils.cpp
└── utils.hpp
└── webfiles
└── hwid.php
/.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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/C++ XenForo Loader.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29806.167
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "C++ XenForo Loader", "C++ XenForo Loader.vcxproj", "{64A9A18D-04B3-452E-8B6D-2E672340CB94}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Debug|x64 = Debug|x64
12 | Release|Win32 = Release|Win32
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}.Debug|Win32.ActiveCfg = Debug|Win32
17 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}.Debug|Win32.Build.0 = Debug|Win32
18 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}.Debug|x64.ActiveCfg = Debug|x64
19 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}.Debug|x64.Build.0 = Debug|x64
20 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}.Release|Win32.ActiveCfg = Release|Win32
21 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}.Release|Win32.Build.0 = Release|Win32
22 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}.Release|x64.ActiveCfg = Release|x64
23 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}.Release|x64.Build.0 = Release|x64
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {6D044158-618D-46A1-A83E-AD851AD02821}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/C++ XenForo Loader.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {64A9A18D-04B3-452E-8B6D-2E672340CB94}
24 | Win32Proj
25 | C++ XenForo Loader
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | MultiByte
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | MultiByte
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | true
78 |
79 |
80 | false
81 | $(IncludePath)
82 |
83 |
84 | false
85 |
86 |
87 |
88 |
89 |
90 | Level3
91 | true
92 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
93 | true
94 |
95 |
96 | Console
97 | true
98 |
99 |
100 |
101 |
102 |
103 |
104 | Level3
105 | true
106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
107 | true
108 |
109 |
110 | Console
111 | true
112 |
113 |
114 |
115 |
116 | Level3
117 | MaxSpeed
118 | true
119 | true
120 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
121 | true
122 |
123 |
124 | Console
125 | true
126 | true
127 | true
128 | ws2_32.lib;%(AdditionalDependencies)
129 |
130 |
131 |
132 |
133 |
134 |
135 | Level3
136 | true
137 | true
138 | true
139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
140 | true
141 |
142 |
143 | Console
144 | true
145 | true
146 | true
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/C++ XenForo Loader.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | configmanager
7 |
8 |
9 | utils
10 |
11 |
12 |
13 |
14 | {c1f500b1-6010-4a1f-bf64-b839deffb04b}
15 |
16 |
17 | {8c7cb401-9c93-434c-acca-d922ff8bb2b3}
18 |
19 |
20 | {0f2108a5-3fac-4c77-8199-3e10157896f4}
21 |
22 |
23 | {5efc35dd-bd16-4c84-bbb3-91b137dec4eb}
24 |
25 |
26 | {038d4898-94fc-471a-9ea1-8c3a4b1df4d0}
27 |
28 |
29 | {50f53050-300b-4a21-8774-1b2260714df6}
30 |
31 |
32 | {ad52dae1-daa0-48a6-8772-52f19b6b1890}
33 |
34 |
35 |
36 |
37 | request
38 |
39 |
40 | rapidjson
41 |
42 |
43 | rapidjson
44 |
45 |
46 | rapidjson
47 |
48 |
49 | rapidjson
50 |
51 |
52 | rapidjson
53 |
54 |
55 | rapidjson
56 |
57 |
58 | rapidjson
59 |
60 |
61 | rapidjson
62 |
63 |
64 | rapidjson
65 |
66 |
67 | rapidjson
68 |
69 |
70 | rapidjson
71 |
72 |
73 | rapidjson
74 |
75 |
76 | rapidjson
77 |
78 |
79 | rapidjson
80 |
81 |
82 | rapidjson
83 |
84 |
85 | rapidjson
86 |
87 |
88 | rapidjson
89 |
90 |
91 | rapidjson
92 |
93 |
94 | rapidjson
95 |
96 |
97 | rapidjson\msinttypes
98 |
99 |
100 | rapidjson\msinttypes
101 |
102 |
103 | rapidjson\internal
104 |
105 |
106 | rapidjson\internal
107 |
108 |
109 | rapidjson\internal
110 |
111 |
112 | rapidjson\internal
113 |
114 |
115 | rapidjson\internal
116 |
117 |
118 | rapidjson\internal
119 |
120 |
121 | rapidjson\internal
122 |
123 |
124 | rapidjson\internal
125 |
126 |
127 | rapidjson\internal
128 |
129 |
130 | rapidjson\internal
131 |
132 |
133 | rapidjson\internal
134 |
135 |
136 | rapidjson\internal
137 |
138 |
139 | rapidjson\error
140 |
141 |
142 | rapidjson\error
143 |
144 |
145 | configmanager
146 |
147 |
148 | utils
149 |
150 |
151 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CPP-XenForo-Loader
2 | WIP Cheat Loader which authenticates with a XenForo 2.1 forum.
3 |
4 | Open-Source made for Void.to using rapidjson and httprequests.
5 |
6 | Please stop contacting, i will publish a reworked version of this sooner or later.
7 |
--------------------------------------------------------------------------------
/configmanager/configmanager.cpp:
--------------------------------------------------------------------------------
1 | #include "configmanager.hpp"
2 |
3 | void CConfigManager::GetValue(string szSection, string szKey, string* Value, string szPath) {
4 | TCHAR KeyValue[32];
5 | GetPrivateProfileString(szSection.c_str(), szKey.c_str(), "", KeyValue, 32, szPath.c_str());
6 |
7 | string szKeyValue = KeyValue;
8 |
9 | *Value = szKeyValue;
10 | }
11 |
12 | void CConfigManager::GetValue(string szSection, string szKey, double* Value, string szPath) {
13 | TCHAR KeyValue[32];
14 | GetPrivateProfileString(szSection.c_str(), szKey.c_str(), "", KeyValue, 32, szPath.c_str());
15 |
16 | string szKeyValue = KeyValue;
17 |
18 | double nKeyValue = atof(szKeyValue.c_str());
19 |
20 | *Value = nKeyValue;
21 | }
22 |
23 | void CConfigManager::GetValue(string szSection, string szKey, int* Value, string szPath) {
24 | TCHAR KeyValue[32];
25 | GetPrivateProfileString(szSection.c_str(), szKey.c_str(), "", KeyValue, 32, szPath.c_str());
26 |
27 | string szKeyValue = KeyValue;
28 |
29 | int nKeyValue = atoi(szKeyValue.c_str());
30 |
31 | *Value = nKeyValue;
32 | }
33 |
34 | void CConfigManager::GetValue(string szSection, string szKey, float* Value, string szPath) {
35 | TCHAR KeyValue[32];
36 | GetPrivateProfileString(szSection.c_str(), szKey.c_str(), "", KeyValue, 32, szPath.c_str());
37 |
38 | string szKeyValue = KeyValue;
39 |
40 | float nKeyValue = (float)atof(szKeyValue.c_str());
41 |
42 | *Value = nKeyValue;
43 | }
44 |
45 | void CConfigManager::GetValue(string szSection, string szKey, bool* Value, string szPath) {
46 | TCHAR KeyValue[32];
47 | GetPrivateProfileString(szSection.c_str(), szKey.c_str(), "", KeyValue, 32, szPath.c_str());
48 |
49 | string szKeyValue = KeyValue;
50 |
51 | bool bKeyValue = StringToBool(szKeyValue);
52 |
53 | *Value = bKeyValue;
54 | }
55 |
56 | void CConfigManager::PushValue(string szSection, string szKey, string Value, string szPath) {
57 | WritePrivateProfileString(szSection.c_str(), szKey.c_str(), Value.c_str(), szPath.c_str());
58 | }
59 |
60 | void CConfigManager::PushValue(string szSection, string szKey, double* Value, string szPath) {
61 | string szKeyValue = to_string(*Value);
62 |
63 | WritePrivateProfileString(szSection.c_str(), szKey.c_str(), szKeyValue.c_str(), szPath.c_str());
64 | }
65 |
66 | void CConfigManager::PushValue(string szSection, string szKey, int* Value, string szPath) {
67 | string szKeyValue = to_string(*Value);
68 |
69 | WritePrivateProfileString(szSection.c_str(), szKey.c_str(), szKeyValue.c_str(), szPath.c_str());
70 | }
71 |
72 | void CConfigManager::PushValue(string szSection, string szKey, float* Value, string szPath) {
73 | string szKeyValue = to_string(*Value);
74 |
75 | WritePrivateProfileString(szSection.c_str(), szKey.c_str(), szKeyValue.c_str(), szPath.c_str());
76 | }
77 |
78 | void CConfigManager::PushValue(string szSection, string szKey, bool* Value, string szPath) {
79 | string szKeyValue = BoolToString(*Value);
80 |
81 | WritePrivateProfileString(szSection.c_str(), szKey.c_str(), szKeyValue.c_str(), szPath.c_str());
82 | }
83 |
84 | void CConfigManager::MakeValue(string szSection, string szKey, string Value, string szPath, bool bIsSave) {
85 | if (!bIsSave)
86 | GetValue(szSection, szKey, &Value, szPath);
87 | else
88 | PushValue(szSection, szKey, Value, szPath);
89 | }
90 |
91 | void CConfigManager::MakeValue(string szSection, string szKey, double* Value, string szPath, bool bIsSave) {
92 | if (!bIsSave)
93 | GetValue(szSection, szKey, Value, szPath);
94 | else
95 | PushValue(szSection, szKey, Value, szPath);
96 | }
97 |
98 | void CConfigManager::MakeValue(string szSection, string szKey, int* Value, string szPath, bool bIsSave) {
99 | if (!bIsSave)
100 | GetValue(szSection, szKey, Value, szPath);
101 | else
102 | PushValue(szSection, szKey, Value, szPath);
103 | }
104 |
105 | void CConfigManager::MakeValue(string szSection, string szKey, float* Value, string szPath, bool bIsSave) {
106 | if (!bIsSave)
107 | GetValue(szSection, szKey, Value, szPath);
108 | else
109 | PushValue(szSection, szKey, Value, szPath);
110 | }
111 |
112 | void CConfigManager::MakeValue(string szSection, string szKey, bool* Value, string szPath, bool bIsSave) {
113 | if (!bIsSave)
114 | GetValue(szSection, szKey, Value, szPath);
115 | else
116 | PushValue(szSection, szKey, Value, szPath);
117 | }
118 |
119 | string CConfigManager::BoolToString(bool value)
120 | {
121 | return value ? "true" : "false";
122 | }
123 |
124 | bool CConfigManager::StringToBool(string value)
125 | {
126 | return (value == "true") ? true : false;
127 | }
128 |
129 | CConfigManager* configmanager;
--------------------------------------------------------------------------------
/configmanager/configmanager.hpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace std;
5 |
6 | class CConfigManager
7 | {
8 | public:
9 | void GetValue(string szSection, string szKey, string* Value, string szPath);
10 | void GetValue(string szSection, string szKey, double* Value, string szPath);
11 | void GetValue(string szSection, string szKey, int* Value, string szPath);
12 | void GetValue(string szSection, string szKey, float* Value, string szPath);
13 | void GetValue(string szSection, string szKey, bool* Value, string szPath);
14 |
15 | void PushValue(string szSection, string szKey, string Value, string szPath);
16 | void PushValue(string szSection, string szKey, double* Value, string szPath);
17 | void PushValue(string szSection, string szKey, int* Value, string szPath);
18 | void PushValue(string szSection, string szKey, float* Value, string szPath);
19 | void PushValue(string szSection, string szKey, bool* Value, string szPath);
20 |
21 | void MakeValue(string szSection, string szKey, string Value, string szPath, bool bIsSave);
22 | void MakeValue(string szSection, string szKey, double* Value, string szPath, bool bIsSave);
23 | void MakeValue(string szSection, string szKey, int* Value, string szPath, bool bIsSave);
24 | void MakeValue(string szSection, string szKey, float* Value, string szPath, bool bIsSave);
25 | void MakeValue(string szSection, string szKey, bool* Value, string szPath, bool bIsSave);
26 | private:
27 | string BoolToString(bool value);
28 | bool StringToBool(string value);
29 | };
30 |
31 | extern CConfigManager* configmanager;
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | // windows related
2 | #include
3 | #include
4 | #include
5 | #include
6 | // request
7 | #include "request/request.hpp"
8 | // rapidjson
9 | #include "rapidjson/document.h"
10 | #include "rapidjson/pointer.h"
11 | #include "rapidjson/stringbuffer.h"
12 | #include "rapidjson/writer.h"
13 | // utils
14 | #include "utils/utils.hpp"
15 |
16 | // using namespaces to make the code cleaner without typing everything with std:: etc
17 | using namespace std;
18 | using namespace http;
19 | using namespace rapidjson;
20 |
21 | int main()
22 | {
23 | /*
24 | some sidenote for the hwid check, there are for sure multiple ways for this,
25 | but imo it was the easiest way to connect to the xenforo database via a php script and
26 | provide it through there.
27 | but to avoid random people fucking up the hwid system (because in the php file we won't check the password)
28 | we will secure the input by a token which is defined in the php file and inside the loader.
29 | */
30 |
31 | string username, password; // defined authentication strings
32 | string hwid, hwidtoken, respondedhwid; // hwid related strings
33 | string appdata, appdatafolder, appdatafile; // paths/file to store the authentication data locally on the host's pc
34 | bool success; // used later for checking our login data
35 |
36 | // definining the paths/file
37 | appdata = utils->GetAppData();
38 | appdatafolder = appdata + "\\loader";
39 | appdatafile = appdatafolder + "\\logindata.ini";
40 |
41 | if (!utils->dirExists(appdatafolder.c_str())) // check if the folder exists already
42 | _mkdir(appdatafolder.c_str()); // creating a folder inside appdata
43 |
44 | cout << "enter your username:" << endl; // asking for the username
45 | cin >> username; // getting the username as input
46 | cout << "enter your password:" << endl; // asking for the password
47 | cin >> password; // getting the password as inpout
48 |
49 | try // try to make a request
50 | {
51 | Request request("http://xenforo.gandaa.lv/index.php/api/auth"); // xenforo api url / request url
52 |
53 | // making the post request
54 | const Response postResponse = request.send("POST", "login=" + username + "&password=" + password, {
55 | "Content-Type: application/x-www-form-urlencoded", "XF-Api-Key: TqfDwgHw3dpuXGXC9MqVdWRmhJUic9BO" // your xenforo api key
56 | });
57 |
58 | // setting up the json document and parsing the output
59 | Document document;
60 | document.Parse(string(postResponse.body.begin(), postResponse.body.end()).c_str());
61 |
62 | assert(document["success"].IsBool()); // checking if the resonded function "success" is a bool
63 | success = document["success"].GetBool(); // defining our local variable "success" to be the responded bool
64 |
65 | if (success == true)
66 | {
67 | cout << "login was successful :)" << endl;
68 |
69 | // now we do a staff check first, if the logged in user is a staff member, we will skip the hwid check
70 |
71 | if (Value* user = GetValueByPointer(document, "/user")) // since "success" and "user" are 2 different pointers, we need to resolve the second one
72 | {
73 | if ((*user)["is_staff"].GetBool() || (*user)["is_admin"].GetBool() || (*user)["is_moderator"].GetBool() || (*user)["is_super_admin"].GetBool() == true) { // we check if either one of those staff variables are true
74 | cout << "staff member detected, no hwid check needed!" << endl;
75 |
76 | // from here the main authentication is basically done, next step would be the cheat part.
77 | }
78 | else // if the logged in user is not a staff member, continue with the hwid check
79 | {
80 | if (Value* v = GetValueByPointer(document, "/user")) {
81 | const Value& secondary_group = (*v)["secondary_group_ids"];
82 | assert(secondary_group.IsArray());
83 |
84 | if (secondary_group[0].GetInt() == 2 || secondary_group[0].GetInt() == 3 || secondary_group[0].GetInt() == 4 || secondary_group[0].GetInt() == 5) // kinda ghetto like, but it checks for the secondary group ids. why? because the xenforo userupgrade function only edits the secondary group id, not the primary.
85 | { // the 0 defines ^^^ the position of inside the array, the other numbers define the usergroup id
86 | try // try to make a second request
87 | {
88 | cout << "checking hwid..." << endl;
89 |
90 | hwid = to_string(utils->GetHWID());
91 | hwidtoken = "1337";
92 |
93 | Request requesthwid("http://xenforo.gandaa.lv/hwid.php?username=" + username + "&token=" + hwidtoken + "&hwid=" + hwid); // we will use now the hwid.php for the new request
94 |
95 | const http::Response getResponseHWID = requesthwid.send("GET"); // for the hwid request we only need a simple 'GET' request
96 | respondedhwid = string(getResponseHWID.body.begin(), getResponseHWID.body.end());
97 |
98 | if (respondedhwid == "new") // if there is no hwid set
99 | {
100 | cout << "no stored hwid found! setting new one." << endl;
101 | utils->StoreLogin(username, password, hwid, appdatafile); // storing the logindata for later
102 | // do cheat stuff
103 | }
104 | else if (respondedhwid == "accepted") // if hwid check was successful
105 | {
106 | cout << "hwid check was successful, welcome back " + username + " :)" << endl;
107 | utils->StoreLogin(username, password, hwid, appdatafile); // storing the logindata for later
108 | // do cheat stuff
109 | }
110 | else if (respondedhwid == "declined")
111 | {
112 | cout << "unknown hwid detected! please request a reset" << endl;
113 | // don't allow to continue / exit the programm
114 | }
115 | else
116 | {
117 | cout << "some unknown error occured, please check back later :(" << endl;
118 | // some other error within the system
119 | }
120 | }
121 | catch (const exception & e) // catch any errors
122 | {
123 | cerr << "hwid request failed, error: " << e.what() << endl; // print the errors
124 |
125 | system("pause"); // wait for user input
126 |
127 | return EXIT_FAILURE; //exit programm with status code 1
128 | }
129 | }
130 | else // no subscription - wrong usergroup
131 | {
132 | cout << "no active sub found" << endl;
133 | system("pause");
134 | return EXIT_FAILURE;
135 | }
136 | }
137 | }
138 | }
139 | }
140 | else
141 | {
142 | cout << "login was not successful :(" << endl; // invalid username+password combination
143 | }
144 |
145 | system("pause"); // wait for user input
146 | }
147 | catch (const exception & e) // catch any errors
148 | {
149 | cerr << "Request failed, error: " << e.what() << endl; // print the errors
150 |
151 | system("pause"); // wait for user input
152 |
153 | return EXIT_FAILURE; //exit programm with status code 1
154 | }
155 |
156 | return EXIT_SUCCESS; //exit programm with status code 0
157 | }
--------------------------------------------------------------------------------
/rapidjson/allocators.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_ALLOCATORS_H_
16 | #define RAPIDJSON_ALLOCATORS_H_
17 |
18 | #include "rapidjson.h"
19 |
20 | RAPIDJSON_NAMESPACE_BEGIN
21 |
22 | ///////////////////////////////////////////////////////////////////////////////
23 | // Allocator
24 |
25 | /*! \class rapidjson::Allocator
26 | \brief Concept for allocating, resizing and freeing memory block.
27 |
28 | Note that Malloc() and Realloc() are non-static but Free() is static.
29 |
30 | So if an allocator need to support Free(), it needs to put its pointer in
31 | the header of memory block.
32 |
33 | \code
34 | concept Allocator {
35 | static const bool kNeedFree; //!< Whether this allocator needs to call Free().
36 |
37 | // Allocate a memory block.
38 | // \param size of the memory block in bytes.
39 | // \returns pointer to the memory block.
40 | void* Malloc(size_t size);
41 |
42 | // Resize a memory block.
43 | // \param originalPtr The pointer to current memory block. Null pointer is permitted.
44 | // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
45 | // \param newSize the new size in bytes.
46 | void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
47 |
48 | // Free a memory block.
49 | // \param pointer to the memory block. Null pointer is permitted.
50 | static void Free(void *ptr);
51 | };
52 | \endcode
53 | */
54 |
55 | ///////////////////////////////////////////////////////////////////////////////
56 | // CrtAllocator
57 |
58 | //! C-runtime library allocator.
59 | /*! This class is just wrapper for standard C library memory routines.
60 | \note implements Allocator concept
61 | */
62 | class CrtAllocator {
63 | public:
64 | static const bool kNeedFree = true;
65 | void* Malloc(size_t size) {
66 | if (size) // behavior of malloc(0) is implementation defined.
67 | return std::malloc(size);
68 | else
69 | return NULL; // standardize to returning NULL.
70 | }
71 | void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
72 | (void)originalSize;
73 | if (newSize == 0) {
74 | std::free(originalPtr);
75 | return NULL;
76 | }
77 | return std::realloc(originalPtr, newSize);
78 | }
79 | static void Free(void *ptr) { std::free(ptr); }
80 | };
81 |
82 | ///////////////////////////////////////////////////////////////////////////////
83 | // MemoryPoolAllocator
84 |
85 | //! Default memory allocator used by the parser and DOM.
86 | /*! This allocator allocate memory blocks from pre-allocated memory chunks.
87 |
88 | It does not free memory blocks. And Realloc() only allocate new memory.
89 |
90 | The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
91 |
92 | User may also supply a buffer as the first chunk.
93 |
94 | If the user-buffer is full then additional chunks are allocated by BaseAllocator.
95 |
96 | The user-buffer is not deallocated by this allocator.
97 |
98 | \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
99 | \note implements Allocator concept
100 | */
101 | template
102 | class MemoryPoolAllocator {
103 | public:
104 | static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
105 |
106 | //! Constructor with chunkSize.
107 | /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
108 | \param baseAllocator The allocator for allocating memory chunks.
109 | */
110 | MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
111 | chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
112 | {
113 | }
114 |
115 | //! Constructor with user-supplied buffer.
116 | /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
117 |
118 | The user buffer will not be deallocated when this allocator is destructed.
119 |
120 | \param buffer User supplied buffer.
121 | \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
122 | \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
123 | \param baseAllocator The allocator for allocating memory chunks.
124 | */
125 | MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
126 | chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
127 | {
128 | RAPIDJSON_ASSERT(buffer != 0);
129 | RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
130 | chunkHead_ = reinterpret_cast(buffer);
131 | chunkHead_->capacity = size - sizeof(ChunkHeader);
132 | chunkHead_->size = 0;
133 | chunkHead_->next = 0;
134 | }
135 |
136 | //! Destructor.
137 | /*! This deallocates all memory chunks, excluding the user-supplied buffer.
138 | */
139 | ~MemoryPoolAllocator() {
140 | Clear();
141 | RAPIDJSON_DELETE(ownBaseAllocator_);
142 | }
143 |
144 | //! Deallocates all memory chunks, excluding the user-supplied buffer.
145 | void Clear() {
146 | while (chunkHead_ && chunkHead_ != userBuffer_) {
147 | ChunkHeader* next = chunkHead_->next;
148 | baseAllocator_->Free(chunkHead_);
149 | chunkHead_ = next;
150 | }
151 | if (chunkHead_ && chunkHead_ == userBuffer_)
152 | chunkHead_->size = 0; // Clear user buffer
153 | }
154 |
155 | //! Computes the total capacity of allocated memory chunks.
156 | /*! \return total capacity in bytes.
157 | */
158 | size_t Capacity() const {
159 | size_t capacity = 0;
160 | for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
161 | capacity += c->capacity;
162 | return capacity;
163 | }
164 |
165 | //! Computes the memory blocks allocated.
166 | /*! \return total used bytes.
167 | */
168 | size_t Size() const {
169 | size_t size = 0;
170 | for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
171 | size += c->size;
172 | return size;
173 | }
174 |
175 | //! Allocates a memory block. (concept Allocator)
176 | void* Malloc(size_t size) {
177 | if (!size)
178 | return NULL;
179 |
180 | size = RAPIDJSON_ALIGN(size);
181 | if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
182 | if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
183 | return NULL;
184 |
185 | void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
186 | chunkHead_->size += size;
187 | return buffer;
188 | }
189 |
190 | //! Resizes a memory block (concept Allocator)
191 | void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
192 | if (originalPtr == 0)
193 | return Malloc(newSize);
194 |
195 | if (newSize == 0)
196 | return NULL;
197 |
198 | originalSize = RAPIDJSON_ALIGN(originalSize);
199 | newSize = RAPIDJSON_ALIGN(newSize);
200 |
201 | // Do not shrink if new size is smaller than original
202 | if (originalSize >= newSize)
203 | return originalPtr;
204 |
205 | // Simply expand it if it is the last allocation and there is sufficient space
206 | if (originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
207 | size_t increment = static_cast(newSize - originalSize);
208 | if (chunkHead_->size + increment <= chunkHead_->capacity) {
209 | chunkHead_->size += increment;
210 | return originalPtr;
211 | }
212 | }
213 |
214 | // Realloc process: allocate and copy memory, do not free original buffer.
215 | if (void* newBuffer = Malloc(newSize)) {
216 | if (originalSize)
217 | std::memcpy(newBuffer, originalPtr, originalSize);
218 | return newBuffer;
219 | }
220 | else
221 | return NULL;
222 | }
223 |
224 | //! Frees a memory block (concept Allocator)
225 | static void Free(void *ptr) { (void)ptr; } // Do nothing
226 |
227 | private:
228 | //! Copy constructor is not permitted.
229 | MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
230 | //! Copy assignment operator is not permitted.
231 | MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
232 |
233 | //! Creates a new chunk.
234 | /*! \param capacity Capacity of the chunk in bytes.
235 | \return true if success.
236 | */
237 | bool AddChunk(size_t capacity) {
238 | if (!baseAllocator_)
239 | ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
240 | if (ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
241 | chunk->capacity = capacity;
242 | chunk->size = 0;
243 | chunk->next = chunkHead_;
244 | chunkHead_ = chunk;
245 | return true;
246 | }
247 | else
248 | return false;
249 | }
250 |
251 | static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
252 |
253 | //! Chunk header for perpending to each chunk.
254 | /*! Chunks are stored as a singly linked list.
255 | */
256 | struct ChunkHeader {
257 | size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
258 | size_t size; //!< Current size of allocated memory in bytes.
259 | ChunkHeader *next; //!< Next chunk in the linked list.
260 | };
261 |
262 | ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
263 | size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
264 | void *userBuffer_; //!< User supplied buffer.
265 | BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
266 | BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
267 | };
268 |
269 | RAPIDJSON_NAMESPACE_END
270 |
271 | #endif // RAPIDJSON_ENCODINGS_H_
272 |
--------------------------------------------------------------------------------
/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. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_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 |
--------------------------------------------------------------------------------
/rapidjson/error/en.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_ERROR_EN_H_
16 | #define RAPIDJSON_ERROR_EN_H_
17 |
18 | #include "error.h"
19 |
20 | #ifdef __clang__
21 | RAPIDJSON_DIAG_PUSH
22 | RAPIDJSON_DIAG_OFF(switch-enum)
23 | RAPIDJSON_DIAG_OFF(covered-switch-default)
24 | #endif
25 |
26 | RAPIDJSON_NAMESPACE_BEGIN
27 |
28 | //! Maps error code of parsing into error message.
29 | /*!
30 | \ingroup RAPIDJSON_ERRORS
31 | \param parseErrorCode Error code obtained in parsing.
32 | \return the error message.
33 | \note User can make a copy of this function for localization.
34 | Using switch-case is safer for future modification of error codes.
35 | */
36 | inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
37 | switch (parseErrorCode) {
38 | case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
39 |
40 | case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
41 | case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
42 |
43 | case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
44 |
45 | case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
46 | case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
47 | case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
48 |
49 | case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
50 |
51 | case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
52 | case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
53 | case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
54 | case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
55 | case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
56 |
57 | case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
58 | case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
59 | case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
60 |
61 | case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
62 | case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
63 |
64 | default: return RAPIDJSON_ERROR_STRING("Unknown error.");
65 | }
66 | }
67 |
68 | RAPIDJSON_NAMESPACE_END
69 |
70 | #ifdef __clang__
71 | RAPIDJSON_DIAG_POP
72 | #endif
73 |
74 | #endif // RAPIDJSON_ERROR_EN_H_
75 |
--------------------------------------------------------------------------------
/rapidjson/error/error.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_ERROR_ERROR_H_
16 | #define RAPIDJSON_ERROR_ERROR_H_
17 |
18 | #include "../rapidjson.h"
19 |
20 | #ifdef __clang__
21 | RAPIDJSON_DIAG_PUSH
22 | RAPIDJSON_DIAG_OFF(padded)
23 | #endif
24 |
25 | /*! \file error.h */
26 |
27 | /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
28 |
29 | ///////////////////////////////////////////////////////////////////////////////
30 | // RAPIDJSON_ERROR_CHARTYPE
31 |
32 | //! Character type of error messages.
33 | /*! \ingroup RAPIDJSON_ERRORS
34 | The default character type is \c char.
35 | On Windows, user can define this macro as \c TCHAR for supporting both
36 | unicode/non-unicode settings.
37 | */
38 | #ifndef RAPIDJSON_ERROR_CHARTYPE
39 | #define RAPIDJSON_ERROR_CHARTYPE char
40 | #endif
41 |
42 | ///////////////////////////////////////////////////////////////////////////////
43 | // RAPIDJSON_ERROR_STRING
44 |
45 | //! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
46 | /*! \ingroup RAPIDJSON_ERRORS
47 | By default this conversion macro does nothing.
48 | On Windows, user can define this macro as \c _T(x) for supporting both
49 | unicode/non-unicode settings.
50 | */
51 | #ifndef RAPIDJSON_ERROR_STRING
52 | #define RAPIDJSON_ERROR_STRING(x) x
53 | #endif
54 |
55 | RAPIDJSON_NAMESPACE_BEGIN
56 |
57 | ///////////////////////////////////////////////////////////////////////////////
58 | // ParseErrorCode
59 |
60 | //! Error code of parsing.
61 | /*! \ingroup RAPIDJSON_ERRORS
62 | \see GenericReader::Parse, GenericReader::GetParseErrorCode
63 | */
64 | enum ParseErrorCode {
65 | kParseErrorNone = 0, //!< No error.
66 |
67 | kParseErrorDocumentEmpty, //!< The document is empty.
68 | kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
69 |
70 | kParseErrorValueInvalid, //!< Invalid value.
71 |
72 | kParseErrorObjectMissName, //!< Missing a name for object member.
73 | kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
74 | kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
75 |
76 | kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
77 |
78 | kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
79 | kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
80 | kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
81 | kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
82 | kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
83 |
84 | kParseErrorNumberTooBig, //!< Number too big to be stored in double.
85 | kParseErrorNumberMissFraction, //!< Miss fraction part in number.
86 | kParseErrorNumberMissExponent, //!< Miss exponent in number.
87 |
88 | kParseErrorTermination, //!< Parsing was terminated.
89 | kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
90 | };
91 |
92 | //! Result of parsing (wraps ParseErrorCode)
93 | /*!
94 | \ingroup RAPIDJSON_ERRORS
95 | \code
96 | Document doc;
97 | ParseResult ok = doc.Parse("[42]");
98 | if (!ok) {
99 | fprintf(stderr, "JSON parse error: %s (%u)",
100 | GetParseError_En(ok.Code()), ok.Offset());
101 | exit(EXIT_FAILURE);
102 | }
103 | \endcode
104 | \see GenericReader::Parse, GenericDocument::Parse
105 | */
106 | struct ParseResult {
107 | public:
108 | //! Default constructor, no error.
109 | ParseResult() : code_(kParseErrorNone), offset_(0) {}
110 | //! Constructor to set an error.
111 | ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
112 |
113 | //! Get the error code.
114 | ParseErrorCode Code() const { return code_; }
115 | //! Get the error offset, if \ref IsError(), 0 otherwise.
116 | size_t Offset() const { return offset_; }
117 |
118 | //! Conversion to \c bool, returns \c true, iff !\ref IsError().
119 | operator bool() const { return !IsError(); }
120 | //! Whether the result is an error.
121 | bool IsError() const { return code_ != kParseErrorNone; }
122 |
123 | bool operator==(const ParseResult& that) const { return code_ == that.code_; }
124 | bool operator==(ParseErrorCode code) const { return code_ == code; }
125 | friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
126 |
127 | //! Reset error code.
128 | void Clear() { Set(kParseErrorNone); }
129 | //! Update error code and offset.
130 | void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
131 |
132 | private:
133 | ParseErrorCode code_;
134 | size_t offset_;
135 | };
136 |
137 | //! Function pointer type of GetParseError().
138 | /*! \ingroup RAPIDJSON_ERRORS
139 |
140 | This is the prototype for \c GetParseError_X(), where \c X is a locale.
141 | User can dynamically change locale in runtime, e.g.:
142 | \code
143 | GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
144 | const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
145 | \endcode
146 | */
147 | typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
148 |
149 | RAPIDJSON_NAMESPACE_END
150 |
151 | #ifdef __clang__
152 | RAPIDJSON_DIAG_POP
153 | #endif
154 |
155 | #endif // RAPIDJSON_ERROR_ERROR_H_
156 |
--------------------------------------------------------------------------------
/rapidjson/filereadstream.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_FILEREADSTREAM_H_
16 | #define RAPIDJSON_FILEREADSTREAM_H_
17 |
18 | #include "stream.h"
19 | #include
20 |
21 | #ifdef __clang__
22 | RAPIDJSON_DIAG_PUSH
23 | RAPIDJSON_DIAG_OFF(padded)
24 | RAPIDJSON_DIAG_OFF(unreachable-code)
25 | RAPIDJSON_DIAG_OFF(missing-noreturn)
26 | #endif
27 |
28 | RAPIDJSON_NAMESPACE_BEGIN
29 |
30 | //! File byte stream for input using fread().
31 | /*!
32 | \note implements Stream concept
33 | */
34 | class FileReadStream {
35 | public:
36 | typedef char Ch; //!< Character type (byte).
37 |
38 | //! Constructor.
39 | /*!
40 | \param fp File pointer opened for read.
41 | \param buffer user-supplied buffer.
42 | \param bufferSize size of buffer in bytes. Must >=4 bytes.
43 | */
44 | FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
45 | RAPIDJSON_ASSERT(fp_ != 0);
46 | RAPIDJSON_ASSERT(bufferSize >= 4);
47 | Read();
48 | }
49 |
50 | Ch Peek() const { return *current_; }
51 | Ch Take() { Ch c = *current_; Read(); return c; }
52 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); }
53 |
54 | // Not implemented
55 | void Put(Ch) { RAPIDJSON_ASSERT(false); }
56 | void Flush() { RAPIDJSON_ASSERT(false); }
57 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
58 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
59 |
60 | // For encoding detection only.
61 | const Ch* Peek4() const {
62 | return (current_ + 4 <= 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_ = 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 |
--------------------------------------------------------------------------------
/rapidjson/filewritestream.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_
16 | #define RAPIDJSON_FILEWRITESTREAM_H_
17 |
18 | #include "stream.h"
19 | #include
20 |
21 | #ifdef __clang__
22 | RAPIDJSON_DIAG_PUSH
23 | RAPIDJSON_DIAG_OFF(unreachable-code)
24 | #endif
25 |
26 | RAPIDJSON_NAMESPACE_BEGIN
27 |
28 | //! Wrapper of C file stream for input using fread().
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 = 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 |
--------------------------------------------------------------------------------
/rapidjson/fwd.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_FWD_H_
16 | #define RAPIDJSON_FWD_H_
17 |
18 | #include "rapidjson.h"
19 |
20 | RAPIDJSON_NAMESPACE_BEGIN
21 |
22 | // encodings.h
23 |
24 | template struct UTF8;
25 | template struct UTF16;
26 | template struct UTF16BE;
27 | template struct UTF16LE;
28 | template struct UTF32;
29 | template struct UTF32BE;
30 | template struct UTF32LE;
31 | template struct ASCII;
32 | template struct AutoUTF;
33 |
34 | template
35 | struct Transcoder;
36 |
37 | // allocators.h
38 |
39 | class CrtAllocator;
40 |
41 | template
42 | class MemoryPoolAllocator;
43 |
44 | // stream.h
45 |
46 | template
47 | struct GenericStringStream;
48 |
49 | typedef GenericStringStream > StringStream;
50 |
51 | template
52 | struct GenericInsituStringStream;
53 |
54 | typedef GenericInsituStringStream > InsituStringStream;
55 |
56 | // stringbuffer.h
57 |
58 | template
59 | class GenericStringBuffer;
60 |
61 | typedef GenericStringBuffer, CrtAllocator> StringBuffer;
62 |
63 | // filereadstream.h
64 |
65 | class FileReadStream;
66 |
67 | // filewritestream.h
68 |
69 | class FileWriteStream;
70 |
71 | // memorybuffer.h
72 |
73 | template
74 | struct GenericMemoryBuffer;
75 |
76 | typedef GenericMemoryBuffer MemoryBuffer;
77 |
78 | // memorystream.h
79 |
80 | struct MemoryStream;
81 |
82 | // reader.h
83 |
84 | template
85 | struct BaseReaderHandler;
86 |
87 | template
88 | class GenericReader;
89 |
90 | typedef GenericReader, UTF8, CrtAllocator> Reader;
91 |
92 | // writer.h
93 |
94 | template
95 | class Writer;
96 |
97 | // prettywriter.h
98 |
99 | template
100 | class PrettyWriter;
101 |
102 | // document.h
103 |
104 | template
105 | struct GenericMember;
106 |
107 | template
108 | class GenericMemberIterator;
109 |
110 | template
111 | struct GenericStringRef;
112 |
113 | template
114 | class GenericValue;
115 |
116 | typedef GenericValue, MemoryPoolAllocator > Value;
117 |
118 | template
119 | class GenericDocument;
120 |
121 | typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document;
122 |
123 | // pointer.h
124 |
125 | template
126 | class GenericPointer;
127 |
128 | typedef GenericPointer Pointer;
129 |
130 | // schema.h
131 |
132 | template
133 | class IGenericRemoteSchemaDocumentProvider;
134 |
135 | template
136 | class GenericSchemaDocument;
137 |
138 | typedef GenericSchemaDocument SchemaDocument;
139 | typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider;
140 |
141 | template <
142 | typename SchemaDocumentType,
143 | typename OutputHandler,
144 | typename StateAllocator>
145 | class GenericSchemaValidator;
146 |
147 | typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator;
148 |
149 | RAPIDJSON_NAMESPACE_END
150 |
151 | #endif // RAPIDJSON_RAPIDJSONFWD_H_
152 |
--------------------------------------------------------------------------------
/rapidjson/internal/biginteger.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_BIGINTEGER_H_
16 | #define RAPIDJSON_BIGINTEGER_H_
17 |
18 | #include "../rapidjson.h"
19 |
20 | #if defined(_MSC_VER) && defined(_M_AMD64)
21 | #include // for _umul128
22 | #pragma intrinsic(_umul128)
23 | #endif
24 |
25 | RAPIDJSON_NAMESPACE_BEGIN
26 | namespace internal {
27 |
28 | class BigInteger {
29 | public:
30 | typedef uint64_t Type;
31 |
32 | BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
33 | std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
34 | }
35 |
36 | explicit BigInteger(uint64_t u) : count_(1) {
37 | digits_[0] = u;
38 | }
39 |
40 | BigInteger(const char* decimals, size_t length) : count_(1) {
41 | RAPIDJSON_ASSERT(length > 0);
42 | digits_[0] = 0;
43 | size_t i = 0;
44 | const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
45 | while (length >= kMaxDigitPerIteration) {
46 | AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
47 | length -= kMaxDigitPerIteration;
48 | i += kMaxDigitPerIteration;
49 | }
50 |
51 | if (length > 0)
52 | AppendDecimal64(decimals + i, decimals + i + length);
53 | }
54 |
55 | BigInteger& operator=(const BigInteger &rhs)
56 | {
57 | if (this != &rhs) {
58 | count_ = rhs.count_;
59 | std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
60 | }
61 | return *this;
62 | }
63 |
64 | BigInteger& operator=(uint64_t u) {
65 | digits_[0] = u;
66 | count_ = 1;
67 | return *this;
68 | }
69 |
70 | BigInteger& operator+=(uint64_t u) {
71 | Type backup = digits_[0];
72 | digits_[0] += u;
73 | for (size_t i = 0; i < count_ - 1; i++) {
74 | if (digits_[i] >= backup)
75 | return *this; // no carry
76 | backup = digits_[i + 1];
77 | digits_[i + 1] += 1;
78 | }
79 |
80 | // Last carry
81 | if (digits_[count_ - 1] < backup)
82 | PushBack(1);
83 |
84 | return *this;
85 | }
86 |
87 | BigInteger& operator*=(uint64_t u) {
88 | if (u == 0) return *this = 0;
89 | if (u == 1) return *this;
90 | if (*this == 1) return *this = u;
91 |
92 | uint64_t k = 0;
93 | for (size_t i = 0; i < count_; i++) {
94 | uint64_t hi;
95 | digits_[i] = MulAdd64(digits_[i], u, k, &hi);
96 | k = hi;
97 | }
98 |
99 | if (k > 0)
100 | PushBack(k);
101 |
102 | return *this;
103 | }
104 |
105 | BigInteger& operator*=(uint32_t u) {
106 | if (u == 0) return *this = 0;
107 | if (u == 1) return *this;
108 | if (*this == 1) return *this = u;
109 |
110 | uint64_t k = 0;
111 | for (size_t i = 0; i < count_; i++) {
112 | const uint64_t c = digits_[i] >> 32;
113 | const uint64_t d = digits_[i] & 0xFFFFFFFF;
114 | const uint64_t uc = u * c;
115 | const uint64_t ud = u * d;
116 | const uint64_t p0 = ud + k;
117 | const uint64_t p1 = uc + (p0 >> 32);
118 | digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
119 | k = p1 >> 32;
120 | }
121 |
122 | if (k > 0)
123 | PushBack(k);
124 |
125 | return *this;
126 | }
127 |
128 | BigInteger& operator<<=(size_t shift) {
129 | if (IsZero() || shift == 0) return *this;
130 |
131 | size_t offset = shift / kTypeBit;
132 | size_t interShift = shift % kTypeBit;
133 | RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
134 |
135 | if (interShift == 0) {
136 | std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
137 | count_ += offset;
138 | }
139 | else {
140 | digits_[count_] = 0;
141 | for (size_t i = count_; i > 0; i--)
142 | digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
143 | digits_[offset] = digits_[0] << interShift;
144 | count_ += offset;
145 | if (digits_[count_])
146 | count_++;
147 | }
148 |
149 | std::memset(digits_, 0, offset * sizeof(Type));
150 |
151 | return *this;
152 | }
153 |
154 | bool operator==(const BigInteger& rhs) const {
155 | return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
156 | }
157 |
158 | bool operator==(const Type rhs) const {
159 | return count_ == 1 && digits_[0] == rhs;
160 | }
161 |
162 | BigInteger& MultiplyPow5(unsigned exp) {
163 | static const uint32_t kPow5[12] = {
164 | 5,
165 | 5 * 5,
166 | 5 * 5 * 5,
167 | 5 * 5 * 5 * 5,
168 | 5 * 5 * 5 * 5 * 5,
169 | 5 * 5 * 5 * 5 * 5 * 5,
170 | 5 * 5 * 5 * 5 * 5 * 5 * 5,
171 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
172 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
173 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
174 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
175 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
176 | };
177 | if (exp == 0) return *this;
178 | for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
179 | for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13
180 | if (exp > 0) *this *= kPow5[exp - 1];
181 | return *this;
182 | }
183 |
184 | // Compute absolute difference of this and rhs.
185 | // Assume this != rhs
186 | bool Difference(const BigInteger& rhs, BigInteger* out) const {
187 | int cmp = Compare(rhs);
188 | RAPIDJSON_ASSERT(cmp != 0);
189 | const BigInteger *a, *b; // Makes a > b
190 | bool ret;
191 | if (cmp < 0) { a = &rhs; b = this; ret = true; }
192 | else { a = this; b = &rhs; ret = false; }
193 |
194 | Type borrow = 0;
195 | for (size_t i = 0; i < a->count_; i++) {
196 | Type d = a->digits_[i] - borrow;
197 | if (i < b->count_)
198 | d -= b->digits_[i];
199 | borrow = (d > a->digits_[i]) ? 1 : 0;
200 | out->digits_[i] = d;
201 | if (d != 0)
202 | out->count_ = i + 1;
203 | }
204 |
205 | return ret;
206 | }
207 |
208 | int Compare(const BigInteger& rhs) const {
209 | if (count_ != rhs.count_)
210 | return count_ < rhs.count_ ? -1 : 1;
211 |
212 | for (size_t i = count_; i-- > 0;)
213 | if (digits_[i] != rhs.digits_[i])
214 | return digits_[i] < rhs.digits_[i] ? -1 : 1;
215 |
216 | return 0;
217 | }
218 |
219 | size_t GetCount() const { return count_; }
220 | Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
221 | bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
222 |
223 | private:
224 | void AppendDecimal64(const char* begin, const char* end) {
225 | uint64_t u = ParseUint64(begin, end);
226 | if (IsZero())
227 | *this = u;
228 | else {
229 | unsigned exp = static_cast(end - begin);
230 | (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
231 | }
232 | }
233 |
234 | void PushBack(Type digit) {
235 | RAPIDJSON_ASSERT(count_ < kCapacity);
236 | digits_[count_++] = digit;
237 | }
238 |
239 | static uint64_t ParseUint64(const char* begin, const char* end) {
240 | uint64_t r = 0;
241 | for (const char* p = begin; p != end; ++p) {
242 | RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
243 | r = r * 10u + static_cast(*p - '0');
244 | }
245 | return r;
246 | }
247 |
248 | // Assume a * b + k < 2^128
249 | static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
250 | #if defined(_MSC_VER) && defined(_M_AMD64)
251 | uint64_t low = _umul128(a, b, outHigh) + k;
252 | if (low < k)
253 | (*outHigh)++;
254 | return low;
255 | #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
256 | __extension__ typedef unsigned __int128 uint128;
257 | uint128 p = static_cast(a) * static_cast(b);
258 | p += k;
259 | *outHigh = static_cast(p >> 64);
260 | return static_cast(p);
261 | #else
262 | const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
263 | uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
264 | x1 += (x0 >> 32); // can't give carry
265 | x1 += x2;
266 | if (x1 < x2)
267 | x3 += (static_cast(1) << 32);
268 | uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
269 | uint64_t hi = x3 + (x1 >> 32);
270 |
271 | lo += k;
272 | if (lo < k)
273 | hi++;
274 | *outHigh = hi;
275 | return lo;
276 | #endif
277 | }
278 |
279 | static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
280 | static const size_t kCapacity = kBitCount / sizeof(Type);
281 | static const size_t kTypeBit = sizeof(Type) * 8;
282 |
283 | Type digits_[kCapacity];
284 | size_t count_;
285 | };
286 |
287 | } // namespace internal
288 | RAPIDJSON_NAMESPACE_END
289 |
290 | #endif // RAPIDJSON_BIGINTEGER_H_
291 |
--------------------------------------------------------------------------------
/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. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | // This is a C++ header-only implementation of Grisu2 algorithm from the publication:
16 | // Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
17 | // integers." ACM Sigplan Notices 45.6 (2010): 233-243.
18 |
19 | #ifndef RAPIDJSON_DIYFP_H_
20 | #define RAPIDJSON_DIYFP_H_
21 |
22 | #include "../rapidjson.h"
23 |
24 | #if defined(_MSC_VER) && defined(_M_AMD64)
25 | #include
26 | #pragma intrinsic(_BitScanReverse64)
27 | #pragma intrinsic(_umul128)
28 | #endif
29 |
30 | RAPIDJSON_NAMESPACE_BEGIN
31 | namespace internal {
32 |
33 | #ifdef __GNUC__
34 | RAPIDJSON_DIAG_PUSH
35 | RAPIDJSON_DIAG_OFF(effc++)
36 | #endif
37 |
38 | #ifdef __clang__
39 | RAPIDJSON_DIAG_PUSH
40 | RAPIDJSON_DIAG_OFF(padded)
41 | #endif
42 |
43 | struct DiyFp {
44 | DiyFp() : f(), e() {}
45 |
46 | DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
47 |
48 | explicit DiyFp(double d) {
49 | union {
50 | double d;
51 | uint64_t u64;
52 | } u = { d };
53 |
54 | int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize);
55 | uint64_t significand = (u.u64 & kDpSignificandMask);
56 | if (biased_e != 0) {
57 | f = significand + kDpHiddenBit;
58 | e = biased_e - kDpExponentBias;
59 | }
60 | else {
61 | f = significand;
62 | e = kDpMinExponent + 1;
63 | }
64 | }
65 |
66 | DiyFp operator-(const DiyFp& rhs) const {
67 | return DiyFp(f - rhs.f, e);
68 | }
69 |
70 | DiyFp operator*(const DiyFp& rhs) const {
71 | #if defined(_MSC_VER) && defined(_M_AMD64)
72 | uint64_t h;
73 | uint64_t l = _umul128(f, rhs.f, &h);
74 | if (l & (uint64_t(1) << 63)) // rounding
75 | h++;
76 | return DiyFp(h, e + rhs.e + 64);
77 | #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
78 | __extension__ typedef unsigned __int128 uint128;
79 | uint128 p = static_cast(f) * static_cast(rhs.f);
80 | uint64_t h = static_cast(p >> 64);
81 | uint64_t l = static_cast(p);
82 | if (l & (uint64_t(1) << 63)) // rounding
83 | h++;
84 | return DiyFp(h, e + rhs.e + 64);
85 | #else
86 | const uint64_t M32 = 0xFFFFFFFF;
87 | const uint64_t a = f >> 32;
88 | const uint64_t b = f & M32;
89 | const uint64_t c = rhs.f >> 32;
90 | const uint64_t d = rhs.f & M32;
91 | const uint64_t ac = a * c;
92 | const uint64_t bc = b * c;
93 | const uint64_t ad = a * d;
94 | const uint64_t bd = b * d;
95 | uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
96 | tmp += 1U << 31; /// mult_round
97 | return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
98 | #endif
99 | }
100 |
101 | DiyFp Normalize() const {
102 | #if defined(_MSC_VER) && defined(_M_AMD64)
103 | unsigned long index;
104 | _BitScanReverse64(&index, f);
105 | return DiyFp(f << (63 - index), e - (63 - index));
106 | #elif defined(__GNUC__) && __GNUC__ >= 4
107 | int s = __builtin_clzll(f);
108 | return DiyFp(f << s, e - s);
109 | #else
110 | DiyFp res = *this;
111 | while (!(res.f & (static_cast(1) << 63))) {
112 | res.f <<= 1;
113 | res.e--;
114 | }
115 | return res;
116 | #endif
117 | }
118 |
119 | DiyFp NormalizeBoundary() const {
120 | DiyFp res = *this;
121 | while (!(res.f & (kDpHiddenBit << 1))) {
122 | res.f <<= 1;
123 | res.e--;
124 | }
125 | res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
126 | res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
127 | return res;
128 | }
129 |
130 | void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
131 | DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
132 | DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
133 | mi.f <<= mi.e - pl.e;
134 | mi.e = pl.e;
135 | *plus = pl;
136 | *minus = mi;
137 | }
138 |
139 | double ToDouble() const {
140 | union {
141 | double d;
142 | uint64_t u64;
143 | }u;
144 | const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
145 | static_cast(e + kDpExponentBias);
146 | u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
147 | return u.d;
148 | }
149 |
150 | static const int kDiySignificandSize = 64;
151 | static const int kDpSignificandSize = 52;
152 | static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
153 | static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
154 | static const int kDpMinExponent = -kDpExponentBias;
155 | static const int kDpDenormalExponent = -kDpExponentBias + 1;
156 | static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
157 | static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
158 | static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
159 |
160 | uint64_t f;
161 | int e;
162 | };
163 |
164 | inline DiyFp GetCachedPowerByIndex(size_t index) {
165 | // 10^-348, 10^-340, ..., 10^340
166 | static const uint64_t kCachedPowers_F[] = {
167 | RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
168 | RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
169 | RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
170 | RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
171 | RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
172 | RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
173 | RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
174 | RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
175 | RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
176 | RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
177 | RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
178 | RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
179 | RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
180 | RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
181 | RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
182 | RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
183 | RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
184 | RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
185 | RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
186 | RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
187 | RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
188 | RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
189 | RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
190 | RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
191 | RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
192 | RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
193 | RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
194 | RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
195 | RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
196 | RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
197 | RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
198 | RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
199 | RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
200 | RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
201 | RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
202 | RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
203 | RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
204 | RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
205 | RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
206 | RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
207 | RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
208 | RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
209 | RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
210 | RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
211 | };
212 | static const int16_t kCachedPowers_E[] = {
213 | -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
214 | -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
215 | -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
216 | -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
217 | -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
218 | 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
219 | 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
220 | 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
221 | 907, 933, 960, 986, 1013, 1039, 1066
222 | };
223 | return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
224 | }
225 |
226 | inline DiyFp GetCachedPower(int e, int* K) {
227 |
228 | //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374;
229 | double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
230 | int k = static_cast(dk);
231 | if (dk - k > 0.0)
232 | k++;
233 |
234 | unsigned index = static_cast((k >> 3) + 1);
235 | *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table
236 |
237 | return GetCachedPowerByIndex(index);
238 | }
239 |
240 | inline DiyFp GetCachedPower10(int exp, int *outExp) {
241 | unsigned index = (static_cast(exp) + 348u) / 8u;
242 | *outExp = -348 + static_cast(index) * 8;
243 | return GetCachedPowerByIndex(index);
244 | }
245 |
246 | #ifdef __GNUC__
247 | RAPIDJSON_DIAG_POP
248 | #endif
249 |
250 | #ifdef __clang__
251 | RAPIDJSON_DIAG_POP
252 | RAPIDJSON_DIAG_OFF(padded)
253 | #endif
254 |
255 | } // namespace internal
256 | RAPIDJSON_NAMESPACE_END
257 |
258 | #endif // RAPIDJSON_DIYFP_H_
259 |
--------------------------------------------------------------------------------
/rapidjson/internal/dtoa.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | // This is a C++ header-only implementation of Grisu2 algorithm from the publication:
16 | // Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
17 | // integers." ACM Sigplan Notices 45.6 (2010): 233-243.
18 |
19 | #ifndef RAPIDJSON_DTOA_
20 | #define RAPIDJSON_DTOA_
21 |
22 | #include "itoa.h" // GetDigitsLut()
23 | #include "diyfp.h"
24 | #include "ieee754.h"
25 |
26 | RAPIDJSON_NAMESPACE_BEGIN
27 | namespace internal {
28 |
29 | #ifdef __GNUC__
30 | RAPIDJSON_DIAG_PUSH
31 | RAPIDJSON_DIAG_OFF(effc++)
32 | RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
33 | #endif
34 |
35 | inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
36 | while (rest < wp_w && delta - rest >= ten_kappa &&
37 | (rest + ten_kappa < wp_w || /// closer
38 | wp_w - rest > rest + ten_kappa - wp_w)) {
39 | buffer[len - 1]--;
40 | rest += ten_kappa;
41 | }
42 | }
43 |
44 | inline int CountDecimalDigit32(uint32_t n) {
45 | // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
46 | if (n < 10) return 1;
47 | if (n < 100) return 2;
48 | if (n < 1000) return 3;
49 | if (n < 10000) return 4;
50 | if (n < 100000) return 5;
51 | if (n < 1000000) return 6;
52 | if (n < 10000000) return 7;
53 | if (n < 100000000) return 8;
54 | // Will not reach 10 digits in DigitGen()
55 | //if (n < 1000000000) return 9;
56 | //return 10;
57 | return 9;
58 | }
59 |
60 | inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
61 | static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
62 | const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
63 | const DiyFp wp_w = Mp - W;
64 | uint32_t p1 = static_cast(Mp.f >> -one.e);
65 | uint64_t p2 = Mp.f & (one.f - 1);
66 | int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
67 | *len = 0;
68 |
69 | while (kappa > 0) {
70 | uint32_t d = 0;
71 | switch (kappa) {
72 | case 9: d = p1 / 100000000; p1 %= 100000000; break;
73 | case 8: d = p1 / 10000000; p1 %= 10000000; break;
74 | case 7: d = p1 / 1000000; p1 %= 1000000; break;
75 | case 6: d = p1 / 100000; p1 %= 100000; break;
76 | case 5: d = p1 / 10000; p1 %= 10000; break;
77 | case 4: d = p1 / 1000; p1 %= 1000; break;
78 | case 3: d = p1 / 100; p1 %= 100; break;
79 | case 2: d = p1 / 10; p1 %= 10; break;
80 | case 1: d = p1; p1 = 0; break;
81 | default:;
82 | }
83 | if (d || *len)
84 | buffer[(*len)++] = static_cast('0' + static_cast(d));
85 | kappa--;
86 | uint64_t tmp = (static_cast(p1) << -one.e) + p2;
87 | if (tmp <= delta) {
88 | *K += kappa;
89 | GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f);
90 | return;
91 | }
92 | }
93 |
94 | // kappa = 0
95 | for (;;) {
96 | p2 *= 10;
97 | delta *= 10;
98 | char d = static_cast(p2 >> -one.e);
99 | if (d || *len)
100 | buffer[(*len)++] = static_cast('0' + d);
101 | p2 &= one.f - 1;
102 | kappa--;
103 | if (p2 < delta) {
104 | *K += kappa;
105 | int index = -kappa;
106 | GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0));
107 | return;
108 | }
109 | }
110 | }
111 |
112 | inline void Grisu2(double value, char* buffer, int* length, int* K) {
113 | const DiyFp v(value);
114 | DiyFp w_m, w_p;
115 | v.NormalizedBoundaries(&w_m, &w_p);
116 |
117 | const DiyFp c_mk = GetCachedPower(w_p.e, K);
118 | const DiyFp W = v.Normalize() * c_mk;
119 | DiyFp Wp = w_p * c_mk;
120 | DiyFp Wm = w_m * c_mk;
121 | Wm.f++;
122 | Wp.f--;
123 | DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
124 | }
125 |
126 | inline char* WriteExponent(int K, char* buffer) {
127 | if (K < 0) {
128 | *buffer++ = '-';
129 | K = -K;
130 | }
131 |
132 | if (K >= 100) {
133 | *buffer++ = static_cast('0' + static_cast(K / 100));
134 | K %= 100;
135 | const char* d = GetDigitsLut() + K * 2;
136 | *buffer++ = d[0];
137 | *buffer++ = d[1];
138 | }
139 | else if (K >= 10) {
140 | const char* d = GetDigitsLut() + K * 2;
141 | *buffer++ = d[0];
142 | *buffer++ = d[1];
143 | }
144 | else
145 | *buffer++ = static_cast('0' + static_cast(K));
146 |
147 | return buffer;
148 | }
149 |
150 | inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
151 | const int kk = length + k; // 10^(kk-1) <= v < 10^kk
152 |
153 | if (0 <= k && kk <= 21) {
154 | // 1234e7 -> 12340000000
155 | for (int i = length; i < kk; i++)
156 | buffer[i] = '0';
157 | buffer[kk] = '.';
158 | buffer[kk + 1] = '0';
159 | return &buffer[kk + 2];
160 | }
161 | else if (0 < kk && kk <= 21) {
162 | // 1234e-2 -> 12.34
163 | std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk));
164 | buffer[kk] = '.';
165 | if (0 > k + maxDecimalPlaces) {
166 | // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
167 | // Remove extra trailing zeros (at least one) after truncation.
168 | for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
169 | if (buffer[i] != '0')
170 | return &buffer[i + 1];
171 | return &buffer[kk + 2]; // Reserve one zero
172 | }
173 | else
174 | return &buffer[length + 1];
175 | }
176 | else if (-6 < kk && kk <= 0) {
177 | // 1234e-6 -> 0.001234
178 | const int offset = 2 - kk;
179 | std::memmove(&buffer[offset], &buffer[0], static_cast(length));
180 | buffer[0] = '0';
181 | buffer[1] = '.';
182 | for (int i = 2; i < offset; i++)
183 | buffer[i] = '0';
184 | if (length - kk > maxDecimalPlaces) {
185 | // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
186 | // Remove extra trailing zeros (at least one) after truncation.
187 | for (int i = maxDecimalPlaces + 1; i > 2; i--)
188 | if (buffer[i] != '0')
189 | return &buffer[i + 1];
190 | return &buffer[3]; // Reserve one zero
191 | }
192 | else
193 | return &buffer[length + offset];
194 | }
195 | else if (kk < -maxDecimalPlaces) {
196 | // Truncate to zero
197 | buffer[0] = '0';
198 | buffer[1] = '.';
199 | buffer[2] = '0';
200 | return &buffer[3];
201 | }
202 | else if (length == 1) {
203 | // 1e30
204 | buffer[1] = 'e';
205 | return WriteExponent(kk - 1, &buffer[2]);
206 | }
207 | else {
208 | // 1234e30 -> 1.234e33
209 | std::memmove(&buffer[2], &buffer[1], static_cast(length - 1));
210 | buffer[1] = '.';
211 | buffer[length + 1] = 'e';
212 | return WriteExponent(kk - 1, &buffer[0 + length + 2]);
213 | }
214 | }
215 |
216 | inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
217 | RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
218 | Double d(value);
219 | if (d.IsZero()) {
220 | if (d.Sign())
221 | *buffer++ = '-'; // -0.0, Issue #289
222 | buffer[0] = '0';
223 | buffer[1] = '.';
224 | buffer[2] = '0';
225 | return &buffer[3];
226 | }
227 | else {
228 | if (value < 0) {
229 | *buffer++ = '-';
230 | value = -value;
231 | }
232 | int length, K;
233 | Grisu2(value, buffer, &length, &K);
234 | return Prettify(buffer, length, K, maxDecimalPlaces);
235 | }
236 | }
237 |
238 | #ifdef __GNUC__
239 | RAPIDJSON_DIAG_POP
240 | #endif
241 |
242 | } // namespace internal
243 | RAPIDJSON_NAMESPACE_END
244 |
245 | #endif // RAPIDJSON_DTOA_
246 |
--------------------------------------------------------------------------------
/rapidjson/internal/ieee754.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_IEEE754_
16 | #define RAPIDJSON_IEEE754_
17 |
18 | #include "../rapidjson.h"
19 |
20 | RAPIDJSON_NAMESPACE_BEGIN
21 | namespace internal {
22 |
23 | class Double {
24 | public:
25 | Double() {}
26 | Double(double d) : d_(d) {}
27 | Double(uint64_t u) : u_(u) {}
28 |
29 | double Value() const { return d_; }
30 | uint64_t Uint64Value() const { return u_; }
31 |
32 | double NextPositiveDouble() const {
33 | RAPIDJSON_ASSERT(!Sign());
34 | return Double(u_ + 1).Value();
35 | }
36 |
37 | bool Sign() const { return (u_ & kSignMask) != 0; }
38 | uint64_t Significand() const { return u_ & kSignificandMask; }
39 | int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
40 |
41 | bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
42 | bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
43 | bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
44 | bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
45 | bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
46 |
47 | uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
48 | int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
49 | uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
50 |
51 | static int EffectiveSignificandSize(int order) {
52 | if (order >= -1021)
53 | return 53;
54 | else if (order <= -1074)
55 | return 0;
56 | else
57 | return order + 1074;
58 | }
59 |
60 | private:
61 | static const int kSignificandSize = 52;
62 | static const int kExponentBias = 0x3FF;
63 | static const int kDenormalExponent = 1 - kExponentBias;
64 | static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
65 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
66 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
67 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
68 |
69 | union {
70 | double d_;
71 | uint64_t u_;
72 | };
73 | };
74 |
75 | } // namespace internal
76 | RAPIDJSON_NAMESPACE_END
77 |
78 | #endif // RAPIDJSON_IEEE754_
79 |
--------------------------------------------------------------------------------
/rapidjson/internal/itoa.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_ITOA_
16 | #define RAPIDJSON_ITOA_
17 |
18 | #include "../rapidjson.h"
19 |
20 | RAPIDJSON_NAMESPACE_BEGIN
21 | namespace internal {
22 |
23 | inline const char* GetDigitsLut() {
24 | static const char cDigitsLut[200] = {
25 | '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
26 | '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
27 | '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
28 | '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
29 | '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
30 | '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
31 | '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
32 | '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
33 | '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
34 | '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
35 | };
36 | return cDigitsLut;
37 | }
38 |
39 | inline char* u32toa(uint32_t value, char* buffer) {
40 | const char* cDigitsLut = GetDigitsLut();
41 |
42 | if (value < 10000) {
43 | const uint32_t d1 = (value / 100) << 1;
44 | const uint32_t d2 = (value % 100) << 1;
45 |
46 | if (value >= 1000)
47 | *buffer++ = cDigitsLut[d1];
48 | if (value >= 100)
49 | *buffer++ = cDigitsLut[d1 + 1];
50 | if (value >= 10)
51 | *buffer++ = cDigitsLut[d2];
52 | *buffer++ = cDigitsLut[d2 + 1];
53 | }
54 | else if (value < 100000000) {
55 | // value = bbbbcccc
56 | const uint32_t b = value / 10000;
57 | const uint32_t c = value % 10000;
58 |
59 | const uint32_t d1 = (b / 100) << 1;
60 | const uint32_t d2 = (b % 100) << 1;
61 |
62 | const uint32_t d3 = (c / 100) << 1;
63 | const uint32_t d4 = (c % 100) << 1;
64 |
65 | if (value >= 10000000)
66 | *buffer++ = cDigitsLut[d1];
67 | if (value >= 1000000)
68 | *buffer++ = cDigitsLut[d1 + 1];
69 | if (value >= 100000)
70 | *buffer++ = cDigitsLut[d2];
71 | *buffer++ = cDigitsLut[d2 + 1];
72 |
73 | *buffer++ = cDigitsLut[d3];
74 | *buffer++ = cDigitsLut[d3 + 1];
75 | *buffer++ = cDigitsLut[d4];
76 | *buffer++ = cDigitsLut[d4 + 1];
77 | }
78 | else {
79 | // value = aabbbbcccc in decimal
80 |
81 | const uint32_t a = value / 100000000; // 1 to 42
82 | value %= 100000000;
83 |
84 | if (a >= 10) {
85 | const unsigned i = a << 1;
86 | *buffer++ = cDigitsLut[i];
87 | *buffer++ = cDigitsLut[i + 1];
88 | }
89 | else
90 | *buffer++ = static_cast('0' + static_cast(a));
91 |
92 | const uint32_t b = value / 10000; // 0 to 9999
93 | const uint32_t c = value % 10000; // 0 to 9999
94 |
95 | const uint32_t d1 = (b / 100) << 1;
96 | const uint32_t d2 = (b % 100) << 1;
97 |
98 | const uint32_t d3 = (c / 100) << 1;
99 | const uint32_t d4 = (c % 100) << 1;
100 |
101 | *buffer++ = cDigitsLut[d1];
102 | *buffer++ = cDigitsLut[d1 + 1];
103 | *buffer++ = cDigitsLut[d2];
104 | *buffer++ = cDigitsLut[d2 + 1];
105 | *buffer++ = cDigitsLut[d3];
106 | *buffer++ = cDigitsLut[d3 + 1];
107 | *buffer++ = cDigitsLut[d4];
108 | *buffer++ = cDigitsLut[d4 + 1];
109 | }
110 | return buffer;
111 | }
112 |
113 | inline char* i32toa(int32_t value, char* buffer) {
114 | uint32_t u = static_cast(value);
115 | if (value < 0) {
116 | *buffer++ = '-';
117 | u = ~u + 1;
118 | }
119 |
120 | return u32toa(u, buffer);
121 | }
122 |
123 | inline char* u64toa(uint64_t value, char* buffer) {
124 | const char* cDigitsLut = GetDigitsLut();
125 | const uint64_t kTen8 = 100000000;
126 | const uint64_t kTen9 = kTen8 * 10;
127 | const uint64_t kTen10 = kTen8 * 100;
128 | const uint64_t kTen11 = kTen8 * 1000;
129 | const uint64_t kTen12 = kTen8 * 10000;
130 | const uint64_t kTen13 = kTen8 * 100000;
131 | const uint64_t kTen14 = kTen8 * 1000000;
132 | const uint64_t kTen15 = kTen8 * 10000000;
133 | const uint64_t kTen16 = kTen8 * kTen8;
134 |
135 | if (value < kTen8) {
136 | uint32_t v = static_cast(value);
137 | if (v < 10000) {
138 | const uint32_t d1 = (v / 100) << 1;
139 | const uint32_t d2 = (v % 100) << 1;
140 |
141 | if (v >= 1000)
142 | *buffer++ = cDigitsLut[d1];
143 | if (v >= 100)
144 | *buffer++ = cDigitsLut[d1 + 1];
145 | if (v >= 10)
146 | *buffer++ = cDigitsLut[d2];
147 | *buffer++ = cDigitsLut[d2 + 1];
148 | }
149 | else {
150 | // value = bbbbcccc
151 | const uint32_t b = v / 10000;
152 | const uint32_t c = v % 10000;
153 |
154 | const uint32_t d1 = (b / 100) << 1;
155 | const uint32_t d2 = (b % 100) << 1;
156 |
157 | const uint32_t d3 = (c / 100) << 1;
158 | const uint32_t d4 = (c % 100) << 1;
159 |
160 | if (value >= 10000000)
161 | *buffer++ = cDigitsLut[d1];
162 | if (value >= 1000000)
163 | *buffer++ = cDigitsLut[d1 + 1];
164 | if (value >= 100000)
165 | *buffer++ = cDigitsLut[d2];
166 | *buffer++ = cDigitsLut[d2 + 1];
167 |
168 | *buffer++ = cDigitsLut[d3];
169 | *buffer++ = cDigitsLut[d3 + 1];
170 | *buffer++ = cDigitsLut[d4];
171 | *buffer++ = cDigitsLut[d4 + 1];
172 | }
173 | }
174 | else if (value < kTen16) {
175 | const uint32_t v0 = static_cast(value / kTen8);
176 | const uint32_t v1 = static_cast(value % kTen8);
177 |
178 | const uint32_t b0 = v0 / 10000;
179 | const uint32_t c0 = v0 % 10000;
180 |
181 | const uint32_t d1 = (b0 / 100) << 1;
182 | const uint32_t d2 = (b0 % 100) << 1;
183 |
184 | const uint32_t d3 = (c0 / 100) << 1;
185 | const uint32_t d4 = (c0 % 100) << 1;
186 |
187 | const uint32_t b1 = v1 / 10000;
188 | const uint32_t c1 = v1 % 10000;
189 |
190 | const uint32_t d5 = (b1 / 100) << 1;
191 | const uint32_t d6 = (b1 % 100) << 1;
192 |
193 | const uint32_t d7 = (c1 / 100) << 1;
194 | const uint32_t d8 = (c1 % 100) << 1;
195 |
196 | if (value >= kTen15)
197 | *buffer++ = cDigitsLut[d1];
198 | if (value >= kTen14)
199 | *buffer++ = cDigitsLut[d1 + 1];
200 | if (value >= kTen13)
201 | *buffer++ = cDigitsLut[d2];
202 | if (value >= kTen12)
203 | *buffer++ = cDigitsLut[d2 + 1];
204 | if (value >= kTen11)
205 | *buffer++ = cDigitsLut[d3];
206 | if (value >= kTen10)
207 | *buffer++ = cDigitsLut[d3 + 1];
208 | if (value >= kTen9)
209 | *buffer++ = cDigitsLut[d4];
210 | if (value >= kTen8)
211 | *buffer++ = cDigitsLut[d4 + 1];
212 |
213 | *buffer++ = cDigitsLut[d5];
214 | *buffer++ = cDigitsLut[d5 + 1];
215 | *buffer++ = cDigitsLut[d6];
216 | *buffer++ = cDigitsLut[d6 + 1];
217 | *buffer++ = cDigitsLut[d7];
218 | *buffer++ = cDigitsLut[d7 + 1];
219 | *buffer++ = cDigitsLut[d8];
220 | *buffer++ = cDigitsLut[d8 + 1];
221 | }
222 | else {
223 | const uint32_t a = static_cast(value / kTen16); // 1 to 1844
224 | value %= kTen16;
225 |
226 | if (a < 10)
227 | *buffer++ = static_cast('0' + static_cast(a));
228 | else if (a < 100) {
229 | const uint32_t i = a << 1;
230 | *buffer++ = cDigitsLut[i];
231 | *buffer++ = cDigitsLut[i + 1];
232 | }
233 | else if (a < 1000) {
234 | *buffer++ = static_cast('0' + static_cast(a / 100));
235 |
236 | const uint32_t i = (a % 100) << 1;
237 | *buffer++ = cDigitsLut[i];
238 | *buffer++ = cDigitsLut[i + 1];
239 | }
240 | else {
241 | const uint32_t i = (a / 100) << 1;
242 | const uint32_t j = (a % 100) << 1;
243 | *buffer++ = cDigitsLut[i];
244 | *buffer++ = cDigitsLut[i + 1];
245 | *buffer++ = cDigitsLut[j];
246 | *buffer++ = cDigitsLut[j + 1];
247 | }
248 |
249 | const uint32_t v0 = static_cast(value / kTen8);
250 | const uint32_t v1 = static_cast(value % kTen8);
251 |
252 | const uint32_t b0 = v0 / 10000;
253 | const uint32_t c0 = v0 % 10000;
254 |
255 | const uint32_t d1 = (b0 / 100) << 1;
256 | const uint32_t d2 = (b0 % 100) << 1;
257 |
258 | const uint32_t d3 = (c0 / 100) << 1;
259 | const uint32_t d4 = (c0 % 100) << 1;
260 |
261 | const uint32_t b1 = v1 / 10000;
262 | const uint32_t c1 = v1 % 10000;
263 |
264 | const uint32_t d5 = (b1 / 100) << 1;
265 | const uint32_t d6 = (b1 % 100) << 1;
266 |
267 | const uint32_t d7 = (c1 / 100) << 1;
268 | const uint32_t d8 = (c1 % 100) << 1;
269 |
270 | *buffer++ = cDigitsLut[d1];
271 | *buffer++ = cDigitsLut[d1 + 1];
272 | *buffer++ = cDigitsLut[d2];
273 | *buffer++ = cDigitsLut[d2 + 1];
274 | *buffer++ = cDigitsLut[d3];
275 | *buffer++ = cDigitsLut[d3 + 1];
276 | *buffer++ = cDigitsLut[d4];
277 | *buffer++ = cDigitsLut[d4 + 1];
278 | *buffer++ = cDigitsLut[d5];
279 | *buffer++ = cDigitsLut[d5 + 1];
280 | *buffer++ = cDigitsLut[d6];
281 | *buffer++ = cDigitsLut[d6 + 1];
282 | *buffer++ = cDigitsLut[d7];
283 | *buffer++ = cDigitsLut[d7 + 1];
284 | *buffer++ = cDigitsLut[d8];
285 | *buffer++ = cDigitsLut[d8 + 1];
286 | }
287 |
288 | return buffer;
289 | }
290 |
291 | inline char* i64toa(int64_t value, char* buffer) {
292 | uint64_t u = static_cast(value);
293 | if (value < 0) {
294 | *buffer++ = '-';
295 | u = ~u + 1;
296 | }
297 |
298 | return u64toa(u, buffer);
299 | }
300 |
301 | } // namespace internal
302 | RAPIDJSON_NAMESPACE_END
303 |
304 | #endif // RAPIDJSON_ITOA_
305 |
--------------------------------------------------------------------------------
/rapidjson/internal/meta.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_INTERNAL_META_H_
16 | #define RAPIDJSON_INTERNAL_META_H_
17 |
18 | #include "../rapidjson.h"
19 |
20 | #ifdef __GNUC__
21 | RAPIDJSON_DIAG_PUSH
22 | RAPIDJSON_DIAG_OFF(effc++)
23 | #endif
24 | #if defined(_MSC_VER)
25 | RAPIDJSON_DIAG_PUSH
26 | RAPIDJSON_DIAG_OFF(6334)
27 | #endif
28 |
29 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS
30 | #include
31 | #endif
32 |
33 | //@cond RAPIDJSON_INTERNAL
34 | RAPIDJSON_NAMESPACE_BEGIN
35 | namespace internal {
36 |
37 | // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
38 | template struct Void { typedef void Type; };
39 |
40 | ///////////////////////////////////////////////////////////////////////////////
41 | // BoolType, TrueType, FalseType
42 | //
43 | template struct BoolType {
44 | static const bool Value = Cond;
45 | typedef BoolType Type;
46 | };
47 | typedef BoolType TrueType;
48 | typedef BoolType FalseType;
49 |
50 |
51 | ///////////////////////////////////////////////////////////////////////////////
52 | // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
53 | //
54 |
55 | template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; };
56 | template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; };
57 | template struct SelectIfCond : SelectIfImpl::template Apply {};
58 | template struct SelectIf : SelectIfCond {};
59 |
60 | template struct AndExprCond : FalseType {};
61 | template <> struct AndExprCond : TrueType {};
62 | template struct OrExprCond : TrueType {};
63 | template <> struct OrExprCond : FalseType {};
64 |
65 | template struct BoolExpr : SelectIf::Type {};
66 | template struct NotExpr : SelectIf::Type {};
67 | template struct AndExpr : AndExprCond::Type {};
68 | template struct OrExpr : OrExprCond::Type {};
69 |
70 |
71 | ///////////////////////////////////////////////////////////////////////////////
72 | // AddConst, MaybeAddConst, RemoveConst
73 | template struct AddConst { typedef const T Type; };
74 | template struct MaybeAddConst : SelectIfCond {};
75 | template struct RemoveConst { typedef T Type; };
76 | template struct RemoveConst { typedef T Type; };
77 |
78 |
79 | ///////////////////////////////////////////////////////////////////////////////
80 | // IsSame, IsConst, IsMoreConst, IsPointer
81 | //
82 | template struct IsSame : FalseType {};
83 | template struct IsSame : TrueType {};
84 |
85 | template struct IsConst : FalseType {};
86 | template struct IsConst : TrueType {};
87 |
88 | template
89 | struct IsMoreConst
90 | : AndExpr::Type, typename RemoveConst::Type>,
91 | BoolType::Value >= IsConst::Value> >::Type {};
92 |
93 | template struct IsPointer : FalseType {};
94 | template struct IsPointer : TrueType {};
95 |
96 | ///////////////////////////////////////////////////////////////////////////////
97 | // IsBaseOf
98 | //
99 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS
100 |
101 | template struct IsBaseOf
102 | : BoolType< ::std::is_base_of::value> {};
103 |
104 | #else // simplified version adopted from Boost
105 |
106 | template struct IsBaseOfImpl {
107 | RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
108 | RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
109 |
110 | typedef char (&Yes)[1];
111 | typedef char (&No) [2];
112 |
113 | template
114 | static Yes Check(const D*, T);
115 | static No Check(const B*, int);
116 |
117 | struct Host {
118 | operator const B*() const;
119 | operator const D*();
120 | };
121 |
122 | enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
123 | };
124 |
125 | template struct IsBaseOf
126 | : OrExpr, BoolExpr > >::Type {};
127 |
128 | #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
129 |
130 |
131 | //////////////////////////////////////////////////////////////////////////
132 | // EnableIf / DisableIf
133 | //
134 | template struct EnableIfCond { typedef T Type; };
135 | template struct EnableIfCond { /* empty */ };
136 |
137 | template struct DisableIfCond { typedef T Type; };
138 | template struct DisableIfCond { /* empty */ };
139 |
140 | template
141 | struct EnableIf : EnableIfCond {};
142 |
143 | template
144 | struct DisableIf : DisableIfCond {};
145 |
146 | // SFINAE helpers
147 | struct SfinaeTag {};
148 | template struct RemoveSfinaeTag;
149 | template struct RemoveSfinaeTag { typedef T Type; };
150 |
151 | #define RAPIDJSON_REMOVEFPTR_(type) \
152 | typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
153 | < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
154 |
155 | #define RAPIDJSON_ENABLEIF(cond) \
156 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
157 | ::Type * = NULL
158 |
159 | #define RAPIDJSON_DISABLEIF(cond) \
160 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
161 | ::Type * = NULL
162 |
163 | #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
164 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
165 | ::Type
167 |
168 | #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
169 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
170 | ::Type
172 |
173 | } // namespace internal
174 | RAPIDJSON_NAMESPACE_END
175 | //@endcond
176 |
177 | #if defined(__GNUC__) || defined(_MSC_VER)
178 | RAPIDJSON_DIAG_POP
179 | #endif
180 |
181 | #endif // RAPIDJSON_INTERNAL_META_H_
182 |
--------------------------------------------------------------------------------
/rapidjson/internal/pow10.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_POW10_
16 | #define RAPIDJSON_POW10_
17 |
18 | #include "../rapidjson.h"
19 |
20 | RAPIDJSON_NAMESPACE_BEGIN
21 | namespace internal {
22 |
23 | //! Computes integer powers of 10 in double (10.0^n).
24 | /*! This function uses lookup table for fast and accurate results.
25 | \param n non-negative exponent. Must <= 308.
26 | \return 10.0^n
27 | */
28 | inline double Pow10(int n) {
29 | static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
30 | 1e+0,
31 | 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
32 | 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
33 | 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
34 | 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
35 | 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
36 | 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
37 | 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
38 | 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
39 | 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
40 | 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
41 | 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
42 | 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
43 | 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
44 | 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
45 | 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
46 | 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
47 | };
48 | RAPIDJSON_ASSERT(n >= 0 && n <= 308);
49 | return e[n];
50 | }
51 |
52 | } // namespace internal
53 | RAPIDJSON_NAMESPACE_END
54 |
55 | #endif // RAPIDJSON_POW10_
56 |
--------------------------------------------------------------------------------
/rapidjson/internal/stack.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_INTERNAL_STACK_H_
16 | #define RAPIDJSON_INTERNAL_STACK_H_
17 |
18 | #include "../allocators.h"
19 | #include "swap.h"
20 |
21 | #if defined(__clang__)
22 | RAPIDJSON_DIAG_PUSH
23 | RAPIDJSON_DIAG_OFF(c++98-compat)
24 | #endif
25 |
26 | RAPIDJSON_NAMESPACE_BEGIN
27 | namespace internal {
28 |
29 | ///////////////////////////////////////////////////////////////////////////////
30 | // Stack
31 |
32 | //! A type-unsafe stack for storing different types of data.
33 | /*! \tparam Allocator Allocator for allocating stack memory.
34 | */
35 | template
36 | class Stack {
37 | public:
38 | // Optimization note: Do not allocate memory for stack_ in constructor.
39 | // Do it lazily when first Push() -> Expand() -> Resize().
40 | Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
41 | }
42 |
43 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
44 | Stack(Stack&& rhs)
45 | : allocator_(rhs.allocator_),
46 | ownAllocator_(rhs.ownAllocator_),
47 | stack_(rhs.stack_),
48 | stackTop_(rhs.stackTop_),
49 | stackEnd_(rhs.stackEnd_),
50 | initialCapacity_(rhs.initialCapacity_)
51 | {
52 | rhs.allocator_ = 0;
53 | rhs.ownAllocator_ = 0;
54 | rhs.stack_ = 0;
55 | rhs.stackTop_ = 0;
56 | rhs.stackEnd_ = 0;
57 | rhs.initialCapacity_ = 0;
58 | }
59 | #endif
60 |
61 | ~Stack() {
62 | Destroy();
63 | }
64 |
65 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
66 | Stack& operator=(Stack&& rhs) {
67 | if (&rhs != this)
68 | {
69 | Destroy();
70 |
71 | allocator_ = rhs.allocator_;
72 | ownAllocator_ = rhs.ownAllocator_;
73 | stack_ = rhs.stack_;
74 | stackTop_ = rhs.stackTop_;
75 | stackEnd_ = rhs.stackEnd_;
76 | initialCapacity_ = rhs.initialCapacity_;
77 |
78 | rhs.allocator_ = 0;
79 | rhs.ownAllocator_ = 0;
80 | rhs.stack_ = 0;
81 | rhs.stackTop_ = 0;
82 | rhs.stackEnd_ = 0;
83 | rhs.initialCapacity_ = 0;
84 | }
85 | return *this;
86 | }
87 | #endif
88 |
89 | void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
90 | internal::Swap(allocator_, rhs.allocator_);
91 | internal::Swap(ownAllocator_, rhs.ownAllocator_);
92 | internal::Swap(stack_, rhs.stack_);
93 | internal::Swap(stackTop_, rhs.stackTop_);
94 | internal::Swap(stackEnd_, rhs.stackEnd_);
95 | internal::Swap(initialCapacity_, rhs.initialCapacity_);
96 | }
97 |
98 | void Clear() { stackTop_ = stack_; }
99 |
100 | void ShrinkToFit() {
101 | if (Empty()) {
102 | // If the stack is empty, completely deallocate the memory.
103 | Allocator::Free(stack_);
104 | stack_ = 0;
105 | stackTop_ = 0;
106 | stackEnd_ = 0;
107 | }
108 | else
109 | Resize(GetSize());
110 | }
111 |
112 | // Optimization note: try to minimize the size of this function for force inline.
113 | // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
114 | template
115 | RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
116 | // Expand the stack if needed
117 | if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
118 | Expand(count);
119 | }
120 |
121 | template
122 | RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
123 | Reserve(count);
124 | return PushUnsafe(count);
125 | }
126 |
127 | template
128 | RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
129 | RAPIDJSON_ASSERT(stackTop_);
130 | RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
131 | T* ret = reinterpret_cast(stackTop_);
132 | stackTop_ += sizeof(T) * count;
133 | return ret;
134 | }
135 |
136 | template
137 | T* Pop(size_t count) {
138 | RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
139 | stackTop_ -= count * sizeof(T);
140 | return reinterpret_cast(stackTop_);
141 | }
142 |
143 | template
144 | T* Top() {
145 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
146 | return reinterpret_cast(stackTop_ - sizeof(T));
147 | }
148 |
149 | template
150 | const T* Top() const {
151 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
152 | return reinterpret_cast(stackTop_ - sizeof(T));
153 | }
154 |
155 | template
156 | T* End() { return reinterpret_cast(stackTop_); }
157 |
158 | template
159 | const T* End() const { return reinterpret_cast(stackTop_); }
160 |
161 | template
162 | T* Bottom() { return reinterpret_cast(stack_); }
163 |
164 | template
165 | const T* Bottom() const { return reinterpret_cast(stack_); }
166 |
167 | bool HasAllocator() const {
168 | return allocator_ != 0;
169 | }
170 |
171 | Allocator& GetAllocator() {
172 | RAPIDJSON_ASSERT(allocator_);
173 | return *allocator_;
174 | }
175 |
176 | bool Empty() const { return stackTop_ == stack_; }
177 | size_t GetSize() const { return static_cast(stackTop_ - stack_); }
178 | size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); }
179 |
180 | private:
181 | template
182 | void Expand(size_t count) {
183 | // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
184 | size_t newCapacity;
185 | if (stack_ == 0) {
186 | if (!allocator_)
187 | ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
188 | newCapacity = initialCapacity_;
189 | } else {
190 | newCapacity = GetCapacity();
191 | newCapacity += (newCapacity + 1) / 2;
192 | }
193 | size_t newSize = GetSize() + sizeof(T) * count;
194 | if (newCapacity < newSize)
195 | newCapacity = newSize;
196 |
197 | Resize(newCapacity);
198 | }
199 |
200 | void Resize(size_t newCapacity) {
201 | const size_t size = GetSize(); // Backup the current size
202 | stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
203 | stackTop_ = stack_ + size;
204 | stackEnd_ = stack_ + newCapacity;
205 | }
206 |
207 | void Destroy() {
208 | Allocator::Free(stack_);
209 | RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
210 | }
211 |
212 | // Prohibit copy constructor & assignment operator.
213 | Stack(const Stack&);
214 | Stack& operator=(const Stack&);
215 |
216 | Allocator* allocator_;
217 | Allocator* ownAllocator_;
218 | char *stack_;
219 | char *stackTop_;
220 | char *stackEnd_;
221 | size_t initialCapacity_;
222 | };
223 |
224 | } // namespace internal
225 | RAPIDJSON_NAMESPACE_END
226 |
227 | #if defined(__clang__)
228 | RAPIDJSON_DIAG_POP
229 | #endif
230 |
231 | #endif // RAPIDJSON_STACK_H_
232 |
--------------------------------------------------------------------------------
/rapidjson/internal/strfunc.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
16 | #define RAPIDJSON_INTERNAL_STRFUNC_H_
17 |
18 | #include "../stream.h"
19 | #include
20 |
21 | RAPIDJSON_NAMESPACE_BEGIN
22 | namespace internal {
23 |
24 | //! Custom strlen() which works on different character types.
25 | /*! \tparam Ch Character type (e.g. char, wchar_t, short)
26 | \param s Null-terminated input string.
27 | \return Number of characters in the string.
28 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
29 | */
30 | template
31 | inline SizeType StrLen(const Ch* s) {
32 | RAPIDJSON_ASSERT(s != 0);
33 | const Ch* p = s;
34 | while (*p) ++p;
35 | return SizeType(p - s);
36 | }
37 |
38 | template <>
39 | inline SizeType StrLen(const char* s) {
40 | return SizeType(std::strlen(s));
41 | }
42 |
43 | template <>
44 | inline SizeType StrLen(const wchar_t* s) {
45 | return SizeType(std::wcslen(s));
46 | }
47 |
48 | //! Returns number of code points in a encoded string.
49 | template
50 | bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
51 | RAPIDJSON_ASSERT(s != 0);
52 | RAPIDJSON_ASSERT(outCount != 0);
53 | GenericStringStream is(s);
54 | const typename Encoding::Ch* end = s + length;
55 | SizeType count = 0;
56 | while (is.src_ < end) {
57 | unsigned codepoint;
58 | if (!Encoding::Decode(is, &codepoint))
59 | return false;
60 | count++;
61 | }
62 | *outCount = count;
63 | return true;
64 | }
65 |
66 | } // namespace internal
67 | RAPIDJSON_NAMESPACE_END
68 |
69 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_
70 |
--------------------------------------------------------------------------------
/rapidjson/internal/strtod.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_STRTOD_
16 | #define RAPIDJSON_STRTOD_
17 |
18 | #include "ieee754.h"
19 | #include "biginteger.h"
20 | #include "diyfp.h"
21 | #include "pow10.h"
22 |
23 | RAPIDJSON_NAMESPACE_BEGIN
24 | namespace internal {
25 |
26 | inline double FastPath(double significand, int exp) {
27 | if (exp < -308)
28 | return 0.0;
29 | else if (exp >= 0)
30 | return significand * internal::Pow10(exp);
31 | else
32 | return significand / internal::Pow10(-exp);
33 | }
34 |
35 | inline double StrtodNormalPrecision(double d, int p) {
36 | if (p < -308) {
37 | // Prevent expSum < -308, making Pow10(p) = 0
38 | d = FastPath(d, -308);
39 | d = FastPath(d, p + 308);
40 | }
41 | else
42 | d = FastPath(d, p);
43 | return d;
44 | }
45 |
46 | template
47 | inline T Min3(T a, T b, T c) {
48 | T m = a;
49 | if (m > b) m = b;
50 | if (m > c) m = c;
51 | return m;
52 | }
53 |
54 | inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
55 | const Double db(b);
56 | const uint64_t bInt = db.IntegerSignificand();
57 | const int bExp = db.IntegerExponent();
58 | const int hExp = bExp - 1;
59 |
60 | int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
61 |
62 | // Adjust for decimal exponent
63 | if (dExp >= 0) {
64 | dS_Exp2 += dExp;
65 | dS_Exp5 += dExp;
66 | }
67 | else {
68 | bS_Exp2 -= dExp;
69 | bS_Exp5 -= dExp;
70 | hS_Exp2 -= dExp;
71 | hS_Exp5 -= dExp;
72 | }
73 |
74 | // Adjust for binary exponent
75 | if (bExp >= 0)
76 | bS_Exp2 += bExp;
77 | else {
78 | dS_Exp2 -= bExp;
79 | hS_Exp2 -= bExp;
80 | }
81 |
82 | // Adjust for half ulp exponent
83 | if (hExp >= 0)
84 | hS_Exp2 += hExp;
85 | else {
86 | dS_Exp2 -= hExp;
87 | bS_Exp2 -= hExp;
88 | }
89 |
90 | // Remove common power of two factor from all three scaled values
91 | int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
92 | dS_Exp2 -= common_Exp2;
93 | bS_Exp2 -= common_Exp2;
94 | hS_Exp2 -= common_Exp2;
95 |
96 | BigInteger dS = d;
97 | dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2);
98 |
99 | BigInteger bS(bInt);
100 | bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2);
101 |
102 | BigInteger hS(1);
103 | hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2);
104 |
105 | BigInteger delta(0);
106 | dS.Difference(bS, &delta);
107 |
108 | return delta.Compare(hS);
109 | }
110 |
111 | inline bool StrtodFast(double d, int p, double* result) {
112 | // Use fast path for string-to-double conversion if possible
113 | // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
114 | if (p > 22 && p < 22 + 16) {
115 | // Fast Path Cases In Disguise
116 | d *= internal::Pow10(p - 22);
117 | p = 22;
118 | }
119 |
120 | if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
121 | *result = FastPath(d, p);
122 | return true;
123 | }
124 | else
125 | return false;
126 | }
127 |
128 | // Compute an approximation and see if it is within 1/2 ULP
129 | inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
130 | uint64_t significand = 0;
131 | size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
132 | for (; i < length; i++) {
133 | if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
134 | (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
135 | break;
136 | significand = significand * 10u + static_cast(decimals[i] - '0');
137 | }
138 |
139 | if (i < length && decimals[i] >= '5') // Rounding
140 | significand++;
141 |
142 | size_t remaining = length - i;
143 | const int kUlpShift = 3;
144 | const int kUlp = 1 << kUlpShift;
145 | int64_t error = (remaining == 0) ? 0 : kUlp / 2;
146 |
147 | DiyFp v(significand, 0);
148 | v = v.Normalize();
149 | error <<= -v.e;
150 |
151 | const int dExp = static_cast(decimalPosition) - static_cast(i) + exp;
152 |
153 | int actualExp;
154 | DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
155 | if (actualExp != dExp) {
156 | static const DiyFp kPow10[] = {
157 | DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
158 | DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
159 | DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
160 | DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
161 | DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
162 | DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
163 | DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
164 | };
165 | int adjustment = dExp - actualExp - 1;
166 | RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
167 | v = v * kPow10[adjustment];
168 | if (length + static_cast(adjustment)> 19u) // has more digits than decimal digits in 64-bit
169 | error += kUlp / 2;
170 | }
171 |
172 | v = v * cachedPower;
173 |
174 | error += kUlp + (error == 0 ? 0 : 1);
175 |
176 | const int oldExp = v.e;
177 | v = v.Normalize();
178 | error <<= oldExp - v.e;
179 |
180 | const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
181 | int precisionSize = 64 - effectiveSignificandSize;
182 | if (precisionSize + kUlpShift >= 64) {
183 | int scaleExp = (precisionSize + kUlpShift) - 63;
184 | v.f >>= scaleExp;
185 | v.e += scaleExp;
186 | error = (error >> scaleExp) + 1 + kUlp;
187 | precisionSize -= scaleExp;
188 | }
189 |
190 | DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
191 | const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
192 | const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
193 | if (precisionBits >= halfWay + static_cast(error)) {
194 | rounded.f++;
195 | if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
196 | rounded.f >>= 1;
197 | rounded.e++;
198 | }
199 | }
200 |
201 | *result = rounded.ToDouble();
202 |
203 | return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error);
204 | }
205 |
206 | inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
207 | const BigInteger dInt(decimals, length);
208 | const int dExp = static_cast(decimalPosition) - static_cast(length) + exp;
209 | Double a(approx);
210 | int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
211 | if (cmp < 0)
212 | return a.Value(); // within half ULP
213 | else if (cmp == 0) {
214 | // Round towards even
215 | if (a.Significand() & 1)
216 | return a.NextPositiveDouble();
217 | else
218 | return a.Value();
219 | }
220 | else // adjustment
221 | return a.NextPositiveDouble();
222 | }
223 |
224 | inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
225 | RAPIDJSON_ASSERT(d >= 0.0);
226 | RAPIDJSON_ASSERT(length >= 1);
227 |
228 | double result;
229 | if (StrtodFast(d, p, &result))
230 | return result;
231 |
232 | // Trim leading zeros
233 | while (*decimals == '0' && length > 1) {
234 | length--;
235 | decimals++;
236 | decimalPosition--;
237 | }
238 |
239 | // Trim trailing zeros
240 | while (decimals[length - 1] == '0' && length > 1) {
241 | length--;
242 | decimalPosition--;
243 | exp++;
244 | }
245 |
246 | // Trim right-most digits
247 | const int kMaxDecimalDigit = 780;
248 | if (static_cast(length) > kMaxDecimalDigit) {
249 | int delta = (static_cast(length) - kMaxDecimalDigit);
250 | exp += delta;
251 | decimalPosition -= static_cast(delta);
252 | length = kMaxDecimalDigit;
253 | }
254 |
255 | // If too small, underflow to zero
256 | if (int(length) + exp < -324)
257 | return 0.0;
258 |
259 | if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
260 | return result;
261 |
262 | // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
263 | return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
264 | }
265 |
266 | } // namespace internal
267 | RAPIDJSON_NAMESPACE_END
268 |
269 | #endif // RAPIDJSON_STRTOD_
270 |
--------------------------------------------------------------------------------
/rapidjson/internal/swap.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_INTERNAL_SWAP_H_
16 | #define RAPIDJSON_INTERNAL_SWAP_H_
17 |
18 | #include "../rapidjson.h"
19 |
20 | #if defined(__clang__)
21 | RAPIDJSON_DIAG_PUSH
22 | RAPIDJSON_DIAG_OFF(c++98-compat)
23 | #endif
24 |
25 | RAPIDJSON_NAMESPACE_BEGIN
26 | namespace internal {
27 |
28 | //! Custom swap() to avoid dependency on C++ header
29 | /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
30 | \note This has the same semantics as std::swap().
31 | */
32 | template
33 | inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
34 | T tmp = a;
35 | a = b;
36 | b = tmp;
37 | }
38 |
39 | } // namespace internal
40 | RAPIDJSON_NAMESPACE_END
41 |
42 | #if defined(__clang__)
43 | RAPIDJSON_DIAG_POP
44 | #endif
45 |
46 | #endif // RAPIDJSON_INTERNAL_SWAP_H_
47 |
--------------------------------------------------------------------------------
/rapidjson/istreamwrapper.h:
--------------------------------------------------------------------------------
1 | // Tencent is pleased to support the open source community by making RapidJSON available.
2 | //
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 | //
5 | // Licensed under the MIT License (the "License"); you may not use this file except
6 | // in compliance with the License. You may obtain a copy of the License at
7 | //
8 | // http://opensource.org/licenses/MIT
9 | //
10 | // Unless required by applicable law or agreed to in writing, software distributed
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 | // specific language governing permissions and limitations under the License.
14 |
15 | #ifndef RAPIDJSON_ISTREAMWRAPPER_H_
16 | #define RAPIDJSON_ISTREAMWRAPPER_H_
17 |
18 | #include "stream.h"
19 | #include
20 |
21 | #ifdef __clang__
22 | RAPIDJSON_DIAG_PUSH
23 | RAPIDJSON_DIAG_OFF(padded)
24 | #endif
25 |
26 | #ifdef _MSC_VER
27 | RAPIDJSON_DIAG_PUSH
28 | RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
29 | #endif
30 |
31 | RAPIDJSON_NAMESPACE_BEGIN
32 |
33 | //! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
34 | /*!
35 | The classes can be wrapped including but not limited to:
36 |
37 | - \c std::istringstream
38 | - \c std::stringstream
39 | - \c std::wistringstream
40 | - \c std::wstringstream
41 | - \c std::ifstream
42 | - \c std::fstream
43 | - \c std::wifstream
44 | - \c std::wfstream
45 |
46 | \tparam StreamType Class derived from \c std::basic_istream.
47 | */
48 |
49 | template
50 | class BasicIStreamWrapper {
51 | public:
52 | typedef typename StreamType::char_type Ch;
53 | BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
54 |
55 | Ch Peek() const {
56 | typename StreamType::int_type c = stream_.peek();
57 | return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast(c) : static_cast('\0');
58 | }
59 |
60 | Ch Take() {
61 | typename StreamType::int_type c = stream_.get();
62 | if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
63 | count_++;
64 | return static_cast(c);
65 | }
66 | else
67 | return '\0';
68 | }
69 |
70 | // tellg() may return -1 when failed. So we count by ourself.
71 | size_t Tell() const { return count_; }
72 |
73 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
74 | void Put(Ch) { RAPIDJSON_ASSERT(false); }
75 | void Flush() { RAPIDJSON_ASSERT(false); }
76 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
77 |
78 | // For encoding detection only.
79 | const Ch* Peek4() const {
80 | RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
81 | int i;
82 | bool hasError = false;
83 | for (i = 0; i < 4; ++i) {
84 | typename StreamType::int_type c = stream_.get();
85 | if (c == StreamType::traits_type::eof()) {
86 | hasError = true;
87 | stream_.clear();
88 | break;
89 | }
90 | peekBuffer_[i] = static_cast(c);
91 | }
92 | for (--i; i >= 0; --i)
93 | stream_.putback(peekBuffer_[i]);
94 | return !hasError ? peekBuffer_ : 0;
95 | }
96 |
97 | private:
98 | BasicIStreamWrapper(const BasicIStreamWrapper&);
99 | BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
100 |
101 | StreamType& stream_;
102 | size_t count_; //!< Number of characters read. Note:
103 | mutable Ch peekBuffer_[4];
104 | };
105 |
106 | typedef BasicIStreamWrapper