diff options
author | babenko <babenko@yandex-team.com> | 2022-09-19 16:59:49 +0300 |
---|---|---|
committer | babenko <babenko@yandex-team.com> | 2022-09-19 16:59:49 +0300 |
commit | ddbed3bdc9fbfec40475f0e3939187bb6ce716c3 (patch) | |
tree | e761fd77c2f6fb80c4edcd47d66d6356bdd71fcb /library/cpp | |
parent | b5a861d056d17322efb73efb580e0d32238e452c (diff) | |
download | ydb-ddbed3bdc9fbfec40475f0e3939187bb6ce716c3.tar.gz |
Sane handling of %x and %X for pointers in Format
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/yt/string/format-inl.h | 7 | ||||
-rw-r--r-- | library/cpp/yt/string/format.cpp | 19 | ||||
-rw-r--r-- | library/cpp/yt/string/unittests/format_ut.cpp | 17 |
3 files changed, 38 insertions, 5 deletions
diff --git a/library/cpp/yt/string/format-inl.h b/library/cpp/yt/string/format-inl.h index c437d7ab34..a6a15485eb 100644 --- a/library/cpp/yt/string/format-inl.h +++ b/library/cpp/yt/string/format-inl.h @@ -462,6 +462,11 @@ void FormatIntValue( TStringBuf format, TStringBuf genericSpec); +void FormatPointerValue( + TStringBuilderBase* builder, + const void* value, + TStringBuf format); + } // namespace NDetail #define XX(valueType, castType, genericSpec) \ @@ -501,7 +506,7 @@ XX(float, float, TStringBuf("f")) template <class T> void FormatValue(TStringBuilderBase* builder, T* value, TStringBuf format) { - NYT::NDetail::FormatValueViaSprintf(builder, static_cast<const void*>(value), format, TStringBuf("p")); + NYT::NDetail::FormatPointerValue(builder, static_cast<const void*>(value), format); } // TDuration (specialize for performance reasons) diff --git a/library/cpp/yt/string/format.cpp b/library/cpp/yt/string/format.cpp index 6c824e8ba3..47b0c1d712 100644 --- a/library/cpp/yt/string/format.cpp +++ b/library/cpp/yt/string/format.cpp @@ -30,7 +30,8 @@ void FormatValueViaSprintf( char formatBuf[MaxFormatSize]; YT_VERIFY(format.length() >= 1 && format.length() <= MaxFormatSize - 2); // one for %, one for \0 formatBuf[0] = '%'; - if (format[format.length() - 1] == GenericSpecSymbol) { + + if (format.back() == GenericSpecSymbol) { char* formatEnd = copyFormat(formatBuf + 1, format.begin(), format.length() - 1); ::memcpy(formatEnd, genericSpec.begin(), genericSpec.length()); formatEnd[genericSpec.length()] = '\0'; @@ -105,6 +106,22 @@ XX(ui64) #undef XX +void FormatPointerValue( + TStringBuilderBase* builder, + const void* value, + TStringBuf format) +{ + static_assert(sizeof(value) == sizeof(ui64)); + if (format == TStringBuf("p") || format == TStringBuf("v")) { + builder->AppendString(TStringBuf("0x")); + FormatValue(builder, reinterpret_cast<ui64>(value), TStringBuf("x")); + } else if (format == TStringBuf("x") || format == TStringBuf("X")) { + FormatValue(builder, reinterpret_cast<ui64>(value), format); + } else { + builder->AppendString("<invalid pointer format>"); + } +} + //////////////////////////////////////////////////////////////////////////////// } // namespace NYT::NDetail diff --git a/library/cpp/yt/string/unittests/format_ut.cpp b/library/cpp/yt/string/unittests/format_ut.cpp index 20ec6392b5..47bb4602e3 100644 --- a/library/cpp/yt/string/unittests/format_ut.cpp +++ b/library/cpp/yt/string/unittests/format_ut.cpp @@ -160,9 +160,20 @@ TEST(TFormatTest, Nullable) TEST(TFormatTest, Pointers) { - // No idea if pointer format is standardized, check against Sprintf. - auto p = reinterpret_cast<void*>(123); - EXPECT_EQ(Sprintf("%p", reinterpret_cast<void*>(123)), Format("%p", p)); + { + auto ptr = reinterpret_cast<void*>(0x12345678); + EXPECT_EQ("0x12345678", Format("%p", ptr)); + EXPECT_EQ("0x12345678", Format("%v", ptr)); + EXPECT_EQ("12345678", Format("%x", ptr)); + EXPECT_EQ("12345678", Format("%X", ptr)); + } + { + auto ptr = reinterpret_cast<void*>(0x12345678abcdefab); + EXPECT_EQ("0x12345678abcdefab", Format("%p", ptr)); + EXPECT_EQ("0x12345678abcdefab", Format("%v", ptr)); + EXPECT_EQ("12345678abcdefab", Format("%x", ptr)); + EXPECT_EQ("12345678ABCDEFAB", Format("%X", ptr)); + } } //////////////////////////////////////////////////////////////////////////////// |