xref: /freebsd/contrib/llvm-project/libcxx/src/charconv.cpp (revision 924226fba12cc9a228c73b956e1b7fa24c60b055)
1 //===----------------------------------------------------------------------===//
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 #include "include/ryu/digit_table.h"
13 #include "include/to_chars_floating_point.h"
14 
15 _LIBCPP_BEGIN_NAMESPACE_STD
16 
17 namespace __itoa
18 {
19 
20 template <typename T>
21 inline _LIBCPP_INLINE_VISIBILITY char*
22 append1(char* buffer, T i) noexcept
23 {
24     *buffer = '0' + static_cast<char>(i);
25     return buffer + 1;
26 }
27 
28 template <typename T>
29 inline _LIBCPP_INLINE_VISIBILITY char*
30 append2(char* buffer, T i) noexcept
31 {
32     memcpy(buffer, &__DIGIT_TABLE[(i)*2], 2);
33     return buffer + 2;
34 }
35 
36 template <typename T>
37 inline _LIBCPP_INLINE_VISIBILITY char*
38 append3(char* buffer, T i) noexcept
39 {
40     return append2(append1(buffer, (i) / 100), (i) % 100);
41 }
42 
43 template <typename T>
44 inline _LIBCPP_INLINE_VISIBILITY char*
45 append4(char* buffer, T i) noexcept
46 {
47     return append2(append2(buffer, (i) / 100), (i) % 100);
48 }
49 
50 template <typename T>
51 inline _LIBCPP_INLINE_VISIBILITY char*
52 append2_no_zeros(char* buffer, T v) noexcept
53 {
54     if (v < 10)
55         return append1(buffer, v);
56     else
57         return append2(buffer, v);
58 }
59 
60 template <typename T>
61 inline _LIBCPP_INLINE_VISIBILITY char*
62 append4_no_zeros(char* buffer, T v) noexcept
63 {
64     if (v < 100)
65         return append2_no_zeros(buffer, v);
66     else if (v < 1000)
67         return append3(buffer, v);
68     else
69         return append4(buffer, v);
70 }
71 
72 template <typename T>
73 inline _LIBCPP_INLINE_VISIBILITY char*
74 append8_no_zeros(char* buffer, T v) noexcept
75 {
76     if (v < 10000)
77     {
78         buffer = append4_no_zeros(buffer, v);
79     }
80     else
81     {
82         buffer = append4_no_zeros(buffer, v / 10000);
83         buffer = append4(buffer, v % 10000);
84     }
85     return buffer;
86 }
87 
88 char*
89 __u32toa(uint32_t value, char* buffer) noexcept
90 {
91     if (value < 100000000)
92     {
93         buffer = append8_no_zeros(buffer, value);
94     }
95     else
96     {
97         // value = aabbbbcccc in decimal
98         const uint32_t a = value / 100000000;  // 1 to 42
99         value %= 100000000;
100 
101         buffer = append2_no_zeros(buffer, a);
102         buffer = append4(buffer, value / 10000);
103         buffer = append4(buffer, value % 10000);
104     }
105 
106     return buffer;
107 }
108 
109 char*
110 __u64toa(uint64_t value, char* buffer) noexcept
111 {
112     if (value < 100000000)
113     {
114         uint32_t v = static_cast<uint32_t>(value);
115         buffer = append8_no_zeros(buffer, v);
116     }
117     else if (value < 10000000000000000)
118     {
119         const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
120         const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
121 
122         buffer = append8_no_zeros(buffer, v0);
123         buffer = append4(buffer, v1 / 10000);
124         buffer = append4(buffer, v1 % 10000);
125     }
126     else
127     {
128         const uint32_t a =
129             static_cast<uint32_t>(value / 10000000000000000);  // 1 to 1844
130         value %= 10000000000000000;
131 
132         buffer = append4_no_zeros(buffer, a);
133 
134         const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
135         const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
136         buffer = append4(buffer, v0 / 10000);
137         buffer = append4(buffer, v0 % 10000);
138         buffer = append4(buffer, v1 / 10000);
139         buffer = append4(buffer, v1 % 10000);
140     }
141 
142     return buffer;
143 }
144 
145 }  // namespace __itoa
146 
147 // The original version of floating-point to_chars was written by Microsoft and
148 // contributed with the following license.
149 
150 // Copyright (c) Microsoft Corporation.
151 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
152 
153 // This implementation is dedicated to the memory of Mary and Thavatchai.
154 
155 to_chars_result to_chars(char* __first, char* __last, float __value) {
156   return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, __value, chars_format{}, 0);
157 }
158 
159 to_chars_result to_chars(char* __first, char* __last, double __value) {
160   return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, __value, chars_format{}, 0);
161 }
162 
163 to_chars_result to_chars(char* __first, char* __last, long double __value) {
164   return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, static_cast<double>(__value),
165                                                                  chars_format{}, 0);
166 }
167 
168 to_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt) {
169   return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, __value, __fmt, 0);
170 }
171 
172 to_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt) {
173   return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, __value, __fmt, 0);
174 }
175 
176 to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt) {
177   return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, static_cast<double>(__value),
178                                                                        __fmt, 0);
179 }
180 
181 to_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision) {
182   return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(__first, __last, __value, __fmt,
183                                                                             __precision);
184 }
185 
186 to_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision) {
187   return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(__first, __last, __value, __fmt,
188                                                                             __precision);
189 }
190 
191 to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision) {
192   return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(
193       __first, __last, static_cast<double>(__value), __fmt, __precision);
194 }
195 
196 _LIBCPP_END_NAMESPACE_STD
197