diff options
-rw-r--r-- | library/cpp/yt/string/format-inl.h | 104 | ||||
-rw-r--r-- | library/cpp/yt/string/format.h | 60 | ||||
-rw-r--r-- | library/cpp/yt/string/string_builder-inl.h | 121 | ||||
-rw-r--r-- | library/cpp/yt/string/string_builder.cpp | 30 | ||||
-rw-r--r-- | library/cpp/yt/string/string_builder.h | 80 | ||||
-rw-r--r-- | library/cpp/yt/string/ya.make | 1 |
6 files changed, 218 insertions, 178 deletions
diff --git a/library/cpp/yt/string/format-inl.h b/library/cpp/yt/string/format-inl.h index 188a699a3d..7f1f725966 100644 --- a/library/cpp/yt/string/format-inl.h +++ b/library/cpp/yt/string/format-inl.h @@ -38,110 +38,6 @@ namespace NYT { //////////////////////////////////////////////////////////////////////////////// -inline char* TStringBuilderBase::Preallocate(size_t size) -{ - Reserve(size + GetLength()); - return Current_; -} - -inline void TStringBuilderBase::Reserve(size_t size) -{ - if (Y_UNLIKELY(End_ - Begin_ < static_cast<ssize_t>(size))) { - size_t length = GetLength(); - auto newLength = std::max(size, MinBufferLength); - DoReserve(newLength); - Current_ = Begin_ + length; - } -} - -inline size_t TStringBuilderBase::GetLength() const -{ - return Current_ ? Current_ - Begin_ : 0; -} - -inline TStringBuf TStringBuilderBase::GetBuffer() const -{ - return TStringBuf(Begin_, Current_); -} - -inline void TStringBuilderBase::Advance(size_t size) -{ - Current_ += size; - YT_ASSERT(Current_ <= End_); -} - -inline void TStringBuilderBase::AppendChar(char ch) -{ - *Preallocate(1) = ch; - Advance(1); -} - -inline void TStringBuilderBase::AppendChar(char ch, int n) -{ - YT_ASSERT(n >= 0); - if (Y_LIKELY(0 != n)) { - char* dst = Preallocate(n); - ::memset(dst, ch, n); - Advance(n); - } -} - -inline void TStringBuilderBase::AppendString(TStringBuf str) -{ - if (Y_LIKELY(str)) { - char* dst = Preallocate(str.length()); - ::memcpy(dst, str.begin(), str.length()); - Advance(str.length()); - } -} - -inline void TStringBuilderBase::AppendString(const char* str) -{ - AppendString(TStringBuf(str)); -} - -inline void TStringBuilderBase::Reset() -{ - Begin_ = Current_ = End_ = nullptr; - DoReset(); -} - -template <class... TArgs> -void TStringBuilderBase::AppendFormat(TStringBuf format, TArgs&& ... args) -{ - Format(this, TRuntimeFormat{format}, std::forward<TArgs>(args)...); -} - -template <size_t Length, class... TArgs> -void TStringBuilderBase::AppendFormat(const char (&format)[Length], TArgs&& ... args) -{ - Format(this, TRuntimeFormat{format}, std::forward<TArgs>(args)...); -} - -//////////////////////////////////////////////////////////////////////////////// - -inline TString TStringBuilder::Flush() -{ - Buffer_.resize(GetLength()); - auto result = std::move(Buffer_); - Reset(); - return result; -} - -inline void TStringBuilder::DoReset() -{ - Buffer_ = {}; -} - -inline void TStringBuilder::DoReserve(size_t newLength) -{ - Buffer_.ReserveAndResize(newLength); - auto capacity = Buffer_.capacity(); - Buffer_.ReserveAndResize(capacity); - Begin_ = &*Buffer_.begin(); - End_ = Begin_ + capacity; -} - inline void FormatValue(TStringBuilderBase* builder, const TStringBuilder& value, TStringBuf /*spec*/) { builder->AppendString(value.GetBuffer()); diff --git a/library/cpp/yt/string/format.h b/library/cpp/yt/string/format.h index a6ab1f76f4..5e5a76db9d 100644 --- a/library/cpp/yt/string/format.h +++ b/library/cpp/yt/string/format.h @@ -1,6 +1,7 @@ #pragma once #include "format_string.h" +#include "string_builder.h" #include <util/generic/string.h> @@ -61,65 +62,6 @@ TString Format(TFormatString<TArgs...> format, TArgs&&... args); //////////////////////////////////////////////////////////////////////////////// -// StringBuilder(Base) definition. - -//! A simple helper for constructing strings by a sequence of appends. -class TStringBuilderBase -{ -public: - virtual ~TStringBuilderBase() = default; - - char* Preallocate(size_t size); - - void Reserve(size_t size); - - size_t GetLength() const; - - TStringBuf GetBuffer() const; - - void Advance(size_t size); - - void AppendChar(char ch); - void AppendChar(char ch, int n); - - void AppendString(TStringBuf str); - void AppendString(const char* str); - - template <size_t Length, class... TArgs> - void AppendFormat(const char (&format)[Length], TArgs&&... args); - template <class... TArgs> - void AppendFormat(TStringBuf format, TArgs&&... args); - - void Reset(); - -protected: - char* Begin_ = nullptr; - char* Current_ = nullptr; - char* End_ = nullptr; - - virtual void DoReset() = 0; - virtual void DoReserve(size_t newLength) = 0; - - static constexpr size_t MinBufferLength = 128; -}; - -//////////////////////////////////////////////////////////////////////////////// - -class TStringBuilder - : public TStringBuilderBase -{ -public: - TString Flush(); - -protected: - TString Buffer_; - - void DoReset() override; - void DoReserve(size_t size) override; -}; - -//////////////////////////////////////////////////////////////////////////////// - template <class... TArgs> void Format(TStringBuilderBase* builder, TFormatString<TArgs...> format, TArgs&&... args); diff --git a/library/cpp/yt/string/string_builder-inl.h b/library/cpp/yt/string/string_builder-inl.h new file mode 100644 index 0000000000..7027f9acc1 --- /dev/null +++ b/library/cpp/yt/string/string_builder-inl.h @@ -0,0 +1,121 @@ +#ifndef STRING_BUILDER_INL_H_ +#error "Direct inclusion of this file is not allowed, include string_builder.h" +// For the sake of sane code completion. +#include "string_builder.h" +#endif + +#include "format_string.h" + +#include <library/cpp/yt/assert/assert.h> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +inline char* TStringBuilderBase::Preallocate(size_t size) +{ + Reserve(size + GetLength()); + return Current_; +} + +inline void TStringBuilderBase::Reserve(size_t size) +{ + if (Y_UNLIKELY(End_ - Begin_ < static_cast<ssize_t>(size))) { + size_t length = GetLength(); + auto newLength = std::max(size, MinBufferLength); + DoReserve(newLength); + Current_ = Begin_ + length; + } +} + +inline size_t TStringBuilderBase::GetLength() const +{ + return Current_ ? Current_ - Begin_ : 0; +} + +inline TStringBuf TStringBuilderBase::GetBuffer() const +{ + return TStringBuf(Begin_, Current_); +} + +inline void TStringBuilderBase::Advance(size_t size) +{ + Current_ += size; + YT_ASSERT(Current_ <= End_); +} + +inline void TStringBuilderBase::AppendChar(char ch) +{ + *Preallocate(1) = ch; + Advance(1); +} + +inline void TStringBuilderBase::AppendChar(char ch, int n) +{ + YT_ASSERT(n >= 0); + if (Y_LIKELY(0 != n)) { + char* dst = Preallocate(n); + ::memset(dst, ch, n); + Advance(n); + } +} + +inline void TStringBuilderBase::AppendString(TStringBuf str) +{ + if (Y_LIKELY(str)) { + char* dst = Preallocate(str.length()); + ::memcpy(dst, str.begin(), str.length()); + Advance(str.length()); + } +} + +inline void TStringBuilderBase::AppendString(const char* str) +{ + AppendString(TStringBuf(str)); +} + +inline void TStringBuilderBase::Reset() +{ + Begin_ = Current_ = End_ = nullptr; + DoReset(); +} + +template <class... TArgs> +void TStringBuilderBase::AppendFormat(TStringBuf format, TArgs&& ... args) +{ + Format(this, TRuntimeFormat{format}, std::forward<TArgs>(args)...); +} + +template <size_t Length, class... TArgs> +void TStringBuilderBase::AppendFormat(const char (&format)[Length], TArgs&& ... args) +{ + Format(this, TRuntimeFormat{format}, std::forward<TArgs>(args)...); +} + +//////////////////////////////////////////////////////////////////////////////// + +inline TString TStringBuilder::Flush() +{ + Buffer_.resize(GetLength()); + auto result = std::move(Buffer_); + Reset(); + return result; +} + +inline void TStringBuilder::DoReset() +{ + Buffer_ = {}; +} + +inline void TStringBuilder::DoReserve(size_t newLength) +{ + Buffer_.ReserveAndResize(newLength); + auto capacity = Buffer_.capacity(); + Buffer_.ReserveAndResize(capacity); + Begin_ = &*Buffer_.begin(); + End_ = Begin_ + capacity; +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT diff --git a/library/cpp/yt/string/string_builder.cpp b/library/cpp/yt/string/string_builder.cpp new file mode 100644 index 0000000000..bca493fa32 --- /dev/null +++ b/library/cpp/yt/string/string_builder.cpp @@ -0,0 +1,30 @@ +#include "string_builder.h" + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +TDelimitedStringBuilderWrapper::TDelimitedStringBuilderWrapper( + TStringBuilderBase* builder, + TStringBuf delimiter) + : Builder_(builder) + , Delimiter_(delimiter) +{ } + +TStringBuilderBase* TDelimitedStringBuilderWrapper::operator->() +{ + return operator&(); +} + +TStringBuilderBase* TDelimitedStringBuilderWrapper::operator&() +{ + if (!FirstCall_) { + Builder_->AppendString(Delimiter_); + } + FirstCall_ = false; + return Builder_; +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT diff --git a/library/cpp/yt/string/string_builder.h b/library/cpp/yt/string/string_builder.h index de1c1abb1e..ac3aa26a7c 100644 --- a/library/cpp/yt/string/string_builder.h +++ b/library/cpp/yt/string/string_builder.h @@ -1,13 +1,68 @@ #pragma once -#include "format.h" - #include <util/generic/string.h> namespace NYT { //////////////////////////////////////////////////////////////////////////////// +//! A simple helper for constructing strings by a sequence of appends. +class TStringBuilderBase +{ +public: + virtual ~TStringBuilderBase() = default; + + char* Preallocate(size_t size); + + void Reserve(size_t size); + + size_t GetLength() const; + + TStringBuf GetBuffer() const; + + void Advance(size_t size); + + void AppendChar(char ch); + void AppendChar(char ch, int n); + + void AppendString(TStringBuf str); + void AppendString(const char* str); + + template <size_t Length, class... TArgs> + void AppendFormat(const char (&format)[Length], TArgs&&... args); + template <class... TArgs> + void AppendFormat(TStringBuf format, TArgs&&... args); + + void Reset(); + +protected: + char* Begin_ = nullptr; + char* Current_ = nullptr; + char* End_ = nullptr; + + virtual void DoReset() = 0; + virtual void DoReserve(size_t newLength) = 0; + + static constexpr size_t MinBufferLength = 128; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TStringBuilder + : public TStringBuilderBase +{ +public: + TString Flush(); + +protected: + TString Buffer_; + + void DoReset() override; + void DoReserve(size_t size) override; +}; + +//////////////////////////////////////////////////////////////////////////////// + //! Appends a certain delimiter starting from the second call. class TDelimitedStringBuilderWrapper : private TNonCopyable @@ -15,19 +70,10 @@ class TDelimitedStringBuilderWrapper public: TDelimitedStringBuilderWrapper( TStringBuilderBase* builder, - TStringBuf delimiter = TStringBuf(", ")) - : Builder_(builder) - , Delimiter_(delimiter) - { } - - TStringBuilderBase* operator->() - { - if (!FirstCall_) { - Builder_->AppendString(Delimiter_); - } - FirstCall_ = false; - return Builder_; - } + TStringBuf delimiter = TStringBuf(", ")); + + TStringBuilderBase* operator->(); + TStringBuilderBase* operator&(); private: TStringBuilderBase* const Builder_; @@ -39,3 +85,7 @@ private: //////////////////////////////////////////////////////////////////////////////// } // namespace NYT + +#define STRING_BUILDER_INL_H_ +#include "string_builder-inl.h" +#undef STRING_BUILDER_INL_H_ diff --git a/library/cpp/yt/string/ya.make b/library/cpp/yt/string/ya.make index db3a477b35..2071e0a115 100644 --- a/library/cpp/yt/string/ya.make +++ b/library/cpp/yt/string/ya.make @@ -8,6 +8,7 @@ SRCS( string.cpp format_string.cpp format.cpp + string_builder.cpp ) PEERDIR( |