GeezerVison is showing github.com — src: enhance C++ sprintf utility · nodejs/node@4b5fd24
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: src/debug_utils-inl.h +38-1Lines changed: 38 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -27,13 +27,39 @@ struct ToStringHelper { | 27 | 27 | } | 28 | 28 | static std::string Convert(const std::string& value) { return value; } | 29 | 29 | static std::string Convert(bool value) { return value ? "true" : "false"; } | | 30 | + template <unsigned BASE_BITS, | | 31 | + typename T, | | 32 | + typename std::enable_if<std::is_integral<T>::value, int>::type = 0> | | 33 | + static std::string BaseConvert(T value) { | | 34 | + char ret[3 * sizeof(T)]; | | 35 | + char* ptr = ret + 3 * sizeof(T) - 1; | | 36 | + *ptr = '\0'; | | 37 | + const char* digits = "0123456789abcdef"; | | 38 | + do { | | 39 | + unsigned digit = value & ((1 << BASE_BITS) - 1); | | 40 | + *--ptr = | | 41 | + (BASE_BITS < 4 ? static_cast<char>('0' + digit) : digits[digit]); | | 42 | + } while ((value >>= BASE_BITS) != 0); | | 43 | + return ptr; | | 44 | + } | | 45 | + template <unsigned BASE_BITS, | | 46 | + typename T, | | 47 | + typename std::enable_if<!std::is_integral<T>::value, int>::type = 0> | | 48 | + static std::string BaseConvert(T value) { | | 49 | + return Convert(std::forward<T>(value)); | | 50 | + } | 30 | 51 | }; | 31 | 52 |
| 32 | 53 | template <typename T> | 33 | 54 | std::string ToString(const T& value) { | 34 | 55 | return ToStringHelper::Convert(value); | 35 | 56 | } | 36 | 57 |
| | 58 | +template <unsigned BASE_BITS, typename T> | | 59 | +std::string ToBaseString(T&& value) { | | 60 | + return ToStringHelper::BaseConvert<BASE_BITS>(std::forward<T>(value)); | | 61 | +} | | 62 | + | 37 | 63 | inline std::string SPrintFImpl(const char* format) { | 38 | 64 | const char* p = strchr(format, '%'); | 39 | 65 | if (LIKELY(p == nullptr)) return format; | @@ -64,7 +90,18 @@ std::string COLD_NOINLINE SPrintFImpl( // NOLINT(runtime/string) | 64 | 90 | case 'd': | 65 | 91 | case 'i': | 66 | 92 | case 'u': | 67 | | - case 's': ret += ToString(arg); break; | | 93 | + case 's': | | 94 | + ret += ToString(arg); | | 95 | + break; | | 96 | + case 'o': | | 97 | + ret += ToBaseString<3>(arg); | | 98 | + break; | | 99 | + case 'x': | | 100 | + ret += ToBaseString<4>(arg); | | 101 | + break; | | 102 | + case 'X': | | 103 | + ret += node::ToUpper(ToBaseString<4>(arg)); | | 104 | + break; | 68 | 105 | case 'p': { | 69 | 106 | CHECK(std::is_pointer<typename std::remove_reference<Arg>::type>::value); | 70 | 107 | char out[20]; | |
Collapse file Copy file name to clipboardExpand all lines: src/debug_utils.h +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 5 | 5 |
| 6 | 6 | #include "async_wrap.h" | 7 | 7 |
| | 8 | +#include <algorithm> | 8 | 9 | #include <sstream> | 9 | 10 | #include <string> | 10 | 11 |
| |
Collapse file Copy file name to clipboardExpand all lines: test/cctest/test_util.cc +6Lines changed: 6 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -268,6 +268,12 @@ TEST(UtilTest, SPrintF) { | 268 | 268 | EXPECT_EQ(SPrintF("%u", -10000000000LL), "-10000000000"); | 269 | 269 | EXPECT_EQ(SPrintF("%i", 10), "10"); | 270 | 270 | EXPECT_EQ(SPrintF("%d", 10), "10"); | | 271 | + EXPECT_EQ(SPrintF("%x", 15), "f"); | | 272 | + EXPECT_EQ(SPrintF("%x", 16), "10"); | | 273 | + EXPECT_EQ(SPrintF("%X", 15), "F"); | | 274 | + EXPECT_EQ(SPrintF("%X", 16), "10"); | | 275 | + EXPECT_EQ(SPrintF("%o", 7), "7"); | | 276 | + EXPECT_EQ(SPrintF("%o", 8), "10"); | 271 | 277 |
| 272 | 278 | EXPECT_EQ(atof(SPrintF("%s", 0.5).c_str()), 0.5); | 273 | 279 | EXPECT_EQ(atof(SPrintF("%s", -0.5).c_str()), -0.5); | |
|