1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#ifndef STRING_BUILDER_INL_H_
#error "Direct inclusion of this file is not allowed, include string.h"
// For the sake of sane code completion.
#include "string_builder.h"
#endif
#include <library/cpp/yt/assert/assert.h>
namespace NYT {
////////////////////////////////////////////////////////////////////////////////
inline char* TStringBuilderBase::Preallocate(size_t size)
{
if (Y_UNLIKELY(End_ - Current_ < static_cast<ssize_t>(size))) {
size_t length = GetLength();
auto newLength = std::max(length + size, MinBufferLength);
DoPreallocate(newLength);
Current_ = Begin_ + length;
}
return Current_;
}
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, format, std::forward<TArgs>(args)...);
}
template <size_t Length, class... TArgs>
void TStringBuilderBase::AppendFormat(const char (&format)[Length], TArgs&& ... args)
{
Format(this, 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::DoPreallocate(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 /*format*/)
{
builder->AppendString(value.GetBuffer());
}
template <class T>
TString ToStringViaBuilder(const T& value, TStringBuf spec)
{
TStringBuilder builder;
FormatValue(&builder, value, spec);
return builder.Flush();
}
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT
|