/src/rapidjson/include/rapidjson/internal/itoa.h
Line | Count | Source |
1 | | // Tencent is pleased to support the open source community by making RapidJSON available. |
2 | | // |
3 | | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. |
4 | | // |
5 | | // Licensed under the MIT License (the "License"); you may not use this file except |
6 | | // in compliance with the License. You may obtain a copy of the License at |
7 | | // |
8 | | // http://opensource.org/licenses/MIT |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software distributed |
11 | | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
12 | | // CONDITIONS OF ANY KIND, either express or implied. See the License for the |
13 | | // specific language governing permissions and limitations under the License. |
14 | | |
15 | | #ifndef RAPIDJSON_ITOA_ |
16 | | #define RAPIDJSON_ITOA_ |
17 | | |
18 | | #include "../rapidjson.h" |
19 | | |
20 | | RAPIDJSON_NAMESPACE_BEGIN |
21 | | namespace internal { |
22 | | |
23 | 12 | inline const char* GetDigitsLut() { |
24 | 12 | static const char cDigitsLut[200] = { |
25 | 12 | '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', |
26 | 12 | '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', |
27 | 12 | '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', |
28 | 12 | '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', |
29 | 12 | '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', |
30 | 12 | '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', |
31 | 12 | '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', |
32 | 12 | '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', |
33 | 12 | '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', |
34 | 12 | '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' |
35 | 12 | }; |
36 | 12 | return cDigitsLut; |
37 | 12 | } |
38 | | |
39 | 0 | inline char* u32toa(uint32_t value, char* buffer) { |
40 | 0 | RAPIDJSON_ASSERT(buffer != 0); |
41 | | |
42 | 0 | const char* cDigitsLut = GetDigitsLut(); |
43 | |
|
44 | 0 | if (value < 10000) { |
45 | 0 | const uint32_t d1 = (value / 100) << 1; |
46 | 0 | const uint32_t d2 = (value % 100) << 1; |
47 | |
|
48 | 0 | if (value >= 1000) |
49 | 0 | *buffer++ = cDigitsLut[d1]; |
50 | 0 | if (value >= 100) |
51 | 0 | *buffer++ = cDigitsLut[d1 + 1]; |
52 | 0 | if (value >= 10) |
53 | 0 | *buffer++ = cDigitsLut[d2]; |
54 | 0 | *buffer++ = cDigitsLut[d2 + 1]; |
55 | 0 | } |
56 | 0 | else if (value < 100000000) { |
57 | | // value = bbbbcccc |
58 | 0 | const uint32_t b = value / 10000; |
59 | 0 | const uint32_t c = value % 10000; |
60 | |
|
61 | 0 | const uint32_t d1 = (b / 100) << 1; |
62 | 0 | const uint32_t d2 = (b % 100) << 1; |
63 | |
|
64 | 0 | const uint32_t d3 = (c / 100) << 1; |
65 | 0 | const uint32_t d4 = (c % 100) << 1; |
66 | |
|
67 | 0 | if (value >= 10000000) |
68 | 0 | *buffer++ = cDigitsLut[d1]; |
69 | 0 | if (value >= 1000000) |
70 | 0 | *buffer++ = cDigitsLut[d1 + 1]; |
71 | 0 | if (value >= 100000) |
72 | 0 | *buffer++ = cDigitsLut[d2]; |
73 | 0 | *buffer++ = cDigitsLut[d2 + 1]; |
74 | |
|
75 | 0 | *buffer++ = cDigitsLut[d3]; |
76 | 0 | *buffer++ = cDigitsLut[d3 + 1]; |
77 | 0 | *buffer++ = cDigitsLut[d4]; |
78 | 0 | *buffer++ = cDigitsLut[d4 + 1]; |
79 | 0 | } |
80 | 0 | else { |
81 | | // value = aabbbbcccc in decimal |
82 | |
|
83 | 0 | const uint32_t a = value / 100000000; // 1 to 42 |
84 | 0 | value %= 100000000; |
85 | |
|
86 | 0 | if (a >= 10) { |
87 | 0 | const unsigned i = a << 1; |
88 | 0 | *buffer++ = cDigitsLut[i]; |
89 | 0 | *buffer++ = cDigitsLut[i + 1]; |
90 | 0 | } |
91 | 0 | else |
92 | 0 | *buffer++ = static_cast<char>('0' + static_cast<char>(a)); |
93 | |
|
94 | 0 | const uint32_t b = value / 10000; // 0 to 9999 |
95 | 0 | const uint32_t c = value % 10000; // 0 to 9999 |
96 | |
|
97 | 0 | const uint32_t d1 = (b / 100) << 1; |
98 | 0 | const uint32_t d2 = (b % 100) << 1; |
99 | |
|
100 | 0 | const uint32_t d3 = (c / 100) << 1; |
101 | 0 | const uint32_t d4 = (c % 100) << 1; |
102 | |
|
103 | 0 | *buffer++ = cDigitsLut[d1]; |
104 | 0 | *buffer++ = cDigitsLut[d1 + 1]; |
105 | 0 | *buffer++ = cDigitsLut[d2]; |
106 | 0 | *buffer++ = cDigitsLut[d2 + 1]; |
107 | 0 | *buffer++ = cDigitsLut[d3]; |
108 | 0 | *buffer++ = cDigitsLut[d3 + 1]; |
109 | 0 | *buffer++ = cDigitsLut[d4]; |
110 | 0 | *buffer++ = cDigitsLut[d4 + 1]; |
111 | 0 | } |
112 | 0 | return buffer; |
113 | 0 | } |
114 | | |
115 | 0 | inline char* i32toa(int32_t value, char* buffer) { |
116 | 0 | RAPIDJSON_ASSERT(buffer != 0); |
117 | 0 | uint32_t u = static_cast<uint32_t>(value); |
118 | 0 | if (value < 0) { |
119 | 0 | *buffer++ = '-'; |
120 | 0 | u = ~u + 1; |
121 | 0 | } |
122 | |
|
123 | 0 | return u32toa(u, buffer); |
124 | 0 | } |
125 | | |
126 | 0 | inline char* u64toa(uint64_t value, char* buffer) { |
127 | 0 | RAPIDJSON_ASSERT(buffer != 0); |
128 | 0 | const char* cDigitsLut = GetDigitsLut(); |
129 | 0 | const uint64_t kTen8 = 100000000; |
130 | 0 | const uint64_t kTen9 = kTen8 * 10; |
131 | 0 | const uint64_t kTen10 = kTen8 * 100; |
132 | 0 | const uint64_t kTen11 = kTen8 * 1000; |
133 | 0 | const uint64_t kTen12 = kTen8 * 10000; |
134 | 0 | const uint64_t kTen13 = kTen8 * 100000; |
135 | 0 | const uint64_t kTen14 = kTen8 * 1000000; |
136 | 0 | const uint64_t kTen15 = kTen8 * 10000000; |
137 | 0 | const uint64_t kTen16 = kTen8 * kTen8; |
138 | |
|
139 | 0 | if (value < kTen8) { |
140 | 0 | uint32_t v = static_cast<uint32_t>(value); |
141 | 0 | if (v < 10000) { |
142 | 0 | const uint32_t d1 = (v / 100) << 1; |
143 | 0 | const uint32_t d2 = (v % 100) << 1; |
144 | |
|
145 | 0 | if (v >= 1000) |
146 | 0 | *buffer++ = cDigitsLut[d1]; |
147 | 0 | if (v >= 100) |
148 | 0 | *buffer++ = cDigitsLut[d1 + 1]; |
149 | 0 | if (v >= 10) |
150 | 0 | *buffer++ = cDigitsLut[d2]; |
151 | 0 | *buffer++ = cDigitsLut[d2 + 1]; |
152 | 0 | } |
153 | 0 | else { |
154 | | // value = bbbbcccc |
155 | 0 | const uint32_t b = v / 10000; |
156 | 0 | const uint32_t c = v % 10000; |
157 | |
|
158 | 0 | const uint32_t d1 = (b / 100) << 1; |
159 | 0 | const uint32_t d2 = (b % 100) << 1; |
160 | |
|
161 | 0 | const uint32_t d3 = (c / 100) << 1; |
162 | 0 | const uint32_t d4 = (c % 100) << 1; |
163 | |
|
164 | 0 | if (value >= 10000000) |
165 | 0 | *buffer++ = cDigitsLut[d1]; |
166 | 0 | if (value >= 1000000) |
167 | 0 | *buffer++ = cDigitsLut[d1 + 1]; |
168 | 0 | if (value >= 100000) |
169 | 0 | *buffer++ = cDigitsLut[d2]; |
170 | 0 | *buffer++ = cDigitsLut[d2 + 1]; |
171 | |
|
172 | 0 | *buffer++ = cDigitsLut[d3]; |
173 | 0 | *buffer++ = cDigitsLut[d3 + 1]; |
174 | 0 | *buffer++ = cDigitsLut[d4]; |
175 | 0 | *buffer++ = cDigitsLut[d4 + 1]; |
176 | 0 | } |
177 | 0 | } |
178 | 0 | else if (value < kTen16) { |
179 | 0 | const uint32_t v0 = static_cast<uint32_t>(value / kTen8); |
180 | 0 | const uint32_t v1 = static_cast<uint32_t>(value % kTen8); |
181 | |
|
182 | 0 | const uint32_t b0 = v0 / 10000; |
183 | 0 | const uint32_t c0 = v0 % 10000; |
184 | |
|
185 | 0 | const uint32_t d1 = (b0 / 100) << 1; |
186 | 0 | const uint32_t d2 = (b0 % 100) << 1; |
187 | |
|
188 | 0 | const uint32_t d3 = (c0 / 100) << 1; |
189 | 0 | const uint32_t d4 = (c0 % 100) << 1; |
190 | |
|
191 | 0 | const uint32_t b1 = v1 / 10000; |
192 | 0 | const uint32_t c1 = v1 % 10000; |
193 | |
|
194 | 0 | const uint32_t d5 = (b1 / 100) << 1; |
195 | 0 | const uint32_t d6 = (b1 % 100) << 1; |
196 | |
|
197 | 0 | const uint32_t d7 = (c1 / 100) << 1; |
198 | 0 | const uint32_t d8 = (c1 % 100) << 1; |
199 | |
|
200 | 0 | if (value >= kTen15) |
201 | 0 | *buffer++ = cDigitsLut[d1]; |
202 | 0 | if (value >= kTen14) |
203 | 0 | *buffer++ = cDigitsLut[d1 + 1]; |
204 | 0 | if (value >= kTen13) |
205 | 0 | *buffer++ = cDigitsLut[d2]; |
206 | 0 | if (value >= kTen12) |
207 | 0 | *buffer++ = cDigitsLut[d2 + 1]; |
208 | 0 | if (value >= kTen11) |
209 | 0 | *buffer++ = cDigitsLut[d3]; |
210 | 0 | if (value >= kTen10) |
211 | 0 | *buffer++ = cDigitsLut[d3 + 1]; |
212 | 0 | if (value >= kTen9) |
213 | 0 | *buffer++ = cDigitsLut[d4]; |
214 | |
|
215 | 0 | *buffer++ = cDigitsLut[d4 + 1]; |
216 | 0 | *buffer++ = cDigitsLut[d5]; |
217 | 0 | *buffer++ = cDigitsLut[d5 + 1]; |
218 | 0 | *buffer++ = cDigitsLut[d6]; |
219 | 0 | *buffer++ = cDigitsLut[d6 + 1]; |
220 | 0 | *buffer++ = cDigitsLut[d7]; |
221 | 0 | *buffer++ = cDigitsLut[d7 + 1]; |
222 | 0 | *buffer++ = cDigitsLut[d8]; |
223 | 0 | *buffer++ = cDigitsLut[d8 + 1]; |
224 | 0 | } |
225 | 0 | else { |
226 | 0 | const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844 |
227 | 0 | value %= kTen16; |
228 | |
|
229 | 0 | if (a < 10) |
230 | 0 | *buffer++ = static_cast<char>('0' + static_cast<char>(a)); |
231 | 0 | else if (a < 100) { |
232 | 0 | const uint32_t i = a << 1; |
233 | 0 | *buffer++ = cDigitsLut[i]; |
234 | 0 | *buffer++ = cDigitsLut[i + 1]; |
235 | 0 | } |
236 | 0 | else if (a < 1000) { |
237 | 0 | *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100)); |
238 | |
|
239 | 0 | const uint32_t i = (a % 100) << 1; |
240 | 0 | *buffer++ = cDigitsLut[i]; |
241 | 0 | *buffer++ = cDigitsLut[i + 1]; |
242 | 0 | } |
243 | 0 | else { |
244 | 0 | const uint32_t i = (a / 100) << 1; |
245 | 0 | const uint32_t j = (a % 100) << 1; |
246 | 0 | *buffer++ = cDigitsLut[i]; |
247 | 0 | *buffer++ = cDigitsLut[i + 1]; |
248 | 0 | *buffer++ = cDigitsLut[j]; |
249 | 0 | *buffer++ = cDigitsLut[j + 1]; |
250 | 0 | } |
251 | |
|
252 | 0 | const uint32_t v0 = static_cast<uint32_t>(value / kTen8); |
253 | 0 | const uint32_t v1 = static_cast<uint32_t>(value % kTen8); |
254 | |
|
255 | 0 | const uint32_t b0 = v0 / 10000; |
256 | 0 | const uint32_t c0 = v0 % 10000; |
257 | |
|
258 | 0 | const uint32_t d1 = (b0 / 100) << 1; |
259 | 0 | const uint32_t d2 = (b0 % 100) << 1; |
260 | |
|
261 | 0 | const uint32_t d3 = (c0 / 100) << 1; |
262 | 0 | const uint32_t d4 = (c0 % 100) << 1; |
263 | |
|
264 | 0 | const uint32_t b1 = v1 / 10000; |
265 | 0 | const uint32_t c1 = v1 % 10000; |
266 | |
|
267 | 0 | const uint32_t d5 = (b1 / 100) << 1; |
268 | 0 | const uint32_t d6 = (b1 % 100) << 1; |
269 | |
|
270 | 0 | const uint32_t d7 = (c1 / 100) << 1; |
271 | 0 | const uint32_t d8 = (c1 % 100) << 1; |
272 | |
|
273 | 0 | *buffer++ = cDigitsLut[d1]; |
274 | 0 | *buffer++ = cDigitsLut[d1 + 1]; |
275 | 0 | *buffer++ = cDigitsLut[d2]; |
276 | 0 | *buffer++ = cDigitsLut[d2 + 1]; |
277 | 0 | *buffer++ = cDigitsLut[d3]; |
278 | 0 | *buffer++ = cDigitsLut[d3 + 1]; |
279 | 0 | *buffer++ = cDigitsLut[d4]; |
280 | 0 | *buffer++ = cDigitsLut[d4 + 1]; |
281 | 0 | *buffer++ = cDigitsLut[d5]; |
282 | 0 | *buffer++ = cDigitsLut[d5 + 1]; |
283 | 0 | *buffer++ = cDigitsLut[d6]; |
284 | 0 | *buffer++ = cDigitsLut[d6 + 1]; |
285 | 0 | *buffer++ = cDigitsLut[d7]; |
286 | 0 | *buffer++ = cDigitsLut[d7 + 1]; |
287 | 0 | *buffer++ = cDigitsLut[d8]; |
288 | 0 | *buffer++ = cDigitsLut[d8 + 1]; |
289 | 0 | } |
290 | |
|
291 | 0 | return buffer; |
292 | 0 | } |
293 | | |
294 | 0 | inline char* i64toa(int64_t value, char* buffer) { |
295 | 0 | RAPIDJSON_ASSERT(buffer != 0); |
296 | 0 | uint64_t u = static_cast<uint64_t>(value); |
297 | 0 | if (value < 0) { |
298 | 0 | *buffer++ = '-'; |
299 | 0 | u = ~u + 1; |
300 | 0 | } |
301 | |
|
302 | 0 | return u64toa(u, buffer); |
303 | 0 | } |
304 | | |
305 | | } // namespace internal |
306 | | RAPIDJSON_NAMESPACE_END |
307 | | |
308 | | #endif // RAPIDJSON_ITOA_ |