aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorifsmirnov <ifsmirnov@yandex-team.com>2023-07-06 22:56:46 +0300
committerifsmirnov <ifsmirnov@yandex-team.com>2023-07-06 22:56:46 +0300
commit3edecc646fd526f54d6cca6331130a9aafb52be4 (patch)
tree89dd719a90774a01e0bf5a123b71bc978c68c5a5
parenta106ebbbe062aa4b0c17a246be1acf8da6785556 (diff)
downloadydb-3edecc646fd526f54d6cca6331130a9aafb52be4.tar.gz
Introduce TLazyMultiValueFormatter
-rw-r--r--library/cpp/yt/string/format-inl.h29
-rw-r--r--library/cpp/yt/string/format.h39
-rw-r--r--library/cpp/yt/string/unittests/format_ut.cpp13
3 files changed, 81 insertions, 0 deletions
diff --git a/library/cpp/yt/string/format-inl.h b/library/cpp/yt/string/format-inl.h
index 2eb42cfb99..cb27961d3b 100644
--- a/library/cpp/yt/string/format-inl.h
+++ b/library/cpp/yt/string/format-inl.h
@@ -633,6 +633,35 @@ void FormatImpl(
////////////////////////////////////////////////////////////////////////////////
+template <class... TArgs>
+TLazyMultiValueFormatter<TArgs...>::TLazyMultiValueFormatter(
+ TStringBuf format,
+ TArgs&&... args)
+ : Format_(format)
+ , Args_(std::forward<TArgs>(args)...)
+{ }
+
+template <class... TArgs>
+void FormatValue(
+ TStringBuilderBase* builder,
+ const TLazyMultiValueFormatter<TArgs...>& value,
+ TStringBuf /*format*/)
+{
+ std::apply(
+ [&] <class... TInnerArgs> (TInnerArgs&&... args) {
+ builder->AppendFormat(value.Format_, std::forward<TInnerArgs>(args)...);
+ },
+ value.Args_);
+}
+
+template <class... TArgs>
+auto MakeLazyMultiValueFormatter(TStringBuf format, TArgs&&... args)
+{
+ return TLazyMultiValueFormatter<TArgs...>(format, std::forward<TArgs>(args)...);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
template <class T>
struct TFormatTraits
{
diff --git a/library/cpp/yt/string/format.h b/library/cpp/yt/string/format.h
index 9708fe5906..8e0d5f82e5 100644
--- a/library/cpp/yt/string/format.h
+++ b/library/cpp/yt/string/format.h
@@ -107,6 +107,45 @@ TFormatterWrapper<TFormatter> MakeFormatterWrapper(
////////////////////////////////////////////////////////////////////////////////
+template <class... TArgs>
+class TLazyMultiValueFormatter;
+
+template <class... TArgs>
+void FormatValue(
+ TStringBuilderBase* builder,
+ const TLazyMultiValueFormatter<TArgs...>& value,
+ TStringBuf /*format*/);
+
+//! A wrapper for a bunch of values that formats them lazily on demand.
+/*!
+ * The intended use of this class is when you need to use the same formatted string
+ * in several places in the function (e.g. log message tags) and want both to avoid
+ * code duplication and premature formatting of the values until necessary.
+ *
+ * NB: lvalues are captured by reference without lifetime extension.
+ */
+template <class... TArgs>
+class TLazyMultiValueFormatter
+ : private TNonCopyable
+{
+public:
+ TLazyMultiValueFormatter(TStringBuf format, TArgs&&... args);
+
+ friend void FormatValue<>(
+ TStringBuilderBase* builder,
+ const TLazyMultiValueFormatter& value,
+ TStringBuf /*format*/);
+
+private:
+ const TStringBuf Format_;
+ const std::tuple<TArgs...> Args_;
+};
+
+template <class ... Args>
+auto MakeLazyMultiValueFormatter(TStringBuf format, Args&&... args);
+
+////////////////////////////////////////////////////////////////////////////////
+
} // namespace NYT
#define FORMAT_INL_H_
diff --git a/library/cpp/yt/string/unittests/format_ut.cpp b/library/cpp/yt/string/unittests/format_ut.cpp
index 89aa01766f..e8965ee947 100644
--- a/library/cpp/yt/string/unittests/format_ut.cpp
+++ b/library/cpp/yt/string/unittests/format_ut.cpp
@@ -183,6 +183,19 @@ TEST(TFormatTest, Pointers)
}
}
+TEST(TFormatTest, LazyMultiValueFormatter)
+{
+ int i = 1;
+ TString s = "hello";
+ std::vector<int> range{1, 2, 3};
+ auto lazyFormatter = MakeLazyMultiValueFormatter(
+ "int: %v, string: %v, range: %v",
+ i,
+ s,
+ MakeFormattableView(range, TDefaultFormatter{}));
+ EXPECT_EQ("int: 1, string: hello, range: [1, 2, 3]", Format("%v", lazyFormatter));
+}
+
////////////////////////////////////////////////////////////////////////////////
} // namespace