aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/string/string_builder-inl.h
blob: b2074525685f3f512f9c5ff2f48d341fb9f838c4 (plain) (blame)
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