diff options
author | babenko <babenko@yandex-team.ru> | 2022-02-10 16:49:19 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:49:19 +0300 |
commit | f31097c96270919a1f49360bdaaa69ea4f3fefab (patch) | |
tree | 5d5cb817648f650d76cf1076100726fd9b8448e8 /library/cpp/yt/string/format-inl.h | |
parent | cec37806d8847aa3db53bafc9e251d4aaf325c12 (diff) | |
download | ydb-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.h | 918 |
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 |