All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
itoa.h
1 #ifndef RAPIDJSON_ITOA_
2 #define RAPIDJSON_ITOA_
3 
4 namespace rapidjson {
5 namespace internal {
6 
7 // Modified from https://github.com/miloyip/itoa-benchmark/blob/master/src/branchlut.cpp
8 // API is changed to return the character passed the end of string, without writing '\0'
9 
10 inline const char* GetDigitsLut() {
11  static const char cDigitsLut[200] = {
12  '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
13  '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
14  '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
15  '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
16  '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
17  '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
18  '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
19  '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
20  '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
21  '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
22  };
23  return cDigitsLut;
24 }
25 
26 inline char* u32toa(uint32_t value, char* buffer) {
27  const char* cDigitsLut = GetDigitsLut();
28 
29  if (value < 10000) {
30  const uint32_t d1 = (value / 100) << 1;
31  const uint32_t d2 = (value % 100) << 1;
32 
33  if (value >= 1000)
34  *buffer++ = cDigitsLut[d1];
35  if (value >= 100)
36  *buffer++ = cDigitsLut[d1 + 1];
37  if (value >= 10)
38  *buffer++ = cDigitsLut[d2];
39  *buffer++ = cDigitsLut[d2 + 1];
40  }
41  else if (value < 100000000) {
42  // value = bbbbcccc
43  const uint32_t b = value / 10000;
44  const uint32_t c = value % 10000;
45 
46  const uint32_t d1 = (b / 100) << 1;
47  const uint32_t d2 = (b % 100) << 1;
48 
49  const uint32_t d3 = (c / 100) << 1;
50  const uint32_t d4 = (c % 100) << 1;
51 
52  if (value >= 10000000)
53  *buffer++ = cDigitsLut[d1];
54  if (value >= 1000000)
55  *buffer++ = cDigitsLut[d1 + 1];
56  if (value >= 100000)
57  *buffer++ = cDigitsLut[d2];
58  *buffer++ = cDigitsLut[d2 + 1];
59 
60  *buffer++ = cDigitsLut[d3];
61  *buffer++ = cDigitsLut[d3 + 1];
62  *buffer++ = cDigitsLut[d4];
63  *buffer++ = cDigitsLut[d4 + 1];
64  }
65  else {
66  // value = aabbbbcccc in decimal
67 
68  const uint32_t a = value / 100000000; // 1 to 42
69  value %= 100000000;
70 
71  if (a >= 10) {
72  const unsigned i = a << 1;
73  *buffer++ = cDigitsLut[i];
74  *buffer++ = cDigitsLut[i + 1];
75  }
76  else
77  *buffer++ = '0' + static_cast<char>(a);
78 
79  const uint32_t b = value / 10000; // 0 to 9999
80  const uint32_t c = value % 10000; // 0 to 9999
81 
82  const uint32_t d1 = (b / 100) << 1;
83  const uint32_t d2 = (b % 100) << 1;
84 
85  const uint32_t d3 = (c / 100) << 1;
86  const uint32_t d4 = (c % 100) << 1;
87 
88  *buffer++ = cDigitsLut[d1];
89  *buffer++ = cDigitsLut[d1 + 1];
90  *buffer++ = cDigitsLut[d2];
91  *buffer++ = cDigitsLut[d2 + 1];
92  *buffer++ = cDigitsLut[d3];
93  *buffer++ = cDigitsLut[d3 + 1];
94  *buffer++ = cDigitsLut[d4];
95  *buffer++ = cDigitsLut[d4 + 1];
96  }
97  return buffer;
98 }
99 
100 inline char* i32toa(int32_t value, char* buffer) {
101  if (value < 0) {
102  *buffer++ = '-';
103  value = -value;
104  }
105 
106  return u32toa(static_cast<uint32_t>(value), buffer);
107 }
108 
109 inline char* u64toa(uint64_t value, char* buffer) {
110  const char* cDigitsLut = GetDigitsLut();
111 
112  if (value < UINT64_C(100000000)) {
113  uint32_t v = static_cast<uint32_t>(value);
114  if (v < 10000) {
115  const uint32_t d1 = (v / 100) << 1;
116  const uint32_t d2 = (v % 100) << 1;
117 
118  if (v >= 1000)
119  *buffer++ = cDigitsLut[d1];
120  if (v >= 100)
121  *buffer++ = cDigitsLut[d1 + 1];
122  if (v >= 10)
123  *buffer++ = cDigitsLut[d2];
124  *buffer++ = cDigitsLut[d2 + 1];
125  }
126  else {
127  // value = bbbbcccc
128  const uint32_t b = v / 10000;
129  const uint32_t c = v % 10000;
130 
131  const uint32_t d1 = (b / 100) << 1;
132  const uint32_t d2 = (b % 100) << 1;
133 
134  const uint32_t d3 = (c / 100) << 1;
135  const uint32_t d4 = (c % 100) << 1;
136 
137  if (value >= 10000000)
138  *buffer++ = cDigitsLut[d1];
139  if (value >= 1000000)
140  *buffer++ = cDigitsLut[d1 + 1];
141  if (value >= 100000)
142  *buffer++ = cDigitsLut[d2];
143  *buffer++ = cDigitsLut[d2 + 1];
144 
145  *buffer++ = cDigitsLut[d3];
146  *buffer++ = cDigitsLut[d3 + 1];
147  *buffer++ = cDigitsLut[d4];
148  *buffer++ = cDigitsLut[d4 + 1];
149  }
150  }
151  else if (value < UINT64_C(10000000000000000)) {
152  const uint32_t v0 = static_cast<uint32_t>(value / UINT64_C(100000000));
153  const uint32_t v1 = static_cast<uint32_t>(value % UINT64_C(100000000));
154 
155  const uint32_t b0 = v0 / 10000;
156  const uint32_t c0 = v0 % 10000;
157 
158  const uint32_t d1 = (b0 / 100) << 1;
159  const uint32_t d2 = (b0 % 100) << 1;
160 
161  const uint32_t d3 = (c0 / 100) << 1;
162  const uint32_t d4 = (c0 % 100) << 1;
163 
164  const uint32_t b1 = v1 / 10000;
165  const uint32_t c1 = v1 % 10000;
166 
167  const uint32_t d5 = (b1 / 100) << 1;
168  const uint32_t d6 = (b1 % 100) << 1;
169 
170  const uint32_t d7 = (c1 / 100) << 1;
171  const uint32_t d8 = (c1 % 100) << 1;
172 
173  if (value >= UINT64_C(1000000000000000))
174  *buffer++ = cDigitsLut[d1];
175  if (value >= UINT64_C(100000000000000))
176  *buffer++ = cDigitsLut[d1 + 1];
177  if (value >= UINT64_C(10000000000000))
178  *buffer++ = cDigitsLut[d2];
179  if (value >= UINT64_C(1000000000000))
180  *buffer++ = cDigitsLut[d2 + 1];
181  if (value >= UINT64_C(100000000000))
182  *buffer++ = cDigitsLut[d3];
183  if (value >= UINT64_C(10000000000))
184  *buffer++ = cDigitsLut[d3 + 1];
185  if (value >= UINT64_C(1000000000))
186  *buffer++ = cDigitsLut[d4];
187  if (value >= UINT64_C(100000000))
188  *buffer++ = cDigitsLut[d4 + 1];
189 
190  *buffer++ = cDigitsLut[d5];
191  *buffer++ = cDigitsLut[d5 + 1];
192  *buffer++ = cDigitsLut[d6];
193  *buffer++ = cDigitsLut[d6 + 1];
194  *buffer++ = cDigitsLut[d7];
195  *buffer++ = cDigitsLut[d7 + 1];
196  *buffer++ = cDigitsLut[d8];
197  *buffer++ = cDigitsLut[d8 + 1];
198  }
199  else {
200  const uint32_t a = static_cast<uint32_t>(value / UINT64_C(10000000000000000)); // 1 to 1844
201  value %= UINT64_C(10000000000000000);
202 
203  if (a < 10)
204  *buffer++ = '0' + static_cast<char>(a);
205  else if (a < 100) {
206  const uint32_t i = a << 1;
207  *buffer++ = cDigitsLut[i];
208  *buffer++ = cDigitsLut[i + 1];
209  }
210  else if (a < 1000) {
211  *buffer++ = '0' + static_cast<char>(a / 100);
212 
213  const uint32_t i = (a % 100) << 1;
214  *buffer++ = cDigitsLut[i];
215  *buffer++ = cDigitsLut[i + 1];
216  }
217  else {
218  const uint32_t i = (a / 100) << 1;
219  const uint32_t j = (a % 100) << 1;
220  *buffer++ = cDigitsLut[i];
221  *buffer++ = cDigitsLut[i + 1];
222  *buffer++ = cDigitsLut[j];
223  *buffer++ = cDigitsLut[j + 1];
224  }
225 
226  const uint32_t v0 = static_cast<uint32_t>(value / UINT64_C(100000000));
227  const uint32_t v1 = static_cast<uint32_t>(value % UINT64_C(100000000));
228 
229  const uint32_t b0 = v0 / 10000;
230  const uint32_t c0 = v0 % 10000;
231 
232  const uint32_t d1 = (b0 / 100) << 1;
233  const uint32_t d2 = (b0 % 100) << 1;
234 
235  const uint32_t d3 = (c0 / 100) << 1;
236  const uint32_t d4 = (c0 % 100) << 1;
237 
238  const uint32_t b1 = v1 / 10000;
239  const uint32_t c1 = v1 % 10000;
240 
241  const uint32_t d5 = (b1 / 100) << 1;
242  const uint32_t d6 = (b1 % 100) << 1;
243 
244  const uint32_t d7 = (c1 / 100) << 1;
245  const uint32_t d8 = (c1 % 100) << 1;
246 
247  *buffer++ = cDigitsLut[d1];
248  *buffer++ = cDigitsLut[d1 + 1];
249  *buffer++ = cDigitsLut[d2];
250  *buffer++ = cDigitsLut[d2 + 1];
251  *buffer++ = cDigitsLut[d3];
252  *buffer++ = cDigitsLut[d3 + 1];
253  *buffer++ = cDigitsLut[d4];
254  *buffer++ = cDigitsLut[d4 + 1];
255  *buffer++ = cDigitsLut[d5];
256  *buffer++ = cDigitsLut[d5 + 1];
257  *buffer++ = cDigitsLut[d6];
258  *buffer++ = cDigitsLut[d6 + 1];
259  *buffer++ = cDigitsLut[d7];
260  *buffer++ = cDigitsLut[d7 + 1];
261  *buffer++ = cDigitsLut[d8];
262  *buffer++ = cDigitsLut[d8 + 1];
263  }
264 
265  return buffer;
266 }
267 
268 inline char* i64toa(int64_t value, char* buffer) {
269  if (value < 0) {
270  *buffer++ = '-';
271  value = -value;
272  }
273 
274  return u64toa(static_cast<uint64_t>(value), buffer);
275 }
276 
277 } // namespace internal
278 } // namespace rapidjson
279 
280 #endif // RAPIDJSON_ITOA_