diff options
author | Zhihao Yuan <zy@miator.net> | 2019-06-10 17:11:46 +0000 |
---|---|---|
committer | Zhihao Yuan <zy@miator.net> | 2019-06-10 17:11:46 +0000 |
commit | 6bc4a7685ee4321a74ad987032e678c6273775ff (patch) | |
tree | cd8524adc5a7d3159e5cd9bc7fc97996bedc2e69 /libcxx/src | |
parent | 13d16b94c6b795d25bfddb8130f13d2284551303 (diff) | |
download | bcm5719-llvm-6bc4a7685ee4321a74ad987032e678c6273775ff.tar.gz bcm5719-llvm-6bc4a7685ee4321a74ad987032e678c6273775ff.zip |
[libc++] Fix leading zeros in std::to_chars
Summary:
It is a bugfix proposal for https://bugs.llvm.org/show_bug.cgi?id=42166.
`std::to_chars` appends leading zeros if input 64-bit value has 9, 10 or 11 digits.
According to documentation `std::to_chars` must not append leading zeros:
https://en.cppreference.com/w/cpp/utility/to_chars
Changeset should not affect `std::to_chars` performance:
http://quick-bench.com/CEpRs14xxA9WLvkXFtaJ3TWOVAg
Unit test that `std::from_chars` supports compatibility for both `std::to_chars` outputs (previous and fixed one) already exists:
https://github.com/llvm-mirror/libcxx/blob/1f60111b597e5cb80a4513ec86f79b7e137f7793/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp#L63
Reviewers: lichray, mclow.lists, ldionne, EricWF
Reviewed By: lichray, mclow.lists
Subscribers: zoecarver, christof, dexonsmith, libcxx-commits
Differential Revision: https://reviews.llvm.org/D63047
llvm-svn: 362967
Diffstat (limited to 'libcxx/src')
-rw-r--r-- | libcxx/src/charconv.cpp | 160 |
1 files changed, 44 insertions, 116 deletions
diff --git a/libcxx/src/charconv.cpp b/libcxx/src/charconv.cpp index 6ea473b25f8..d3035883a78 100644 --- a/libcxx/src/charconv.cpp +++ b/libcxx/src/charconv.cpp @@ -60,48 +60,50 @@ append4(char* buffer, T i) return append2(append2(buffer, (i) / 100), (i) % 100); } -char* -__u32toa(uint32_t value, char* buffer) +template <typename T> +inline _LIBCPP_INLINE_VISIBILITY char* +append2_no_zeros(char* buffer, T v) +{ + if (v < 10) + return append1(buffer, v); + else + return append2(buffer, v); +} + +template <typename T> +inline _LIBCPP_INLINE_VISIBILITY char* +append4_no_zeros(char* buffer, T v) { - if (value < 10000) + if (v < 100) + return append2_no_zeros(buffer, v); + else if (v < 1000) + return append3(buffer, v); + else + return append4(buffer, v); +} + +template <typename T> +inline _LIBCPP_INLINE_VISIBILITY char* +append8_no_zeros(char* buffer, T v) +{ + if (v < 10000) { - if (value < 100) - { - if (value < 10) - buffer = append1(buffer, value); - else - buffer = append2(buffer, value); - } - else - { - if (value < 1000) - buffer = append3(buffer, value); - else - buffer = append4(buffer, value); - } + buffer = append4_no_zeros(buffer, v); } - else if (value < 100000000) + else { - // value = bbbbcccc - const uint32_t b = value / 10000; - const uint32_t c = value % 10000; - - if (value < 1000000) - { - if (value < 100000) - buffer = append1(buffer, b); - else - buffer = append2(buffer, b); - } - else - { - if (value < 10000000) - buffer = append3(buffer, b); - else - buffer = append4(buffer, b); - } - - buffer = append4(buffer, c); + buffer = append4_no_zeros(buffer, v / 10000); + buffer = append4(buffer, v % 10000); + } + return buffer; +} + +char* +__u32toa(uint32_t value, char* buffer) +{ + if (value < 100000000) + { + buffer = append8_no_zeros(buffer, value); } else { @@ -109,11 +111,7 @@ __u32toa(uint32_t value, char* buffer) const uint32_t a = value / 100000000; // 1 to 42 value %= 100000000; - if (a < 10) - buffer = append1(buffer, a); - else - buffer = append2(buffer, a); - + buffer = append2_no_zeros(buffer, a); buffer = append4(buffer, value / 10000); buffer = append4(buffer, value % 10000); } @@ -127,71 +125,14 @@ __u64toa(uint64_t value, char* buffer) if (value < 100000000) { uint32_t v = static_cast<uint32_t>(value); - if (v < 10000) - { - if (v < 100) - { - if (v < 10) - buffer = append1(buffer, v); - else - buffer = append2(buffer, v); - } - else - { - if (v < 1000) - buffer = append3(buffer, v); - else - buffer = append4(buffer, v); - } - } - else - { - // value = bbbbcccc - const uint32_t b = v / 10000; - const uint32_t c = v % 10000; - - if (v < 1000000) - { - if (v < 100000) - buffer = append1(buffer, b); - else - buffer = append2(buffer, b); - } - else - { - if (v < 10000000) - buffer = append3(buffer, b); - else - buffer = append4(buffer, b); - } - - buffer = append4(buffer, c); - } + buffer = append8_no_zeros(buffer, v); } else if (value < 10000000000000000) { const uint32_t v0 = static_cast<uint32_t>(value / 100000000); const uint32_t v1 = static_cast<uint32_t>(value % 100000000); - const uint32_t b0 = v0 / 10000; - const uint32_t c0 = v0 % 10000; - - if (v0 < 1000000) - { - if (v0 < 100000) - buffer = append1(buffer, b0); - else - buffer = append2(buffer, b0); - } - else - { - if (v0 < 10000000) - buffer = append3(buffer, b0); - else - buffer = append4(buffer, b0); - } - - buffer = append4(buffer, c0); + buffer = append8_no_zeros(buffer, v0); buffer = append4(buffer, v1 / 10000); buffer = append4(buffer, v1 % 10000); } @@ -201,20 +142,7 @@ __u64toa(uint64_t value, char* buffer) static_cast<uint32_t>(value / 10000000000000000); // 1 to 1844 value %= 10000000000000000; - if (a < 100) - { - if (a < 10) - buffer = append1(buffer, a); - else - buffer = append2(buffer, a); - } - else - { - if (a < 1000) - buffer = append3(buffer, a); - else - buffer = append4(buffer, a); - } + buffer = append4_no_zeros(buffer, a); const uint32_t v0 = static_cast<uint32_t>(value / 100000000); const uint32_t v1 = static_cast<uint32_t>(value % 100000000); |