1337143Sdim//===------------------------- charconv.cpp -------------------------------===//
2337143Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6337143Sdim//
7337143Sdim//===----------------------------------------------------------------------===//
8337143Sdim
9337143Sdim#include "charconv"
10337143Sdim#include <string.h>
11337143Sdim
12337143Sdim_LIBCPP_BEGIN_NAMESPACE_STD
13337143Sdim
14337143Sdimnamespace __itoa
15337143Sdim{
16337143Sdim
17337143Sdimstatic constexpr char cDigitsLut[200] = {
18337143Sdim    '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0',
19337143Sdim    '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
20337143Sdim    '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2',
21337143Sdim    '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
22337143Sdim    '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3',
23337143Sdim    '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
24337143Sdim    '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5',
25337143Sdim    '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
26337143Sdim    '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6',
27337143Sdim    '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
28337143Sdim    '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8',
29337143Sdim    '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
30337143Sdim    '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9',
31337143Sdim    '7', '9', '8', '9', '9'};
32337143Sdim
33337143Sdimtemplate <typename T>
34337143Sdiminline _LIBCPP_INLINE_VISIBILITY char*
35337143Sdimappend1(char* buffer, T i)
36337143Sdim{
37337143Sdim    *buffer = '0' + static_cast<char>(i);
38337143Sdim    return buffer + 1;
39337143Sdim}
40337143Sdim
41337143Sdimtemplate <typename T>
42337143Sdiminline _LIBCPP_INLINE_VISIBILITY char*
43337143Sdimappend2(char* buffer, T i)
44337143Sdim{
45337143Sdim    memcpy(buffer, &cDigitsLut[(i)*2], 2);
46337143Sdim    return buffer + 2;
47337143Sdim}
48337143Sdim
49337143Sdimtemplate <typename T>
50337143Sdiminline _LIBCPP_INLINE_VISIBILITY char*
51337143Sdimappend3(char* buffer, T i)
52337143Sdim{
53337143Sdim    return append2(append1(buffer, (i) / 100), (i) % 100);
54337143Sdim}
55337143Sdim
56337143Sdimtemplate <typename T>
57337143Sdiminline _LIBCPP_INLINE_VISIBILITY char*
58337143Sdimappend4(char* buffer, T i)
59337143Sdim{
60337143Sdim    return append2(append2(buffer, (i) / 100), (i) % 100);
61337143Sdim}
62337143Sdim
63353358Sdimtemplate <typename T>
64353358Sdiminline _LIBCPP_INLINE_VISIBILITY char*
65353358Sdimappend2_no_zeros(char* buffer, T v)
66337143Sdim{
67353358Sdim    if (v < 10)
68353358Sdim        return append1(buffer, v);
69353358Sdim    else
70353358Sdim        return append2(buffer, v);
71353358Sdim}
72353358Sdim
73353358Sdimtemplate <typename T>
74353358Sdiminline _LIBCPP_INLINE_VISIBILITY char*
75353358Sdimappend4_no_zeros(char* buffer, T v)
76353358Sdim{
77353358Sdim    if (v < 100)
78353358Sdim        return append2_no_zeros(buffer, v);
79353358Sdim    else if (v < 1000)
80353358Sdim        return append3(buffer, v);
81353358Sdim    else
82353358Sdim        return append4(buffer, v);
83353358Sdim}
84353358Sdim
85353358Sdimtemplate <typename T>
86353358Sdiminline _LIBCPP_INLINE_VISIBILITY char*
87353358Sdimappend8_no_zeros(char* buffer, T v)
88353358Sdim{
89353358Sdim    if (v < 10000)
90337143Sdim    {
91353358Sdim        buffer = append4_no_zeros(buffer, v);
92337143Sdim    }
93353358Sdim    else
94337143Sdim    {
95353358Sdim        buffer = append4_no_zeros(buffer, v / 10000);
96353358Sdim        buffer = append4(buffer, v % 10000);
97353358Sdim    }
98353358Sdim    return buffer;
99353358Sdim}
100337143Sdim
101353358Sdimchar*
102353358Sdim__u32toa(uint32_t value, char* buffer)
103353358Sdim{
104353358Sdim    if (value < 100000000)
105353358Sdim    {
106353358Sdim        buffer = append8_no_zeros(buffer, value);
107337143Sdim    }
108337143Sdim    else
109337143Sdim    {
110337143Sdim        // value = aabbbbcccc in decimal
111337143Sdim        const uint32_t a = value / 100000000;  // 1 to 42
112337143Sdim        value %= 100000000;
113337143Sdim
114353358Sdim        buffer = append2_no_zeros(buffer, a);
115337143Sdim        buffer = append4(buffer, value / 10000);
116337143Sdim        buffer = append4(buffer, value % 10000);
117337143Sdim    }
118337143Sdim
119337143Sdim    return buffer;
120337143Sdim}
121337143Sdim
122337143Sdimchar*
123337143Sdim__u64toa(uint64_t value, char* buffer)
124337143Sdim{
125337143Sdim    if (value < 100000000)
126337143Sdim    {
127337143Sdim        uint32_t v = static_cast<uint32_t>(value);
128353358Sdim        buffer = append8_no_zeros(buffer, v);
129337143Sdim    }
130337143Sdim    else if (value < 10000000000000000)
131337143Sdim    {
132337143Sdim        const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
133337143Sdim        const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
134337143Sdim
135353358Sdim        buffer = append8_no_zeros(buffer, v0);
136337143Sdim        buffer = append4(buffer, v1 / 10000);
137337143Sdim        buffer = append4(buffer, v1 % 10000);
138337143Sdim    }
139337143Sdim    else
140337143Sdim    {
141337143Sdim        const uint32_t a =
142337143Sdim            static_cast<uint32_t>(value / 10000000000000000);  // 1 to 1844
143337143Sdim        value %= 10000000000000000;
144337143Sdim
145353358Sdim        buffer = append4_no_zeros(buffer, a);
146337143Sdim
147337143Sdim        const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
148337143Sdim        const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
149337143Sdim        buffer = append4(buffer, v0 / 10000);
150337143Sdim        buffer = append4(buffer, v0 % 10000);
151337143Sdim        buffer = append4(buffer, v1 / 10000);
152337143Sdim        buffer = append4(buffer, v1 % 10000);
153337143Sdim    }
154337143Sdim
155337143Sdim    return buffer;
156337143Sdim}
157337143Sdim
158337143Sdim}  // namespace __itoa
159337143Sdim
160337143Sdim_LIBCPP_END_NAMESPACE_STD
161