@@ -27,13 +27,39 @@ struct ToStringHelper {
2727 }
2828 static std::string Convert (const std::string& value) { return value; }
2929 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+ }
3051};
3152
3253template <typename T>
3354std::string ToString (const T& value) {
3455 return ToStringHelper::Convert (value);
3556}
3657
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+
3763inline std::string SPrintFImpl (const char * format) {
3864 const char * p = strchr (format, ' %' );
3965 if (LIKELY (p == nullptr )) return format;
@@ -64,7 +90,18 @@ std::string COLD_NOINLINE SPrintFImpl( // NOLINT(runtime/string)
6490 case ' d' :
6591 case ' i' :
6692 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 ;
68105 case ' p' : {
69106 CHECK (std::is_pointer<typename std::remove_reference<Arg>::type>::value);
70107 char out[20 ];
0 commit comments