string_builder-inl.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #ifndef STRING_BUILDER_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include string.h"
  3. // For the sake of sane code completion.
  4. #include "string_builder.h"
  5. #endif
  6. #include <library/cpp/yt/assert/assert.h>
  7. namespace NYT {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. inline char* TStringBuilderBase::Preallocate(size_t size)
  10. {
  11. if (Y_UNLIKELY(End_ - Current_ < static_cast<ssize_t>(size))) {
  12. size_t length = GetLength();
  13. auto newLength = std::max(length + size, MinBufferLength);
  14. DoPreallocate(newLength);
  15. Current_ = Begin_ + length;
  16. }
  17. return Current_;
  18. }
  19. inline size_t TStringBuilderBase::GetLength() const
  20. {
  21. return Current_ ? Current_ - Begin_ : 0;
  22. }
  23. inline TStringBuf TStringBuilderBase::GetBuffer() const
  24. {
  25. return TStringBuf(Begin_, Current_);
  26. }
  27. inline void TStringBuilderBase::Advance(size_t size)
  28. {
  29. Current_ += size;
  30. YT_ASSERT(Current_ <= End_);
  31. }
  32. inline void TStringBuilderBase::AppendChar(char ch)
  33. {
  34. *Preallocate(1) = ch;
  35. Advance(1);
  36. }
  37. inline void TStringBuilderBase::AppendChar(char ch, int n)
  38. {
  39. YT_ASSERT(n >= 0);
  40. if (Y_LIKELY(0 != n)) {
  41. char* dst = Preallocate(n);
  42. ::memset(dst, ch, n);
  43. Advance(n);
  44. }
  45. }
  46. inline void TStringBuilderBase::AppendString(TStringBuf str)
  47. {
  48. if (Y_LIKELY(str)) {
  49. char* dst = Preallocate(str.length());
  50. ::memcpy(dst, str.begin(), str.length());
  51. Advance(str.length());
  52. }
  53. }
  54. inline void TStringBuilderBase::AppendString(const char* str)
  55. {
  56. AppendString(TStringBuf(str));
  57. }
  58. inline void TStringBuilderBase::Reset()
  59. {
  60. Begin_ = Current_ = End_ = nullptr;
  61. DoReset();
  62. }
  63. template <class... TArgs>
  64. void TStringBuilderBase::AppendFormat(TStringBuf format, TArgs&& ... args)
  65. {
  66. Format(this, format, std::forward<TArgs>(args)...);
  67. }
  68. template <size_t Length, class... TArgs>
  69. void TStringBuilderBase::AppendFormat(const char (&format)[Length], TArgs&& ... args)
  70. {
  71. Format(this, format, std::forward<TArgs>(args)...);
  72. }
  73. ////////////////////////////////////////////////////////////////////////////////
  74. inline TString TStringBuilder::Flush()
  75. {
  76. Buffer_.resize(GetLength());
  77. auto result = std::move(Buffer_);
  78. Reset();
  79. return result;
  80. }
  81. inline void TStringBuilder::DoReset()
  82. {
  83. Buffer_ = {};
  84. }
  85. inline void TStringBuilder::DoPreallocate(size_t newLength)
  86. {
  87. Buffer_.ReserveAndResize(newLength);
  88. auto capacity = Buffer_.capacity();
  89. Buffer_.ReserveAndResize(capacity);
  90. Begin_ = &*Buffer_.begin();
  91. End_ = Begin_ + capacity;
  92. }
  93. ////////////////////////////////////////////////////////////////////////////////
  94. inline void FormatValue(TStringBuilderBase* builder, const TStringBuilder& value, TStringBuf /*format*/)
  95. {
  96. builder->AppendString(value.GetBuffer());
  97. }
  98. template <class T>
  99. TString ToStringViaBuilder(const T& value, TStringBuf spec)
  100. {
  101. TStringBuilder builder;
  102. FormatValue(&builder, value, spec);
  103. return builder.Flush();
  104. }
  105. ////////////////////////////////////////////////////////////////////////////////
  106. } // namespace NYT