Coverage Report

Created: 2026-02-26 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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_