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<char>('0' + static_cast<char>(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<uint32_t>(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<uint32_t>(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<uint32_t>(value / kTen8); |
176 | const uint32_t v1 = static_cast<uint32_t>(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<uint32_t>(value / kTen16); // 1 to 1844 |
224 | value %= kTen16; |
225 | |
226 | if (a < 10) |
227 | *buffer++ = static_cast<char>('0' + static_cast<char>(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<char>('0' + static_cast<char>(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<uint32_t>(value / kTen8); |
250 | const uint32_t v1 = static_cast<uint32_t>(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<uint64_t>(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 | |