[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
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 6bc4a7685ee4321a74ad987032e678c6273775ff
diff --git a/src/charconv.cpp b/src/charconv.cpp
index 6ea473b..d303588 100644
--- a/src/charconv.cpp
+++ b/src/charconv.cpp
@@ -60,48 +60,50 @@
     return append2(append2(buffer, (i) / 100), (i) % 100);
 }
 
+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 (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)
+    {
+        buffer = append4_no_zeros(buffer, v);
+    }
+    else
+    {
+        buffer = append4_no_zeros(buffer, v / 10000);
+        buffer = append4(buffer, v % 10000);
+    }
+    return buffer;
+}
+
 char*
 __u32toa(uint32_t value, char* buffer)
 {
-    if (value < 10000)
+    if (value < 100000000)
     {
-        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);
-        }
-    }
-    else if (value < 100000000)
-    {
-        // 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 = append8_no_zeros(buffer, value);
     }
     else
     {
@@ -109,11 +111,7 @@
         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 @@
     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 @@
             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);