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*
append1(char * buffer,T i)35 append1(char* buffer, T i) noexcept
36 {
37 *buffer = '0' + static_cast<char>(i);
38 return buffer + 1;
39 }
40
41 template <typename T>
42 inline _LIBCPP_INLINE_VISIBILITY char*
append2(char * buffer,T i)43 append2(char* buffer, T i) noexcept
44 {
45 memcpy(buffer, &cDigitsLut[(i)*2], 2);
46 return buffer + 2;
47 }
48
49 template <typename T>
50 inline _LIBCPP_INLINE_VISIBILITY char*
append3(char * buffer,T i)51 append3(char* buffer, T i) noexcept
52 {
53 return append2(append1(buffer, (i) / 100), (i) % 100);
54 }
55
56 template <typename T>
57 inline _LIBCPP_INLINE_VISIBILITY char*
append4(char * buffer,T i)58 append4(char* buffer, T i) noexcept
59 {
60 return append2(append2(buffer, (i) / 100), (i) % 100);
61 }
62
63 template <typename T>
64 inline _LIBCPP_INLINE_VISIBILITY char*
append2_no_zeros(char * buffer,T v)65 append2_no_zeros(char* buffer, T v) noexcept
66 {
67 if (v < 10)
68 return append1(buffer, v);
69 else
70 return append2(buffer, v);
71 }
72
73 template <typename T>
74 inline _LIBCPP_INLINE_VISIBILITY char*
append4_no_zeros(char * buffer,T v)75 append4_no_zeros(char* buffer, T v) noexcept
76 {
77 if (v < 100)
78 return append2_no_zeros(buffer, v);
79 else if (v < 1000)
80 return append3(buffer, v);
81 else
82 return append4(buffer, v);
83 }
84
85 template <typename T>
86 inline _LIBCPP_INLINE_VISIBILITY char*
append8_no_zeros(char * buffer,T v)87 append8_no_zeros(char* buffer, T v) noexcept
88 {
89 if (v < 10000)
90 {
91 buffer = append4_no_zeros(buffer, v);
92 }
93 else
94 {
95 buffer = append4_no_zeros(buffer, v / 10000);
96 buffer = append4(buffer, v % 10000);
97 }
98 return buffer;
99 }
100
101 char*
__u32toa(uint32_t value,char * buffer)102 __u32toa(uint32_t value, char* buffer) noexcept
103 {
104 if (value < 100000000)
105 {
106 buffer = append8_no_zeros(buffer, value);
107 }
108 else
109 {
110 // value = aabbbbcccc in decimal
111 const uint32_t a = value / 100000000; // 1 to 42
112 value %= 100000000;
113
114 buffer = append2_no_zeros(buffer, a);
115 buffer = append4(buffer, value / 10000);
116 buffer = append4(buffer, value % 10000);
117 }
118
119 return buffer;
120 }
121
122 char*
__u64toa(uint64_t value,char * buffer)123 __u64toa(uint64_t value, char* buffer) noexcept
124 {
125 if (value < 100000000)
126 {
127 uint32_t v = static_cast<uint32_t>(value);
128 buffer = append8_no_zeros(buffer, v);
129 }
130 else if (value < 10000000000000000)
131 {
132 const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
133 const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
134
135 buffer = append8_no_zeros(buffer, v0);
136 buffer = append4(buffer, v1 / 10000);
137 buffer = append4(buffer, v1 % 10000);
138 }
139 else
140 {
141 const uint32_t a =
142 static_cast<uint32_t>(value / 10000000000000000); // 1 to 1844
143 value %= 10000000000000000;
144
145 buffer = append4_no_zeros(buffer, a);
146
147 const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
148 const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
149 buffer = append4(buffer, v0 / 10000);
150 buffer = append4(buffer, v0 % 10000);
151 buffer = append4(buffer, v1 / 10000);
152 buffer = append4(buffer, v1 % 10000);
153 }
154
155 return buffer;
156 }
157
158 } // namespace __itoa
159
160 _LIBCPP_END_NAMESPACE_STD
161