1 //===-- Utilities to convert integral values to string ----------*- C++ -*-===// 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 #ifndef LLVM_LIBC_SRC_SUPPORT_INTEGER_TO_STRING_H 10 #define LLVM_LIBC_SRC_SUPPORT_INTEGER_TO_STRING_H 11 12 #include "src/__support/CPP/StringView.h" 13 #include "src/__support/CPP/TypeTraits.h" 14 15 namespace __llvm_libc { 16 17 template <typename T> class IntegerToString { 18 static_assert(cpp::IsIntegral<T>::Value, 19 "IntegerToString can only be used with integral types."); 20 21 using UnsignedType = cpp::MakeUnsignedType<T>; 22 23 // We size the string buffer using an approximation algorithm: 24 // 25 // size = ceil(sizeof(T) * 5 / 2) 26 // 27 // If sizeof(T) is 1, then size is 3 (actually 3) 28 // If sizeof(T) is 2, then size is 5 (actually need 5) 29 // If sizeof(T) is 4, then size is 10 (actually need 10) 30 // If sizeof(T) is 8, then size is 20 (actually need 20) 31 // If sizeof(T) is 16, then size is 40 (actually need 39) 32 // 33 // NOTE: The ceil operation is actually implemented as 34 // floor(((sizeof(T) * 5) + 1)/2) 35 // where floor operation is just integer division. 36 // 37 // This estimation grows slightly faster than the actual value, but the 38 // overhead is small enough to tolerate. In the actual formula below, we 39 // add an additional byte to accommodate the '-' sign in case of signed 40 // integers. 41 static constexpr size_t BUFSIZE = 42 (sizeof(T) * 5 + 1) / 2 + (cpp::IsSigned<T>() ? 1 : 0); 43 char strbuf[BUFSIZE] = {'\0'}; 44 size_t len = 0; 45 46 constexpr void convert(UnsignedType val) { 47 size_t buffptr = BUFSIZE; 48 if (val == 0) { 49 strbuf[buffptr - 1] = '0'; 50 --buffptr; 51 } else { 52 for (; val > 0; --buffptr, val /= 10) 53 strbuf[buffptr - 1] = (val % 10) + '0'; 54 } 55 len = BUFSIZE - buffptr; 56 } 57 58 public: 59 constexpr explicit IntegerToString(T val) { 60 convert(val < 0 ? UnsignedType(-val) : UnsignedType(val)); 61 if (val < 0) { 62 // This branch will be taken only for negative signed values. 63 ++len; 64 strbuf[BUFSIZE - len] = '-'; 65 } 66 } 67 68 cpp::StringView str() const { 69 return cpp::StringView(strbuf + BUFSIZE - len, len); 70 } 71 72 operator cpp::StringView() const { return str(); } 73 }; 74 75 template <typename T> IntegerToString<T> integer_to_string(T val) { 76 return IntegerToString<T>(val); 77 } 78 79 } // namespace __llvm_libc 80 81 #endif // LLVM_LIBC_SRC_SUPPORT_INTEGER_TO_STRING_H 82