mirror of
https://github.com/nodejs/node.git
synced 2024-11-29 15:06:33 +01:00
src: enhance C++ sprintf utility
PR-URL: https://github.com/nodejs/node/pull/32385 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
This commit is contained in:
parent
b950daf836
commit
dade90db9c
@ -27,6 +27,27 @@ struct ToStringHelper {
|
||||
}
|
||||
static std::string Convert(const std::string& value) { return value; }
|
||||
static std::string Convert(bool value) { return value ? "true" : "false"; }
|
||||
template <unsigned BASE_BITS,
|
||||
typename T,
|
||||
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||
static std::string BaseConvert(T value) {
|
||||
char ret[3 * sizeof(T)];
|
||||
char* ptr = ret + 3 * sizeof(T) - 1;
|
||||
*ptr = '\0';
|
||||
const char* digits = "0123456789abcdef";
|
||||
do {
|
||||
unsigned digit = value & ((1 << BASE_BITS) - 1);
|
||||
*--ptr =
|
||||
(BASE_BITS < 4 ? static_cast<char>('0' + digit) : digits[digit]);
|
||||
} while ((value >>= BASE_BITS) != 0);
|
||||
return ptr;
|
||||
}
|
||||
template <unsigned BASE_BITS,
|
||||
typename T,
|
||||
typename std::enable_if<!std::is_integral<T>::value, int>::type = 0>
|
||||
static std::string BaseConvert(T value) {
|
||||
return Convert(std::forward<T>(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -34,6 +55,11 @@ std::string ToString(const T& value) {
|
||||
return ToStringHelper::Convert(value);
|
||||
}
|
||||
|
||||
template <unsigned BASE_BITS, typename T>
|
||||
std::string ToBaseString(T&& value) {
|
||||
return ToStringHelper::BaseConvert<BASE_BITS>(std::forward<T>(value));
|
||||
}
|
||||
|
||||
inline std::string SPrintFImpl(const char* format) {
|
||||
const char* p = strchr(format, '%');
|
||||
if (LIKELY(p == nullptr)) return format;
|
||||
@ -64,7 +90,18 @@ std::string COLD_NOINLINE SPrintFImpl( // NOLINT(runtime/string)
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'u':
|
||||
case 's': ret += ToString(arg); break;
|
||||
case 's':
|
||||
ret += ToString(arg);
|
||||
break;
|
||||
case 'o':
|
||||
ret += ToBaseString<3>(arg);
|
||||
break;
|
||||
case 'x':
|
||||
ret += ToBaseString<4>(arg);
|
||||
break;
|
||||
case 'X':
|
||||
ret += node::ToUpper(ToBaseString<4>(arg));
|
||||
break;
|
||||
case 'p': {
|
||||
CHECK(std::is_pointer<typename std::remove_reference<Arg>::type>::value);
|
||||
char out[20];
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "async_wrap.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
@ -268,6 +268,12 @@ TEST(UtilTest, SPrintF) {
|
||||
EXPECT_EQ(SPrintF("%u", -10000000000LL), "-10000000000");
|
||||
EXPECT_EQ(SPrintF("%i", 10), "10");
|
||||
EXPECT_EQ(SPrintF("%d", 10), "10");
|
||||
EXPECT_EQ(SPrintF("%x", 15), "f");
|
||||
EXPECT_EQ(SPrintF("%x", 16), "10");
|
||||
EXPECT_EQ(SPrintF("%X", 15), "F");
|
||||
EXPECT_EQ(SPrintF("%X", 16), "10");
|
||||
EXPECT_EQ(SPrintF("%o", 7), "7");
|
||||
EXPECT_EQ(SPrintF("%o", 8), "10");
|
||||
|
||||
EXPECT_EQ(atof(SPrintF("%s", 0.5).c_str()), 0.5);
|
||||
EXPECT_EQ(atof(SPrintF("%s", -0.5).c_str()), -0.5);
|
||||
|
Loading…
Reference in New Issue
Block a user