format.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "format.h"
  2. #include "string.h"
  3. namespace NYT::NDetail {
  4. ////////////////////////////////////////////////////////////////////////////////
  5. template <class TValue>
  6. void FormatValueViaSprintf(
  7. TStringBuilderBase* builder,
  8. TValue value,
  9. TStringBuf format,
  10. TStringBuf genericSpec)
  11. {
  12. constexpr int MaxFormatSize = 64;
  13. constexpr int SmallResultSize = 64;
  14. auto copyFormat = [] (char* destination, const char* source, int length) {
  15. int position = 0;
  16. for (int index = 0; index < length; ++index) {
  17. if (IsQuotationSpecSymbol(source[index])) {
  18. continue;
  19. }
  20. destination[position] = source[index];
  21. ++position;
  22. }
  23. return destination + position;
  24. };
  25. char formatBuf[MaxFormatSize];
  26. YT_VERIFY(format.length() >= 1 && format.length() <= MaxFormatSize - 2); // one for %, one for \0
  27. formatBuf[0] = '%';
  28. if (format.back() == GenericSpecSymbol) {
  29. char* formatEnd = copyFormat(formatBuf + 1, format.begin(), format.length() - 1);
  30. ::memcpy(formatEnd, genericSpec.begin(), genericSpec.length());
  31. formatEnd[genericSpec.length()] = '\0';
  32. } else {
  33. char* formatEnd = copyFormat(formatBuf + 1, format.begin(), format.length());
  34. *formatEnd = '\0';
  35. }
  36. char* result = builder->Preallocate(SmallResultSize);
  37. size_t resultSize = ::snprintf(result, SmallResultSize, formatBuf, value);
  38. if (resultSize >= SmallResultSize) {
  39. result = builder->Preallocate(resultSize + 1);
  40. YT_VERIFY(::snprintf(result, resultSize + 1, formatBuf, value) == static_cast<int>(resultSize));
  41. }
  42. builder->Advance(resultSize);
  43. }
  44. #define XX(type) \
  45. template \
  46. void FormatValueViaSprintf( \
  47. TStringBuilderBase* builder, \
  48. type value, \
  49. TStringBuf format, \
  50. TStringBuf genericSpec);
  51. XX(i32)
  52. XX(ui32)
  53. XX(i64)
  54. XX(ui64)
  55. XX(float)
  56. XX(double)
  57. XX(const void*)
  58. #undef XX
  59. template <class TValue>
  60. void FormatIntValue(
  61. TStringBuilderBase* builder,
  62. TValue value,
  63. TStringBuf format,
  64. TStringBuf genericSpec)
  65. {
  66. if (format == TStringBuf("v")) {
  67. constexpr int MaxResultSize = 64;
  68. char buffer[MaxResultSize];
  69. char* end = buffer + MaxResultSize;
  70. char* start = WriteDecIntToBufferBackwards(end, value);
  71. builder->AppendString(TStringBuf(start, end));
  72. } else if (format == TStringBuf("x") || format == TStringBuf("X")) {
  73. constexpr int MaxResultSize = 64;
  74. char buffer[MaxResultSize];
  75. char* end = buffer + MaxResultSize;
  76. char* start = WriteHexIntToBufferBackwards(end, value, format[0] == 'X');
  77. builder->AppendString(TStringBuf(start, end));
  78. } else {
  79. FormatValueViaSprintf(builder, value, format, genericSpec);
  80. }
  81. }
  82. #define XX(type) \
  83. template \
  84. void FormatIntValue( \
  85. TStringBuilderBase* builder, \
  86. type value, \
  87. TStringBuf format, \
  88. TStringBuf genericSpec);
  89. XX(i32)
  90. XX(ui32)
  91. XX(i64)
  92. XX(ui64)
  93. #undef XX
  94. void FormatPointerValue(
  95. TStringBuilderBase* builder,
  96. const void* value,
  97. TStringBuf format)
  98. {
  99. static_assert(sizeof(value) == sizeof(ui64));
  100. if (format == TStringBuf("p") || format == TStringBuf("v")) {
  101. builder->AppendString(TStringBuf("0x"));
  102. FormatValue(builder, reinterpret_cast<ui64>(value), TStringBuf("x"));
  103. } else if (format == TStringBuf("x") || format == TStringBuf("X")) {
  104. FormatValue(builder, reinterpret_cast<ui64>(value), format);
  105. } else {
  106. builder->AppendString("<invalid pointer format>");
  107. }
  108. }
  109. ////////////////////////////////////////////////////////////////////////////////
  110. } // namespace NYT::NDetail