xref: /freebsd/contrib/llvm-project/libcxx/src/charconv.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
1349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "charconv"
100b57cec5SDimitry Andric #include <string.h>
110b57cec5SDimitry Andric 
12*0eae32dcSDimitry Andric #include "include/ryu/digit_table.h"
13*0eae32dcSDimitry Andric #include "include/to_chars_floating_point.h"
14*0eae32dcSDimitry Andric 
150b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric namespace __itoa
180b57cec5SDimitry Andric {
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric template <typename T>
210b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
225ffd83dbSDimitry Andric append1(char* buffer, T i) noexcept
230b57cec5SDimitry Andric {
240b57cec5SDimitry Andric     *buffer = '0' + static_cast<char>(i);
250b57cec5SDimitry Andric     return buffer + 1;
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric template <typename T>
290b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
305ffd83dbSDimitry Andric append2(char* buffer, T i) noexcept
310b57cec5SDimitry Andric {
32*0eae32dcSDimitry Andric     memcpy(buffer, &__DIGIT_TABLE[(i)*2], 2);
330b57cec5SDimitry Andric     return buffer + 2;
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric template <typename T>
370b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
385ffd83dbSDimitry Andric append3(char* buffer, T i) noexcept
390b57cec5SDimitry Andric {
400b57cec5SDimitry Andric     return append2(append1(buffer, (i) / 100), (i) % 100);
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric template <typename T>
440b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
455ffd83dbSDimitry Andric append4(char* buffer, T i) noexcept
460b57cec5SDimitry Andric {
470b57cec5SDimitry Andric     return append2(append2(buffer, (i) / 100), (i) % 100);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric template <typename T>
510b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
525ffd83dbSDimitry Andric append2_no_zeros(char* buffer, T v) noexcept
530b57cec5SDimitry Andric {
540b57cec5SDimitry Andric     if (v < 10)
550b57cec5SDimitry Andric         return append1(buffer, v);
560b57cec5SDimitry Andric     else
570b57cec5SDimitry Andric         return append2(buffer, v);
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric template <typename T>
610b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
625ffd83dbSDimitry Andric append4_no_zeros(char* buffer, T v) noexcept
630b57cec5SDimitry Andric {
640b57cec5SDimitry Andric     if (v < 100)
650b57cec5SDimitry Andric         return append2_no_zeros(buffer, v);
660b57cec5SDimitry Andric     else if (v < 1000)
670b57cec5SDimitry Andric         return append3(buffer, v);
680b57cec5SDimitry Andric     else
690b57cec5SDimitry Andric         return append4(buffer, v);
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric template <typename T>
730b57cec5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY char*
745ffd83dbSDimitry Andric append8_no_zeros(char* buffer, T v) noexcept
750b57cec5SDimitry Andric {
760b57cec5SDimitry Andric     if (v < 10000)
770b57cec5SDimitry Andric     {
780b57cec5SDimitry Andric         buffer = append4_no_zeros(buffer, v);
790b57cec5SDimitry Andric     }
800b57cec5SDimitry Andric     else
810b57cec5SDimitry Andric     {
820b57cec5SDimitry Andric         buffer = append4_no_zeros(buffer, v / 10000);
830b57cec5SDimitry Andric         buffer = append4(buffer, v % 10000);
840b57cec5SDimitry Andric     }
850b57cec5SDimitry Andric     return buffer;
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric char*
89fe6060f1SDimitry Andric __u32toa(uint32_t value, char* buffer) noexcept
900b57cec5SDimitry Andric {
910b57cec5SDimitry Andric     if (value < 100000000)
920b57cec5SDimitry Andric     {
930b57cec5SDimitry Andric         buffer = append8_no_zeros(buffer, value);
940b57cec5SDimitry Andric     }
950b57cec5SDimitry Andric     else
960b57cec5SDimitry Andric     {
970b57cec5SDimitry Andric         // value = aabbbbcccc in decimal
980b57cec5SDimitry Andric         const uint32_t a = value / 100000000;  // 1 to 42
990b57cec5SDimitry Andric         value %= 100000000;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric         buffer = append2_no_zeros(buffer, a);
1020b57cec5SDimitry Andric         buffer = append4(buffer, value / 10000);
1030b57cec5SDimitry Andric         buffer = append4(buffer, value % 10000);
1040b57cec5SDimitry Andric     }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric     return buffer;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric char*
110fe6060f1SDimitry Andric __u64toa(uint64_t value, char* buffer) noexcept
1110b57cec5SDimitry Andric {
1120b57cec5SDimitry Andric     if (value < 100000000)
1130b57cec5SDimitry Andric     {
1140b57cec5SDimitry Andric         uint32_t v = static_cast<uint32_t>(value);
1150b57cec5SDimitry Andric         buffer = append8_no_zeros(buffer, v);
1160b57cec5SDimitry Andric     }
1170b57cec5SDimitry Andric     else if (value < 10000000000000000)
1180b57cec5SDimitry Andric     {
1190b57cec5SDimitry Andric         const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
1200b57cec5SDimitry Andric         const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric         buffer = append8_no_zeros(buffer, v0);
1230b57cec5SDimitry Andric         buffer = append4(buffer, v1 / 10000);
1240b57cec5SDimitry Andric         buffer = append4(buffer, v1 % 10000);
1250b57cec5SDimitry Andric     }
1260b57cec5SDimitry Andric     else
1270b57cec5SDimitry Andric     {
1280b57cec5SDimitry Andric         const uint32_t a =
1290b57cec5SDimitry Andric             static_cast<uint32_t>(value / 10000000000000000);  // 1 to 1844
1300b57cec5SDimitry Andric         value %= 10000000000000000;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric         buffer = append4_no_zeros(buffer, a);
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric         const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
1350b57cec5SDimitry Andric         const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
1360b57cec5SDimitry Andric         buffer = append4(buffer, v0 / 10000);
1370b57cec5SDimitry Andric         buffer = append4(buffer, v0 % 10000);
1380b57cec5SDimitry Andric         buffer = append4(buffer, v1 / 10000);
1390b57cec5SDimitry Andric         buffer = append4(buffer, v1 % 10000);
1400b57cec5SDimitry Andric     }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric     return buffer;
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric }  // namespace __itoa
1460b57cec5SDimitry Andric 
147*0eae32dcSDimitry Andric // The original version of floating-point to_chars was written by Microsoft and
148*0eae32dcSDimitry Andric // contributed with the following license.
149*0eae32dcSDimitry Andric 
150*0eae32dcSDimitry Andric // Copyright (c) Microsoft Corporation.
151*0eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
152*0eae32dcSDimitry Andric 
153*0eae32dcSDimitry Andric // This implementation is dedicated to the memory of Mary and Thavatchai.
154*0eae32dcSDimitry Andric 
155*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, float __value) {
156*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, __value, chars_format{}, 0);
157*0eae32dcSDimitry Andric }
158*0eae32dcSDimitry Andric 
159*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, double __value) {
160*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, __value, chars_format{}, 0);
161*0eae32dcSDimitry Andric }
162*0eae32dcSDimitry Andric 
163*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, long double __value) {
164*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, static_cast<double>(__value),
165*0eae32dcSDimitry Andric                                                                  chars_format{}, 0);
166*0eae32dcSDimitry Andric }
167*0eae32dcSDimitry Andric 
168*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt) {
169*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, __value, __fmt, 0);
170*0eae32dcSDimitry Andric }
171*0eae32dcSDimitry Andric 
172*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt) {
173*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, __value, __fmt, 0);
174*0eae32dcSDimitry Andric }
175*0eae32dcSDimitry Andric 
176*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt) {
177*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, static_cast<double>(__value),
178*0eae32dcSDimitry Andric                                                                        __fmt, 0);
179*0eae32dcSDimitry Andric }
180*0eae32dcSDimitry Andric 
181*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision) {
182*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(__first, __last, __value, __fmt,
183*0eae32dcSDimitry Andric                                                                             __precision);
184*0eae32dcSDimitry Andric }
185*0eae32dcSDimitry Andric 
186*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision) {
187*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(__first, __last, __value, __fmt,
188*0eae32dcSDimitry Andric                                                                             __precision);
189*0eae32dcSDimitry Andric }
190*0eae32dcSDimitry Andric 
191*0eae32dcSDimitry Andric to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision) {
192*0eae32dcSDimitry Andric   return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(
193*0eae32dcSDimitry Andric       __first, __last, static_cast<double>(__value), __fmt, __precision);
194*0eae32dcSDimitry Andric }
195*0eae32dcSDimitry Andric 
1960b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
197