1 //===------------------------- charconv.cpp -------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "charconv"
10 #include <string.h>
11 
12 _LIBCPP_BEGIN_NAMESPACE_STD
13 
14 namespace __itoa
15 {
16 
17 static constexpr char cDigitsLut[200] = {
18     '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0',
19     '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
20     '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2',
21     '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
22     '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3',
23     '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
24     '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5',
25     '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
26     '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6',
27     '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
28     '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8',
29     '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
30     '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9',
31     '7', '9', '8', '9', '9'};
32 
33 template <typename T>
34 inline _LIBCPP_INLINE_VISIBILITY char*
35 append1(char* buffer, T i)
36 {
37     *buffer = '0' + static_cast<char>(i);
38     return buffer + 1;
39 }
40 
41 template <typename T>
42 inline _LIBCPP_INLINE_VISIBILITY char*
43 append2(char* buffer, T i)
44 {
45     memcpy(buffer, &cDigitsLut[(i)*2], 2);
46     return buffer + 2;
47 }
48 
49 template <typename T>
50 inline _LIBCPP_INLINE_VISIBILITY char*
51 append3(char* buffer, T i)
52 {
53     return append2(append1(buffer, (i) / 100), (i) % 100);
54 }
55 
56 template <typename T>
57 inline _LIBCPP_INLINE_VISIBILITY char*
58 append4(char* buffer, T i)
59 {
60     return append2(append2(buffer, (i) / 100), (i) % 100);
61 }
62 
63 char*
64 __u32toa(uint32_t value, char* buffer)
65 {
66     if (value < 10000)
67     {
68         if (value < 100)
69         {
70             if (value < 10)
71                 buffer = append1(buffer, value);
72             else
73                 buffer = append2(buffer, value);
74         }
75         else
76         {
77             if (value < 1000)
78                 buffer = append3(buffer, value);
79             else
80                 buffer = append4(buffer, value);
81         }
82     }
83     else if (value < 100000000)
84     {
85         // value = bbbbcccc
86         const uint32_t b = value / 10000;
87         const uint32_t c = value % 10000;
88 
89         if (value < 1000000)
90         {
91             if (value < 100000)
92                 buffer = append1(buffer, b);
93             else
94                 buffer = append2(buffer, b);
95         }
96         else
97         {
98             if (value < 10000000)
99                 buffer = append3(buffer, b);
100             else
101                 buffer = append4(buffer, b);
102         }
103 
104         buffer = append4(buffer, c);
105     }
106     else
107     {
108         // value = aabbbbcccc in decimal
109         const uint32_t a = value / 100000000;  // 1 to 42
110         value %= 100000000;
111 
112         if (a < 10)
113             buffer = append1(buffer, a);
114         else
115             buffer = append2(buffer, a);
116 
117         buffer = append4(buffer, value / 10000);
118         buffer = append4(buffer, value % 10000);
119     }
120 
121     return buffer;
122 }
123 
124 char*
125 __u64toa(uint64_t value, char* buffer)
126 {
127     if (value < 100000000)
128     {
129         uint32_t v = static_cast<uint32_t>(value);
130         if (v < 10000)
131         {
132             if (v < 100)
133             {
134                 if (v < 10)
135                     buffer = append1(buffer, v);
136                 else
137                     buffer = append2(buffer, v);
138             }
139             else
140             {
141                 if (v < 1000)
142                     buffer = append3(buffer, v);
143                 else
144                     buffer = append4(buffer, v);
145             }
146         }
147         else
148         {
149             // value = bbbbcccc
150             const uint32_t b = v / 10000;
151             const uint32_t c = v % 10000;
152 
153             if (v < 1000000)
154             {
155                 if (v < 100000)
156                     buffer = append1(buffer, b);
157                 else
158                     buffer = append2(buffer, b);
159             }
160             else
161             {
162                 if (v < 10000000)
163                     buffer = append3(buffer, b);
164                 else
165                     buffer = append4(buffer, b);
166             }
167 
168             buffer = append4(buffer, c);
169         }
170     }
171     else if (value < 10000000000000000)
172     {
173         const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
174         const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
175 
176         const uint32_t b0 = v0 / 10000;
177         const uint32_t c0 = v0 % 10000;
178 
179         if (v0 < 1000000)
180         {
181             if (v0 < 100000)
182                 buffer = append1(buffer, b0);
183             else
184                 buffer = append2(buffer, b0);
185         }
186         else
187         {
188             if (v0 < 10000000)
189                 buffer = append3(buffer, b0);
190             else
191                 buffer = append4(buffer, b0);
192         }
193 
194         buffer = append4(buffer, c0);
195         buffer = append4(buffer, v1 / 10000);
196         buffer = append4(buffer, v1 % 10000);
197     }
198     else
199     {
200         const uint32_t a =
201             static_cast<uint32_t>(value / 10000000000000000);  // 1 to 1844
202         value %= 10000000000000000;
203 
204         if (a < 100)
205         {
206             if (a < 10)
207                 buffer = append1(buffer, a);
208             else
209                 buffer = append2(buffer, a);
210         }
211         else
212         {
213             if (a < 1000)
214                 buffer = append3(buffer, a);
215             else
216                 buffer = append4(buffer, a);
217         }
218 
219         const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
220         const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
221         buffer = append4(buffer, v0 / 10000);
222         buffer = append4(buffer, v0 % 10000);
223         buffer = append4(buffer, v1 / 10000);
224         buffer = append4(buffer, v1 % 10000);
225     }
226 
227     return buffer;
228 }
229 
230 }  // namespace __itoa
231 
232 _LIBCPP_END_NAMESPACE_STD
233