format_arg.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #pragma once
  2. #include <util/generic/strbuf.h>
  3. #include <array>
  4. #include <string_view>
  5. namespace NYT {
  6. ////////////////////////////////////////////////////////////////////////////////
  7. class TStringBuilderBase;
  8. ////////////////////////////////////////////////////////////////////////////////
  9. namespace NDetail {
  10. template <class T>
  11. constexpr std::string_view QualidName();
  12. template <class T>
  13. constexpr bool IsNYTName();
  14. } // namespace NDetail
  15. ////////////////////////////////////////////////////////////////////////////////
  16. // Base used for flag checks for each type independently.
  17. // Use it for overrides.
  18. class TFormatArgBase
  19. {
  20. public:
  21. // TODO(arkady-e1ppa): Consider more strict formatting rules.
  22. static constexpr std::array ConversionSpecifiers = {
  23. 'v', '1', 'c', 's', 'd', 'i', 'o',
  24. 'x', 'X', 'u', 'f', 'F', 'e', 'E',
  25. 'a', 'A', 'g', 'G', 'n', 'p'
  26. };
  27. static constexpr std::array FlagSpecifiers = {
  28. '-', '+', ' ', '#', '0',
  29. '1', '2', '3', '4', '5',
  30. '6', '7', '8', '9',
  31. '*', '.', 'h', 'l', 'j',
  32. 'z', 't', 'L', 'q', 'Q'
  33. };
  34. template <class T>
  35. static constexpr bool IsSpecifierList = requires (T t) {
  36. [] <size_t N> (std::array<char, N>) { } (t);
  37. };
  38. // Hot = |true| adds specifiers to the beggining
  39. // of a new array.
  40. template <bool Hot, size_t N, std::array<char, N> List, class TFrom = TFormatArgBase>
  41. static consteval auto ExtendConversion();
  42. template <bool Hot, size_t N, std::array<char, N> List, class TFrom = TFormatArgBase>
  43. static consteval auto ExtendFlags();
  44. private:
  45. template <bool Hot, size_t N, std::array<char, N> List, auto* From>
  46. static consteval auto AppendArrays();
  47. };
  48. ////////////////////////////////////////////////////////////////////////////////
  49. template <class T>
  50. struct TFormatArg
  51. : public TFormatArgBase
  52. { };
  53. // Ultimate customization point mechanism --- define an overload
  54. // of FormatValue in order to support formatting of your type.
  55. // Semantic requirement:
  56. // Said field must be constexpr.
  57. template <class T>
  58. concept CFormattable =
  59. requires {
  60. TFormatArg<T>::ConversionSpecifiers;
  61. requires TFormatArgBase::IsSpecifierList<decltype(TFormatArg<T>::ConversionSpecifiers)>;
  62. TFormatArg<T>::FlagSpecifiers;
  63. requires TFormatArgBase::IsSpecifierList<decltype(TFormatArg<T>::FlagSpecifiers)>;
  64. } &&
  65. requires (
  66. TStringBuilderBase* builder,
  67. const T& value,
  68. TStringBuf spec
  69. ) {
  70. { FormatValue(builder, value, spec) } -> std::same_as<void>;
  71. };
  72. ////////////////////////////////////////////////////////////////////////////////
  73. } // namespace NYT
  74. #define FORMAT_ARG_INL_H_
  75. #include "format_arg-inl.h"
  76. #undef FORMAT_ARG_INL_H_