From 1b14ec50568549b060a0bdb27463d9ea6aa56605 Mon Sep 17 00:00:00 2001
From: Marco Bubke <marco.bubke@qt.io>
Date: Mon, 31 Jul 2017 16:08:35 +0200
Subject: [PATCH] Utils: Add number to string conversion

We use std::to_string except for integer where we want a low overhead
solution.

Change-Id: I16ce7d575d83ff56e61a5038aa7f9a1febfaf34f
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
---
 src/libs/utils/smallstring.h             | 69 ++++++++++++++++++++++++
 tests/unit/unittest/smallstring-test.cpp | 13 +++++
 2 files changed, 82 insertions(+)

diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h
index eb301586915..3614bee0a83 100644
--- a/src/libs/utils/smallstring.h
+++ b/src/libs/utils/smallstring.h
@@ -547,6 +547,30 @@ public:
         return joinedString;
     }
 
+    static
+    BasicSmallString number(int number)
+    {
+        char buffer[12];
+        std::size_t size = itoa(number, buffer, 10);
+
+        return BasicSmallString(buffer, size);
+    }
+
+    static
+    BasicSmallString number(long long int number)
+    {
+        char buffer[22];
+        std::size_t size = itoa(number, buffer, 10);
+
+        return BasicSmallString(buffer, size);
+    }
+
+    static
+    BasicSmallString number(double number)
+    {
+        return std::to_string(number);
+    }
+
     char &operator[](std::size_t index)
     {
         return *(data() + index);
@@ -849,6 +873,51 @@ private:
             m_data.allocated.data.size = size;
     }
 
+    static
+    std::size_t itoa(long long int number, char* string, uint base)
+    {
+        using llint = long long int;
+        using lluint = long long unsigned int;
+        std::size_t size = 0;
+        bool isNegative = false;
+        lluint unsignedNumber = 0;
+
+        if (number == 0)
+        {
+            string[size] = '0';
+            string[++size] = '\0';
+
+            return size;
+        }
+
+        if (number < 0 && base == 10)
+        {
+            isNegative = true;
+            if (number == std::numeric_limits<llint>::min())
+                unsignedNumber = lluint(std::numeric_limits<llint>::max()) + 1;
+            else
+                unsignedNumber = lluint(-number);
+        } else {
+            unsignedNumber = lluint(number);
+        }
+
+        while (unsignedNumber != 0)
+        {
+            int remainder = int(unsignedNumber % base);
+            string[size++] = (remainder > 9) ? char((remainder - 10) + 'a') : char(remainder + '0');
+            unsignedNumber /= base;
+        }
+
+        if (isNegative)
+            string[size++] = '-';
+
+        string[size] = '\0';
+
+        std::reverse(string, string+size);
+
+        return size;
+    }
+
 private:
     Internal::StringDataLayout<Size> m_data;
 };
diff --git a/tests/unit/unittest/smallstring-test.cpp b/tests/unit/unittest/smallstring-test.cpp
index 29c40635421..e555a8fabd1 100644
--- a/tests/unit/unittest/smallstring-test.cpp
+++ b/tests/unit/unittest/smallstring-test.cpp
@@ -1256,3 +1256,16 @@ TEST(SmallString, InitializerListNullTerminated)
 
     ASSERT_THAT(end, '\0');
 }
+
+TEST(SmallString, NumberToString)
+{
+    ASSERT_THAT(SmallString::number(-0), "0");
+    ASSERT_THAT(SmallString::number(1), "1");
+    ASSERT_THAT(SmallString::number(-1), "-1");
+    ASSERT_THAT(SmallString::number(std::numeric_limits<int>::max()), "2147483647");
+    ASSERT_THAT(SmallString::number(std::numeric_limits<int>::min()), "-2147483648");
+    ASSERT_THAT(SmallString::number(std::numeric_limits<long long int>::max()), "9223372036854775807");
+    ASSERT_THAT(SmallString::number(std::numeric_limits<long long int>::min()), "-9223372036854775808");
+    ASSERT_THAT(SmallString::number(1.2), "1.200000");
+    ASSERT_THAT(SmallString::number(-1.2), "-1.200000");
+}
-- 
GitLab