aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorbabenko <babenko@yandex-team.com>2022-09-19 16:59:49 +0300
committerbabenko <babenko@yandex-team.com>2022-09-19 16:59:49 +0300
commitddbed3bdc9fbfec40475f0e3939187bb6ce716c3 (patch)
treee761fd77c2f6fb80c4edcd47d66d6356bdd71fcb /library/cpp
parentb5a861d056d17322efb73efb580e0d32238e452c (diff)
downloadydb-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.h7
-rw-r--r--library/cpp/yt/string/format.cpp19
-rw-r--r--library/cpp/yt/string/unittests/format_ut.cpp17
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));
+ }
}
////////////////////////////////////////////////////////////////////////////////