format.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #pragma once
  2. #include "string_builder.h"
  3. namespace NYT {
  4. ////////////////////////////////////////////////////////////////////////////////
  5. /*
  6. * Format: a type-safe and fast formatting utility.
  7. *
  8. * Basically works as a type-safe analogue of |sprintf| and is expected to
  9. * be backwards-compatible with the latter.
  10. *
  11. * Like Go's |Sprintf|, supports the ultimate format specifier |v|
  12. * causing arguments to be emitted in default format.
  13. * This is the default and preferred way of formatting things,
  14. * which should be used in newer code.
  15. *
  16. * |Format| may currently invoke |sprintf| internally for emitting numeric and some other
  17. * types. You can always write your own optimized implementation, if you wish :)
  18. *
  19. * In additional to the usual |sprintf|, supports a number of non-standard flags:
  20. *
  21. * |q| Causes the argument to be surrounded with single quotes (|'|).
  22. * Applies to all types.
  23. *
  24. * |Q| Causes the argument to be surrounded with double quotes (|"|).
  25. * Applies to all types.
  26. *
  27. * |l| The argument is emitted in "lowercase" style.
  28. * Only applies to enums and bools.
  29. *
  30. * The following argument types are supported:
  31. *
  32. * Strings (including |const char*|, |TStringBuf|, and |TString|) and chars:
  33. * Emitted as is. Fast.
  34. *
  35. * Numerics and pointers:
  36. * Emitted using |sprintf|. Maybe not that fast.
  37. *
  38. * |bool|:
  39. * Emitted either as |True| and |False| or |true| and |false| (if lowercase mode is ON).
  40. *
  41. * Enums:
  42. * Emitted in either camel (|SomeName|) or in lowercase-with-underscores style
  43. * (|some_name|, if lowercase mode is ON).
  44. *
  45. * Nullables:
  46. * |std::nullopt| is emitted as |<null>|.
  47. *
  48. * All others:
  49. * Emitted as strings by calling |ToString|.
  50. *
  51. */
  52. template <size_t Length, class... TArgs>
  53. void Format(TStringBuilderBase* builder, const char (&format)[Length], TArgs&&... args);
  54. template <class... TArgs>
  55. void Format(TStringBuilderBase* builder, TStringBuf format, TArgs&&... args);
  56. template <size_t Length, class... TArgs>
  57. TString Format(const char (&format)[Length], TArgs&&... args);
  58. template <class... TArgs>
  59. TString Format(TStringBuf format, TArgs&&... args);
  60. ////////////////////////////////////////////////////////////////////////////////
  61. template <class TRange, class TFormatter>
  62. struct TFormattableView
  63. {
  64. using TBegin = std::decay_t<decltype(std::declval<const TRange>().begin())>;
  65. using TEnd = std::decay_t<decltype(std::declval<const TRange>().end())>;
  66. TBegin RangeBegin;
  67. TEnd RangeEnd;
  68. TFormatter Formatter;
  69. size_t Limit = std::numeric_limits<size_t>::max();
  70. TBegin begin() const;
  71. TEnd end() const;
  72. };
  73. //! Annotates a given #range with #formatter to be applied to each item.
  74. template <class TRange, class TFormatter>
  75. TFormattableView<TRange, TFormatter> MakeFormattableView(
  76. const TRange& range,
  77. TFormatter&& formatter);
  78. template <class TRange, class TFormatter>
  79. TFormattableView<TRange, TFormatter> MakeShrunkFormattableView(
  80. const TRange& range,
  81. TFormatter&& formatter,
  82. size_t limit);
  83. ////////////////////////////////////////////////////////////////////////////////
  84. template <class TFormatter>
  85. struct TFormatterWrapper
  86. {
  87. TFormatter Formatter;
  88. };
  89. template <class TFormatter>
  90. TFormatterWrapper<TFormatter> MakeFormatterWrapper(
  91. TFormatter&& formatter);
  92. ////////////////////////////////////////////////////////////////////////////////
  93. template <class... TArgs>
  94. class TLazyMultiValueFormatter;
  95. template <class... TArgs>
  96. void FormatValue(
  97. TStringBuilderBase* builder,
  98. const TLazyMultiValueFormatter<TArgs...>& value,
  99. TStringBuf /*format*/);
  100. //! A wrapper for a bunch of values that formats them lazily on demand.
  101. /*!
  102. * The intended use of this class is when you need to use the same formatted string
  103. * in several places in the function (e.g. log message tags) and want both to avoid
  104. * code duplication and premature formatting of the values until necessary.
  105. *
  106. * NB: lvalues are captured by reference without lifetime extension.
  107. */
  108. template <class... TArgs>
  109. class TLazyMultiValueFormatter
  110. : private TNonCopyable
  111. {
  112. public:
  113. TLazyMultiValueFormatter(TStringBuf format, TArgs&&... args);
  114. friend void FormatValue<>(
  115. TStringBuilderBase* builder,
  116. const TLazyMultiValueFormatter& value,
  117. TStringBuf /*format*/);
  118. private:
  119. const TStringBuf Format_;
  120. const std::tuple<TArgs...> Args_;
  121. };
  122. template <class ... Args>
  123. auto MakeLazyMultiValueFormatter(TStringBuf format, Args&&... args);
  124. ////////////////////////////////////////////////////////////////////////////////
  125. } // namespace NYT
  126. #define FORMAT_INL_H_
  127. #include "format-inl.h"
  128. #undef FORMAT_INL_H_