xref: /freebsd/contrib/llvm-project/libcxx/src/charconv.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===------------------------- charconv.cpp -------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "charconv"
10*0b57cec5SDimitry Andric #include <string.h>
11*0b57cec5SDimitry Andric 
12*0b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric namespace __itoa
15*0b57cec5SDimitry Andric {
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric static constexpr char cDigitsLut[200] = {
18*0b57cec5SDimitry Andric     '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0',
19*0b57cec5SDimitry Andric     '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
20*0b57cec5SDimitry Andric     '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2',
21*0b57cec5SDimitry Andric     '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
22*0b57cec5SDimitry Andric     '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3',
23*0b57cec5SDimitry Andric     '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
24*0b57cec5SDimitry Andric     '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5',
25*0b57cec5SDimitry Andric     '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
26*0b57cec5SDimitry Andric     '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6',
27*0b57cec5SDimitry Andric     '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
28*0b57cec5SDimitry Andric     '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8',
29*0b57cec5SDimitry Andric     '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
30*0b57cec5SDimitry Andric     '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9',
31*0b57cec5SDimitry Andric     '7', '9', '8', '9', '9'};
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric template <typename T>
34*0b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
35*0b57cec5SDimitry Andric append1(char* buffer, T i)
36*0b57cec5SDimitry Andric {
37*0b57cec5SDimitry Andric     *buffer = '0' + static_cast<char>(i);
38*0b57cec5SDimitry Andric     return buffer + 1;
39*0b57cec5SDimitry Andric }
40*0b57cec5SDimitry Andric 
41*0b57cec5SDimitry Andric template <typename T>
42*0b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
43*0b57cec5SDimitry Andric append2(char* buffer, T i)
44*0b57cec5SDimitry Andric {
45*0b57cec5SDimitry Andric     memcpy(buffer, &cDigitsLut[(i)*2], 2);
46*0b57cec5SDimitry Andric     return buffer + 2;
47*0b57cec5SDimitry Andric }
48*0b57cec5SDimitry Andric 
49*0b57cec5SDimitry Andric template <typename T>
50*0b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
51*0b57cec5SDimitry Andric append3(char* buffer, T i)
52*0b57cec5SDimitry Andric {
53*0b57cec5SDimitry Andric     return append2(append1(buffer, (i) / 100), (i) % 100);
54*0b57cec5SDimitry Andric }
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric template <typename T>
57*0b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
58*0b57cec5SDimitry Andric append4(char* buffer, T i)
59*0b57cec5SDimitry Andric {
60*0b57cec5SDimitry Andric     return append2(append2(buffer, (i) / 100), (i) % 100);
61*0b57cec5SDimitry Andric }
62*0b57cec5SDimitry Andric 
63*0b57cec5SDimitry Andric template <typename T>
64*0b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
65*0b57cec5SDimitry Andric append2_no_zeros(char* buffer, T v)
66*0b57cec5SDimitry Andric {
67*0b57cec5SDimitry Andric     if (v < 10)
68*0b57cec5SDimitry Andric         return append1(buffer, v);
69*0b57cec5SDimitry Andric     else
70*0b57cec5SDimitry Andric         return append2(buffer, v);
71*0b57cec5SDimitry Andric }
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric template <typename T>
74*0b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
75*0b57cec5SDimitry Andric append4_no_zeros(char* buffer, T v)
76*0b57cec5SDimitry Andric {
77*0b57cec5SDimitry Andric     if (v < 100)
78*0b57cec5SDimitry Andric         return append2_no_zeros(buffer, v);
79*0b57cec5SDimitry Andric     else if (v < 1000)
80*0b57cec5SDimitry Andric         return append3(buffer, v);
81*0b57cec5SDimitry Andric     else
82*0b57cec5SDimitry Andric         return append4(buffer, v);
83*0b57cec5SDimitry Andric }
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric template <typename T>
86*0b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
87*0b57cec5SDimitry Andric append8_no_zeros(char* buffer, T v)
88*0b57cec5SDimitry Andric {
89*0b57cec5SDimitry Andric     if (v < 10000)
90*0b57cec5SDimitry Andric     {
91*0b57cec5SDimitry Andric         buffer = append4_no_zeros(buffer, v);
92*0b57cec5SDimitry Andric     }
93*0b57cec5SDimitry Andric     else
94*0b57cec5SDimitry Andric     {
95*0b57cec5SDimitry Andric         buffer = append4_no_zeros(buffer, v / 10000);
96*0b57cec5SDimitry Andric         buffer = append4(buffer, v % 10000);
97*0b57cec5SDimitry Andric     }
98*0b57cec5SDimitry Andric     return buffer;
99*0b57cec5SDimitry Andric }
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric char*
102*0b57cec5SDimitry Andric __u32toa(uint32_t value, char* buffer)
103*0b57cec5SDimitry Andric {
104*0b57cec5SDimitry Andric     if (value < 100000000)
105*0b57cec5SDimitry Andric     {
106*0b57cec5SDimitry Andric         buffer = append8_no_zeros(buffer, value);
107*0b57cec5SDimitry Andric     }
108*0b57cec5SDimitry Andric     else
109*0b57cec5SDimitry Andric     {
110*0b57cec5SDimitry Andric         // value = aabbbbcccc in decimal
111*0b57cec5SDimitry Andric         const uint32_t a = value / 100000000;  // 1 to 42
112*0b57cec5SDimitry Andric         value %= 100000000;
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric         buffer = append2_no_zeros(buffer, a);
115*0b57cec5SDimitry Andric         buffer = append4(buffer, value / 10000);
116*0b57cec5SDimitry Andric         buffer = append4(buffer, value % 10000);
117*0b57cec5SDimitry Andric     }
118*0b57cec5SDimitry Andric 
119*0b57cec5SDimitry Andric     return buffer;
120*0b57cec5SDimitry Andric }
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric char*
123*0b57cec5SDimitry Andric __u64toa(uint64_t value, char* buffer)
124*0b57cec5SDimitry Andric {
125*0b57cec5SDimitry Andric     if (value < 100000000)
126*0b57cec5SDimitry Andric     {
127*0b57cec5SDimitry Andric         uint32_t v = static_cast<uint32_t>(value);
128*0b57cec5SDimitry Andric         buffer = append8_no_zeros(buffer, v);
129*0b57cec5SDimitry Andric     }
130*0b57cec5SDimitry Andric     else if (value < 10000000000000000)
131*0b57cec5SDimitry Andric     {
132*0b57cec5SDimitry Andric         const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
133*0b57cec5SDimitry Andric         const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
134*0b57cec5SDimitry Andric 
135*0b57cec5SDimitry Andric         buffer = append8_no_zeros(buffer, v0);
136*0b57cec5SDimitry Andric         buffer = append4(buffer, v1 / 10000);
137*0b57cec5SDimitry Andric         buffer = append4(buffer, v1 % 10000);
138*0b57cec5SDimitry Andric     }
139*0b57cec5SDimitry Andric     else
140*0b57cec5SDimitry Andric     {
141*0b57cec5SDimitry Andric         const uint32_t a =
142*0b57cec5SDimitry Andric             static_cast<uint32_t>(value / 10000000000000000);  // 1 to 1844
143*0b57cec5SDimitry Andric         value %= 10000000000000000;
144*0b57cec5SDimitry Andric 
145*0b57cec5SDimitry Andric         buffer = append4_no_zeros(buffer, a);
146*0b57cec5SDimitry Andric 
147*0b57cec5SDimitry Andric         const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
148*0b57cec5SDimitry Andric         const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
149*0b57cec5SDimitry Andric         buffer = append4(buffer, v0 / 10000);
150*0b57cec5SDimitry Andric         buffer = append4(buffer, v0 % 10000);
151*0b57cec5SDimitry Andric         buffer = append4(buffer, v1 / 10000);
152*0b57cec5SDimitry Andric         buffer = append4(buffer, v1 % 10000);
153*0b57cec5SDimitry Andric     }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric     return buffer;
156*0b57cec5SDimitry Andric }
157*0b57cec5SDimitry Andric 
158*0b57cec5SDimitry Andric }  // namespace __itoa
159*0b57cec5SDimitry Andric 
160*0b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
161