aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/string/format-inl.h
diff options
context:
space:
mode:
authorbabenko <babenko@yandex-team.ru>2022-02-10 16:49:19 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:49:19 +0300
commitf31097c96270919a1f49360bdaaa69ea4f3fefab (patch)
tree5d5cb817648f650d76cf1076100726fd9b8448e8 /library/cpp/yt/string/format-inl.h
parentcec37806d8847aa3db53bafc9e251d4aaf325c12 (diff)
downloadydb-f31097c96270919a1f49360bdaaa69ea4f3fefab.tar.gz
Restoring authorship annotation for <babenko@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/yt/string/format-inl.h')
-rw-r--r--library/cpp/yt/string/format-inl.h918
1 files changed, 459 insertions, 459 deletions
diff --git a/library/cpp/yt/string/format-inl.h b/library/cpp/yt/string/format-inl.h
index 550869846e..5484d4a216 100644
--- a/library/cpp/yt/string/format-inl.h
+++ b/library/cpp/yt/string/format-inl.h
@@ -1,72 +1,72 @@
-#ifndef FORMAT_INL_H_
-#error "Direct inclusion of this file is not allowed, include format.h"
+#ifndef FORMAT_INL_H_
+#error "Direct inclusion of this file is not allowed, include format.h"
// For the sake of sane code completion.
#include "format.h"
-#endif
-
+#endif
+
#include "enum.h"
-#include "string.h"
-
-#include <library/cpp/yt/assert/assert.h>
+#include "string.h"
+
+#include <library/cpp/yt/assert/assert.h>
#include <library/cpp/yt/small_containers/compact_vector.h>
-#include <library/cpp/yt/misc/enum.h>
+#include <library/cpp/yt/misc/enum.h>
#include <cctype>
#include <optional>
-namespace NYT {
-
-////////////////////////////////////////////////////////////////////////////////
-
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
static const char GenericSpecSymbol = 'v';
-
+
inline bool IsQuotationSpecSymbol(char symbol)
{
return symbol == 'Q' || symbol == 'q';
}
-// TStringBuf
-inline void FormatValue(TStringBuilderBase* builder, TStringBuf value, TStringBuf format)
-{
- if (!format) {
- builder->AppendString(value);
- return;
- }
-
- // Parse alignment.
- bool alignLeft = false;
- const char* current = format.begin();
- if (*current == '-') {
- alignLeft = true;
- ++current;
- }
-
- bool hasAlign = false;
- int alignSize = 0;
- while (*current >= '0' && *current <= '9') {
- hasAlign = true;
- alignSize = 10 * alignSize + (*current - '0');
- if (alignSize > 1000000) {
+// TStringBuf
+inline void FormatValue(TStringBuilderBase* builder, TStringBuf value, TStringBuf format)
+{
+ if (!format) {
+ builder->AppendString(value);
+ return;
+ }
+
+ // Parse alignment.
+ bool alignLeft = false;
+ const char* current = format.begin();
+ if (*current == '-') {
+ alignLeft = true;
+ ++current;
+ }
+
+ bool hasAlign = false;
+ int alignSize = 0;
+ while (*current >= '0' && *current <= '9') {
+ hasAlign = true;
+ alignSize = 10 * alignSize + (*current - '0');
+ if (alignSize > 1000000) {
builder->AppendString(TStringBuf("<alignment overflow>"));
- return;
- }
- ++current;
- }
-
- int padding = 0;
- bool padLeft = false;
- bool padRight = false;
- if (hasAlign) {
- padding = alignSize - value.size();
- if (padding < 0) {
- padding = 0;
- }
- padLeft = !alignLeft;
- padRight = alignLeft;
- }
-
+ return;
+ }
+ ++current;
+ }
+
+ int padding = 0;
+ bool padLeft = false;
+ bool padRight = false;
+ if (hasAlign) {
+ padding = alignSize - value.size();
+ if (padding < 0) {
+ padding = 0;
+ }
+ padLeft = !alignLeft;
+ padRight = alignLeft;
+ }
+
bool singleQuotes = false;
bool doubleQuotes = false;
while (current < format.end()) {
@@ -78,9 +78,9 @@ inline void FormatValue(TStringBuilderBase* builder, TStringBuf value, TStringBu
++current;
}
- if (padLeft) {
- builder->AppendChar(' ', padding);
- }
+ if (padLeft) {
+ builder->AppendChar(' ', padding);
+ }
if (singleQuotes || doubleQuotes) {
for (const char* valueCurrent = value.begin(); valueCurrent < value.end(); ++valueCurrent) {
@@ -104,92 +104,92 @@ inline void FormatValue(TStringBuilderBase* builder, TStringBuf value, TStringBu
builder->AppendString(value);
}
- if (padRight) {
- builder->AppendChar(' ', padding);
- }
-}
-
+ if (padRight) {
+ builder->AppendChar(' ', padding);
+ }
+}
+
// TString
-inline void FormatValue(TStringBuilderBase* builder, const TString& value, TStringBuf format)
-{
- FormatValue(builder, TStringBuf(value), format);
-}
-
-// const char*
-inline void FormatValue(TStringBuilderBase* builder, const char* value, TStringBuf format)
-{
- FormatValue(builder, TStringBuf(value), format);
-}
-
+inline void FormatValue(TStringBuilderBase* builder, const TString& value, TStringBuf format)
+{
+ FormatValue(builder, TStringBuf(value), format);
+}
+
+// const char*
+inline void FormatValue(TStringBuilderBase* builder, const char* value, TStringBuf format)
+{
+ FormatValue(builder, TStringBuf(value), format);
+}
+
// char
-inline void FormatValue(TStringBuilderBase* builder, char value, TStringBuf format)
+inline void FormatValue(TStringBuilderBase* builder, char value, TStringBuf format)
{
FormatValue(builder, TStringBuf(&value, 1), format);
}
-// bool
-inline void FormatValue(TStringBuilderBase* builder, bool value, TStringBuf format)
-{
- // Parse custom flags.
- bool lowercase = false;
- const char* current = format.begin();
- while (current != format.end()) {
- if (*current == 'l') {
- ++current;
- lowercase = true;
+// bool
+inline void FormatValue(TStringBuilderBase* builder, bool value, TStringBuf format)
+{
+ // Parse custom flags.
+ bool lowercase = false;
+ const char* current = format.begin();
+ while (current != format.end()) {
+ if (*current == 'l') {
+ ++current;
+ lowercase = true;
} else if (IsQuotationSpecSymbol(*current)) {
++current;
- } else
- break;
- }
-
- auto str = lowercase
+ } else
+ break;
+ }
+
+ auto str = lowercase
? (value ? TStringBuf("true") : TStringBuf("false"))
: (value ? TStringBuf("True") : TStringBuf("False"));
-
- builder->AppendString(str);
-}
-
-// Fallback to ToString
-struct TToStringFallbackValueFormatterTag
-{ };
-
-template <class TValue, class = void>
-struct TValueFormatter
-{
- static TToStringFallbackValueFormatterTag Do(TStringBuilderBase* builder, const TValue& value, TStringBuf format)
- {
- using ::ToString;
- FormatValue(builder, ToString(value), format);
- return {};
- }
-};
-
-// Enum
-template <class TEnum>
-struct TValueFormatter<TEnum, typename std::enable_if<TEnumTraits<TEnum>::IsEnum>::type>
-{
- static void Do(TStringBuilderBase* builder, TEnum value, TStringBuf format)
- {
- // Parse custom flags.
- bool lowercase = false;
- const char* current = format.begin();
- while (current != format.end()) {
- if (*current == 'l') {
- ++current;
- lowercase = true;
+
+ builder->AppendString(str);
+}
+
+// Fallback to ToString
+struct TToStringFallbackValueFormatterTag
+{ };
+
+template <class TValue, class = void>
+struct TValueFormatter
+{
+ static TToStringFallbackValueFormatterTag Do(TStringBuilderBase* builder, const TValue& value, TStringBuf format)
+ {
+ using ::ToString;
+ FormatValue(builder, ToString(value), format);
+ return {};
+ }
+};
+
+// Enum
+template <class TEnum>
+struct TValueFormatter<TEnum, typename std::enable_if<TEnumTraits<TEnum>::IsEnum>::type>
+{
+ static void Do(TStringBuilderBase* builder, TEnum value, TStringBuf format)
+ {
+ // Parse custom flags.
+ bool lowercase = false;
+ const char* current = format.begin();
+ while (current != format.end()) {
+ if (*current == 'l') {
+ ++current;
+ lowercase = true;
} else if (IsQuotationSpecSymbol(*current)) {
++current;
} else {
- break;
+ break;
}
- }
-
+ }
+
FormatEnum(builder, value, lowercase);
- }
-};
-
-template <class TRange, class TFormatter>
+ }
+};
+
+template <class TRange, class TFormatter>
typename TFormattableView<TRange, TFormatter>::TBegin TFormattableView<TRange, TFormatter>::begin() const
{
return RangeBegin;
@@ -203,42 +203,42 @@ typename TFormattableView<TRange, TFormatter>::TEnd TFormattableView<TRange, TFo
template <class TRange, class TFormatter>
TFormattableView<TRange, TFormatter> MakeFormattableView(
- const TRange& range,
+ const TRange& range,
TFormatter&& formatter)
-{
+{
return TFormattableView<TRange, std::decay_t<TFormatter>>{range.begin(), range.end(), std::forward<TFormatter>(formatter)};
-}
-
-template <class TRange, class TFormatter>
+}
+
+template <class TRange, class TFormatter>
TFormattableView<TRange, TFormatter> MakeShrunkFormattableView(
const TRange& range,
TFormatter&& formatter,
size_t limit)
-{
+{
return TFormattableView<TRange, std::decay_t<TFormatter>>{range.begin(), range.end(), std::forward<TFormatter>(formatter), limit};
}
template <class TRange, class TFormatter>
-void FormatRange(TStringBuilderBase* builder, const TRange& range, const TFormatter& formatter, size_t limit = std::numeric_limits<size_t>::max())
+void FormatRange(TStringBuilderBase* builder, const TRange& range, const TFormatter& formatter, size_t limit = std::numeric_limits<size_t>::max())
{
- builder->AppendChar('[');
+ builder->AppendChar('[');
size_t index = 0;
- for (const auto& item : range) {
+ for (const auto& item : range) {
if (index > 0) {
- builder->AppendString(DefaultJoinToStringDelimiter);
- }
+ builder->AppendString(DefaultJoinToStringDelimiter);
+ }
if (index == limit) {
builder->AppendString(DefaultRangeEllipsisFormat);
break;
}
- formatter(builder, item);
+ formatter(builder, item);
++index;
- }
- builder->AppendChar(']');
-}
-
+ }
+ builder->AppendChar(']');
+}
+
template <class TRange, class TFormatter>
-void FormatKeyValueRange(TStringBuilderBase* builder, const TRange& range, const TFormatter& formatter, size_t limit = std::numeric_limits<size_t>::max())
+void FormatKeyValueRange(TStringBuilderBase* builder, const TRange& range, const TFormatter& formatter, size_t limit = std::numeric_limits<size_t>::max())
{
builder->AppendChar('{');
size_t index = 0;
@@ -259,44 +259,44 @@ void FormatKeyValueRange(TStringBuilderBase* builder, const TRange& range, const
}
// TFormattableView
-template <class TRange, class TFormatter>
+template <class TRange, class TFormatter>
struct TValueFormatter<TFormattableView<TRange, TFormatter>>
-{
- static void Do(TStringBuilderBase* builder, const TFormattableView<TRange, TFormatter>& range, TStringBuf /*format*/)
- {
+{
+ static void Do(TStringBuilderBase* builder, const TFormattableView<TRange, TFormatter>& range, TStringBuf /*format*/)
+ {
FormatRange(builder, range, range.Formatter, range.Limit);
- }
-};
-
-template <class TFormatter>
-TFormatterWrapper<TFormatter> MakeFormatterWrapper(
- TFormatter&& formatter)
-{
- return TFormatterWrapper<TFormatter>{
- .Formatter = std::move(formatter)
- };
-}
-
-// TFormatterWrapper
-template <class TFormatter>
-struct TValueFormatter<TFormatterWrapper<TFormatter>>
-{
- static void Do(TStringBuilderBase* builder, const TFormatterWrapper<TFormatter>& wrapper, TStringBuf /*format*/)
- {
- wrapper.Formatter(builder);
- }
-};
-
-// std::vector
+ }
+};
+
+template <class TFormatter>
+TFormatterWrapper<TFormatter> MakeFormatterWrapper(
+ TFormatter&& formatter)
+{
+ return TFormatterWrapper<TFormatter>{
+ .Formatter = std::move(formatter)
+ };
+}
+
+// TFormatterWrapper
+template <class TFormatter>
+struct TValueFormatter<TFormatterWrapper<TFormatter>>
+{
+ static void Do(TStringBuilderBase* builder, const TFormatterWrapper<TFormatter>& wrapper, TStringBuf /*format*/)
+ {
+ wrapper.Formatter(builder);
+ }
+};
+
+// std::vector
template <class T, class TAllocator>
struct TValueFormatter<std::vector<T, TAllocator>>
-{
+{
static void Do(TStringBuilderBase* builder, const std::vector<T, TAllocator>& collection, TStringBuf /*format*/)
- {
- FormatRange(builder, collection, TDefaultFormatter());
- }
-};
-
+ {
+ FormatRange(builder, collection, TDefaultFormatter());
+ }
+};
+
// TCompactVector
template <class T, unsigned N>
struct TValueFormatter<TCompactVector<T, N>>
@@ -307,21 +307,21 @@ struct TValueFormatter<TCompactVector<T, N>>
}
};
-// std::set
-template <class T>
-struct TValueFormatter<std::set<T>>
-{
- static void Do(TStringBuilderBase* builder, const std::set<T>& collection, TStringBuf /*format*/)
- {
- FormatRange(builder, collection, TDefaultFormatter());
- }
-};
-
+// std::set
+template <class T>
+struct TValueFormatter<std::set<T>>
+{
+ static void Do(TStringBuilderBase* builder, const std::set<T>& collection, TStringBuf /*format*/)
+ {
+ FormatRange(builder, collection, TDefaultFormatter());
+ }
+};
+
// std::map
template <class K, class V>
struct TValueFormatter<std::map<K, V>>
{
- static void Do(TStringBuilderBase* builder, const std::map<K, V>& collection, TStringBuf /*format*/)
+ static void Do(TStringBuilderBase* builder, const std::map<K, V>& collection, TStringBuf /*format*/)
{
FormatKeyValueRange(builder, collection, TDefaultFormatter());
}
@@ -331,37 +331,37 @@ struct TValueFormatter<std::map<K, V>>
template <class K, class V>
struct TValueFormatter<std::multimap<K, V>>
{
- static void Do(TStringBuilderBase* builder, const std::multimap<K, V>& collection, TStringBuf /*format*/)
+ static void Do(TStringBuilderBase* builder, const std::multimap<K, V>& collection, TStringBuf /*format*/)
{
FormatKeyValueRange(builder, collection, TDefaultFormatter());
}
};
// THashSet
-template <class T>
+template <class T>
struct TValueFormatter<THashSet<T>>
-{
- static void Do(TStringBuilderBase* builder, const THashSet<T>& collection, TStringBuf /*format*/)
- {
- FormatRange(builder, collection, TDefaultFormatter());
- }
-};
-
-// THashMultiSet
-template <class T>
-struct TValueFormatter<THashMultiSet<T>>
-{
- static void Do(TStringBuilderBase* builder, const THashMultiSet<T>& collection, TStringBuf /*format*/)
- {
- FormatRange(builder, collection, TDefaultFormatter());
- }
-};
-
+{
+ static void Do(TStringBuilderBase* builder, const THashSet<T>& collection, TStringBuf /*format*/)
+ {
+ FormatRange(builder, collection, TDefaultFormatter());
+ }
+};
+
+// THashMultiSet
+template <class T>
+struct TValueFormatter<THashMultiSet<T>>
+{
+ static void Do(TStringBuilderBase* builder, const THashMultiSet<T>& collection, TStringBuf /*format*/)
+ {
+ FormatRange(builder, collection, TDefaultFormatter());
+ }
+};
+
// THashMap
template <class K, class V>
struct TValueFormatter<THashMap<K, V>>
{
- static void Do(TStringBuilderBase* builder, const THashMap<K, V>& collection, TStringBuf /*format*/)
+ static void Do(TStringBuilderBase* builder, const THashMap<K, V>& collection, TStringBuf /*format*/)
{
FormatKeyValueRange(builder, collection, TDefaultFormatter());
}
@@ -371,7 +371,7 @@ struct TValueFormatter<THashMap<K, V>>
template <class K, class V>
struct TValueFormatter<THashMultiMap<K, V>>
{
- static void Do(TStringBuilderBase* builder, const THashMultiMap<K, V>& collection, TStringBuf /*format*/)
+ static void Do(TStringBuilderBase* builder, const THashMultiMap<K, V>& collection, TStringBuf /*format*/)
{
FormatKeyValueRange(builder, collection, TDefaultFormatter());
}
@@ -412,42 +412,42 @@ struct TValueFormatter<std::pair<T1, T2>>
}
};
-// std::optional
-inline void FormatValue(TStringBuilderBase* builder, std::nullopt_t, TStringBuf /*format*/)
-{
+// std::optional
+inline void FormatValue(TStringBuilderBase* builder, std::nullopt_t, TStringBuf /*format*/)
+{
builder->AppendString(TStringBuf("<null>"));
-}
-
-template <class T>
-struct TValueFormatter<std::optional<T>>
-{
- static void Do(TStringBuilderBase* builder, const std::optional<T>& value, TStringBuf format)
- {
- if (value) {
- FormatValue(builder, *value, format);
- } else {
- FormatValue(builder, std::nullopt, format);
- }
- }
-};
-
-template <class TValue>
-auto FormatValue(TStringBuilderBase* builder, const TValue& value, TStringBuf format) ->
- decltype(TValueFormatter<TValue>::Do(builder, value, format))
-{
- return TValueFormatter<TValue>::Do(builder, value, format);
-}
-
-template <class TValue>
+}
+
+template <class T>
+struct TValueFormatter<std::optional<T>>
+{
+ static void Do(TStringBuilderBase* builder, const std::optional<T>& value, TStringBuf format)
+ {
+ if (value) {
+ FormatValue(builder, *value, format);
+ } else {
+ FormatValue(builder, std::nullopt, format);
+ }
+ }
+};
+
+template <class TValue>
+auto FormatValue(TStringBuilderBase* builder, const TValue& value, TStringBuf format) ->
+ decltype(TValueFormatter<TValue>::Do(builder, value, format))
+{
+ return TValueFormatter<TValue>::Do(builder, value, format);
+}
+
+template <class TValue>
void FormatValueViaSprintf(
- TStringBuilderBase* builder,
+ TStringBuilderBase* builder,
TValue value,
- TStringBuf format,
- TStringBuf genericSpec)
-{
- constexpr int MaxFormatSize = 64;
- constexpr int SmallResultSize = 64;
-
+ TStringBuf format,
+ TStringBuf genericSpec)
+{
+ constexpr int MaxFormatSize = 64;
+ constexpr int SmallResultSize = 64;
+
auto copyFormat = [] (char* destination, const char* source, int length) {
int position = 0;
for (int index = 0; index < length; ++index) {
@@ -460,32 +460,32 @@ void FormatValueViaSprintf(
return destination + position;
};
- 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) {
+ 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) {
char* formatEnd = copyFormat(formatBuf + 1, format.begin(), format.length() - 1);
- ::memcpy(formatEnd, genericSpec.begin(), genericSpec.length());
+ ::memcpy(formatEnd, genericSpec.begin(), genericSpec.length());
formatEnd[genericSpec.length()] = '\0';
- } else {
+ } else {
char* formatEnd = copyFormat(formatBuf + 1, format.begin(), format.length());
*formatEnd = '\0';
- }
-
+ }
+
char* result = builder->Preallocate(SmallResultSize);
- size_t resultSize = ::snprintf(result, SmallResultSize, formatBuf, value);
+ size_t resultSize = ::snprintf(result, SmallResultSize, formatBuf, value);
if (resultSize >= SmallResultSize) {
result = builder->Preallocate(resultSize + 1);
- YT_VERIFY(::snprintf(result, resultSize + 1, formatBuf, value) == static_cast<int>(resultSize));
+ YT_VERIFY(::snprintf(result, resultSize + 1, formatBuf, value) == static_cast<int>(resultSize));
}
- builder->Advance(resultSize);
-}
-
+ builder->Advance(resultSize);
+}
+
template <class TValue>
char* WriteIntToBufferBackwards(char* buffer, TValue value);
template <class TValue>
-void FormatValueViaHelper(TStringBuilderBase* builder, TValue value, TStringBuf format, TStringBuf genericSpec)
+void FormatValueViaHelper(TStringBuilderBase* builder, TValue value, TStringBuf format, TStringBuf genericSpec)
{
if (format == TStringBuf("v")) {
const int MaxResultSize = 64;
@@ -499,11 +499,11 @@ void FormatValueViaHelper(TStringBuilderBase* builder, TValue value, TStringBuf
}
#define XX(valueType, castType, genericSpec) \
- inline void FormatValue(TStringBuilderBase* builder, valueType value, TStringBuf format) \
- { \
+ inline void FormatValue(TStringBuilderBase* builder, valueType value, TStringBuf format) \
+ { \
FormatValueViaHelper(builder, static_cast<castType>(value), format, genericSpec); \
- }
-
+ }
+
XX(i8, int, TStringBuf("d"))
XX(ui8, unsigned int, TStringBuf("u"))
XX(i16, int, TStringBuf("d"))
@@ -512,11 +512,11 @@ XX(i32, int, TStringBuf("d"))
XX(ui32, unsigned int, TStringBuf("u"))
XX(long, long, TStringBuf("ld"))
XX(unsigned long, unsigned long, TStringBuf("lu"))
-
+
#undef XX
-
+
#define XX(valueType, castType, genericSpec) \
- inline void FormatValue(TStringBuilderBase* builder, valueType value, TStringBuf format) \
+ inline void FormatValue(TStringBuilderBase* builder, valueType value, TStringBuf format) \
{ \
FormatValueViaSprintf(builder, static_cast<castType>(value), format, genericSpec); \
}
@@ -526,219 +526,219 @@ XX(float, float, TStringBuf("f"))
#undef XX
-// Pointer
+// Pointer
template <class T>
-void FormatValue(TStringBuilderBase* builder, T* value, TStringBuf format)
+void FormatValue(TStringBuilderBase* builder, T* value, TStringBuf format)
{
FormatValueViaSprintf(builder, value, format, TStringBuf("p"));
}
// TDuration (specialize for performance reasons)
-inline void FormatValue(TStringBuilderBase* builder, TDuration value, TStringBuf /*format*/)
+inline void FormatValue(TStringBuilderBase* builder, TDuration value, TStringBuf /*format*/)
+{
+ builder->AppendFormat("%vus", value.MicroSeconds());
+}
+
+// TInstant (specialize for TFormatTraits)
+inline void FormatValue(TStringBuilderBase* builder, TInstant value, TStringBuf format)
{
- builder->AppendFormat("%vus", value.MicroSeconds());
+ // TODO(babenko): optimize
+ builder->AppendFormat("%v", ToString(value), format);
}
-// TInstant (specialize for TFormatTraits)
-inline void FormatValue(TStringBuilderBase* builder, TInstant value, TStringBuf format)
-{
- // TODO(babenko): optimize
- builder->AppendFormat("%v", ToString(value), format);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <class TArgFormatter>
-void FormatImpl(
- TStringBuilderBase* builder,
- TStringBuf format,
- const TArgFormatter& argFormatter)
-{
- size_t argIndex = 0;
- auto current = format.begin();
- while (true) {
- // Scan verbatim part until stop symbol.
- auto verbatimBegin = current;
- auto verbatimEnd = verbatimBegin;
- while (verbatimEnd != format.end() && *verbatimEnd != '%') {
- ++verbatimEnd;
- }
-
- // Copy verbatim part, if any.
- size_t verbatimSize = verbatimEnd - verbatimBegin;
- if (verbatimSize > 0) {
- builder->AppendString(TStringBuf(verbatimBegin, verbatimSize));
- }
-
- // Handle stop symbol.
- current = verbatimEnd;
- if (current == format.end()) {
- break;
- }
-
- YT_ASSERT(*current == '%');
- ++current;
-
- if (*current == '%') {
- // Verbatim %.
- builder->AppendChar('%');
- ++current;
- } else {
- // Scan format part until stop symbol.
- auto argFormatBegin = current;
- auto argFormatEnd = argFormatBegin;
+////////////////////////////////////////////////////////////////////////////////
+
+template <class TArgFormatter>
+void FormatImpl(
+ TStringBuilderBase* builder,
+ TStringBuf format,
+ const TArgFormatter& argFormatter)
+{
+ size_t argIndex = 0;
+ auto current = format.begin();
+ while (true) {
+ // Scan verbatim part until stop symbol.
+ auto verbatimBegin = current;
+ auto verbatimEnd = verbatimBegin;
+ while (verbatimEnd != format.end() && *verbatimEnd != '%') {
+ ++verbatimEnd;
+ }
+
+ // Copy verbatim part, if any.
+ size_t verbatimSize = verbatimEnd - verbatimBegin;
+ if (verbatimSize > 0) {
+ builder->AppendString(TStringBuf(verbatimBegin, verbatimSize));
+ }
+
+ // Handle stop symbol.
+ current = verbatimEnd;
+ if (current == format.end()) {
+ break;
+ }
+
+ YT_ASSERT(*current == '%');
+ ++current;
+
+ if (*current == '%') {
+ // Verbatim %.
+ builder->AppendChar('%');
+ ++current;
+ } else {
+ // Scan format part until stop symbol.
+ auto argFormatBegin = current;
+ auto argFormatEnd = argFormatBegin;
bool singleQuotes = false;
bool doubleQuotes = false;
- while (
- argFormatEnd != format.end() &&
- *argFormatEnd != GenericSpecSymbol && // value in generic format
- *argFormatEnd != 'd' && // others are standard specifiers supported by printf
- *argFormatEnd != 'i' &&
- *argFormatEnd != 'u' &&
- *argFormatEnd != 'o' &&
- *argFormatEnd != 'x' &&
- *argFormatEnd != 'X' &&
- *argFormatEnd != 'f' &&
- *argFormatEnd != 'F' &&
- *argFormatEnd != 'e' &&
- *argFormatEnd != 'E' &&
- *argFormatEnd != 'g' &&
- *argFormatEnd != 'G' &&
- *argFormatEnd != 'a' &&
- *argFormatEnd != 'A' &&
- *argFormatEnd != 'c' &&
- *argFormatEnd != 's' &&
- *argFormatEnd != 'p' &&
- *argFormatEnd != 'n')
- {
+ while (
+ argFormatEnd != format.end() &&
+ *argFormatEnd != GenericSpecSymbol && // value in generic format
+ *argFormatEnd != 'd' && // others are standard specifiers supported by printf
+ *argFormatEnd != 'i' &&
+ *argFormatEnd != 'u' &&
+ *argFormatEnd != 'o' &&
+ *argFormatEnd != 'x' &&
+ *argFormatEnd != 'X' &&
+ *argFormatEnd != 'f' &&
+ *argFormatEnd != 'F' &&
+ *argFormatEnd != 'e' &&
+ *argFormatEnd != 'E' &&
+ *argFormatEnd != 'g' &&
+ *argFormatEnd != 'G' &&
+ *argFormatEnd != 'a' &&
+ *argFormatEnd != 'A' &&
+ *argFormatEnd != 'c' &&
+ *argFormatEnd != 's' &&
+ *argFormatEnd != 'p' &&
+ *argFormatEnd != 'n')
+ {
if (*argFormatEnd == 'q') {
singleQuotes = true;
} else if (*argFormatEnd == 'Q') {
doubleQuotes = true;
}
- ++argFormatEnd;
- }
-
- // Handle end of format string.
- if (argFormatEnd != format.end()) {
- ++argFormatEnd;
- }
-
- // 'n' means 'nothing'; skip the argument.
- if (*argFormatBegin != 'n') {
- // Format argument.
- TStringBuf argFormat(argFormatBegin, argFormatEnd);
- if (singleQuotes) {
- builder->AppendChar('\'');
- }
- if (doubleQuotes) {
- builder->AppendChar('"');
- }
- argFormatter(argIndex++, builder, argFormat);
- if (singleQuotes) {
- builder->AppendChar('\'');
- }
- if (doubleQuotes) {
- builder->AppendChar('"');
- }
- }
-
- current = argFormatEnd;
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <class T>
-struct TFormatTraits
-{
- static constexpr bool HasCustomFormatValue = !std::is_same_v<
- decltype(FormatValue(
- static_cast<TStringBuilderBase*>(nullptr),
- *static_cast<const T*>(nullptr),
- TStringBuf())),
- TToStringFallbackValueFormatterTag>;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <size_t IndexBase, class... TArgs>
-struct TArgFormatterImpl;
-
-template <size_t IndexBase>
-struct TArgFormatterImpl<IndexBase>
-{
- void operator() (size_t /*index*/, TStringBuilderBase* builder, TStringBuf /*format*/) const
- {
+ ++argFormatEnd;
+ }
+
+ // Handle end of format string.
+ if (argFormatEnd != format.end()) {
+ ++argFormatEnd;
+ }
+
+ // 'n' means 'nothing'; skip the argument.
+ if (*argFormatBegin != 'n') {
+ // Format argument.
+ TStringBuf argFormat(argFormatBegin, argFormatEnd);
+ if (singleQuotes) {
+ builder->AppendChar('\'');
+ }
+ if (doubleQuotes) {
+ builder->AppendChar('"');
+ }
+ argFormatter(argIndex++, builder, argFormat);
+ if (singleQuotes) {
+ builder->AppendChar('\'');
+ }
+ if (doubleQuotes) {
+ builder->AppendChar('"');
+ }
+ }
+
+ current = argFormatEnd;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+struct TFormatTraits
+{
+ static constexpr bool HasCustomFormatValue = !std::is_same_v<
+ decltype(FormatValue(
+ static_cast<TStringBuilderBase*>(nullptr),
+ *static_cast<const T*>(nullptr),
+ TStringBuf())),
+ TToStringFallbackValueFormatterTag>;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <size_t IndexBase, class... TArgs>
+struct TArgFormatterImpl;
+
+template <size_t IndexBase>
+struct TArgFormatterImpl<IndexBase>
+{
+ void operator() (size_t /*index*/, TStringBuilderBase* builder, TStringBuf /*format*/) const
+ {
builder->AppendString(TStringBuf("<missing argument>"));
- }
-};
-
-template <size_t IndexBase, class THeadArg, class... TTailArgs>
-struct TArgFormatterImpl<IndexBase, THeadArg, TTailArgs...>
-{
- explicit TArgFormatterImpl(const THeadArg& headArg, const TTailArgs&... tailArgs)
- : HeadArg(headArg)
- , TailFormatter(tailArgs...)
- { }
-
- const THeadArg& HeadArg;
- TArgFormatterImpl<IndexBase + 1, TTailArgs...> TailFormatter;
-
- void operator() (size_t index, TStringBuilderBase* builder, TStringBuf format) const
- {
- YT_ASSERT(index >= IndexBase);
- if (index == IndexBase) {
- FormatValue(builder, HeadArg, format);
- } else {
- TailFormatter(index, builder, format);
- }
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <size_t Length, class... TArgs>
-void Format(
- TStringBuilderBase* builder,
- const char (&format)[Length],
- TArgs&&... args)
-{
- Format(builder, TStringBuf(format, Length - 1), std::forward<TArgs>(args)...);
-}
-
-template <class... TArgs>
-void Format(
- TStringBuilderBase* builder,
- TStringBuf format,
- TArgs&&... args)
-{
- TArgFormatterImpl<0, TArgs...> argFormatter(args...);
- FormatImpl(builder, format, argFormatter);
-}
-
-template <size_t Length, class... TArgs>
-TString Format(
- const char (&format)[Length],
- TArgs&&... args)
-{
- TStringBuilder builder;
- Format(&builder, format, std::forward<TArgs>(args)...);
- return builder.Flush();
-}
-
-template <class... TArgs>
+ }
+};
+
+template <size_t IndexBase, class THeadArg, class... TTailArgs>
+struct TArgFormatterImpl<IndexBase, THeadArg, TTailArgs...>
+{
+ explicit TArgFormatterImpl(const THeadArg& headArg, const TTailArgs&... tailArgs)
+ : HeadArg(headArg)
+ , TailFormatter(tailArgs...)
+ { }
+
+ const THeadArg& HeadArg;
+ TArgFormatterImpl<IndexBase + 1, TTailArgs...> TailFormatter;
+
+ void operator() (size_t index, TStringBuilderBase* builder, TStringBuf format) const
+ {
+ YT_ASSERT(index >= IndexBase);
+ if (index == IndexBase) {
+ FormatValue(builder, HeadArg, format);
+ } else {
+ TailFormatter(index, builder, format);
+ }
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <size_t Length, class... TArgs>
+void Format(
+ TStringBuilderBase* builder,
+ const char (&format)[Length],
+ TArgs&&... args)
+{
+ Format(builder, TStringBuf(format, Length - 1), std::forward<TArgs>(args)...);
+}
+
+template <class... TArgs>
+void Format(
+ TStringBuilderBase* builder,
+ TStringBuf format,
+ TArgs&&... args)
+{
+ TArgFormatterImpl<0, TArgs...> argFormatter(args...);
+ FormatImpl(builder, format, argFormatter);
+}
+
+template <size_t Length, class... TArgs>
+TString Format(
+ const char (&format)[Length],
+ TArgs&&... args)
+{
+ TStringBuilder builder;
+ Format(&builder, format, std::forward<TArgs>(args)...);
+ return builder.Flush();
+}
+
+template <class... TArgs>
TString Format(
- TStringBuf format,
- TArgs&&... args)
-{
- TStringBuilder builder;
- Format(&builder, format, std::forward<TArgs>(args)...);
- return builder.Flush();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-} // namespace NYT
+ TStringBuf format,
+ TArgs&&... args)
+{
+ TStringBuilder builder;
+ Format(&builder, format, std::forward<TArgs>(args)...);
+ return builder.Flush();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT