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 | template <typename T> |
64 | inline _LIBCPP_INLINE_VISIBILITY char* |
65 | append2_no_zeros(char* buffer, T v) |
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* |
75 | append4_no_zeros(char* buffer, T v) |
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* |
87 | append8_no_zeros(char* buffer, T v) |
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* |
102 | __u32toa(uint32_t value, char* buffer) |
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* |
123 | __u64toa(uint64_t value, char* buffer) |
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 | |