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
14namespace __itoa
15{
16
17static 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
33template <typename T>
34inline _LIBCPP_INLINE_VISIBILITY char*
35append1(char* buffer, T i)
36{
37 *buffer = '0' + static_cast<char>(i);
38 return buffer + 1;
39}
40
41template <typename T>
42inline _LIBCPP_INLINE_VISIBILITY char*
43append2(char* buffer, T i)
44{
45 memcpy(buffer, &cDigitsLut[(i)*2], 2);
46 return buffer + 2;
47}
48
49template <typename T>
50inline _LIBCPP_INLINE_VISIBILITY char*
51append3(char* buffer, T i)
52{
53 return append2(append1(buffer, (i) / 100), (i) % 100);
54}
55
56template <typename T>
57inline _LIBCPP_INLINE_VISIBILITY char*
58append4(char* buffer, T i)
59{
60 return append2(append2(buffer, (i) / 100), (i) % 100);
61}
62
63template <typename T>
64inline _LIBCPP_INLINE_VISIBILITY char*
65append2_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
73template <typename T>
74inline _LIBCPP_INLINE_VISIBILITY char*
75append4_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
85template <typename T>
86inline _LIBCPP_INLINE_VISIBILITY char*
87append8_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
101char*
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
122char*
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