Coverage Report

Created: 2024-11-20 21:49

/root/doris/be/src/gutil/strings/strcat.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2008 and onwards Google Inc.  All rights reserved.
2
3
#include "gutil/strings/strcat.h"
4
5
#include "common/logging.h"
6
#include <stdarg.h>
7
#include <stdint.h>
8
#include <string.h>
9
10
#include "gutil/stl_util.h"
11
#include "gutil/strings/escaping.h"
12
13
AlphaNum gEmptyAlphaNum("");
14
15
// ----------------------------------------------------------------------
16
// StrCat()
17
//    This merges the given strings or integers, with no delimiter.  This
18
//    is designed to be the fastest possible way to construct a string out
19
//    of a mix of raw C strings, StringPieces, strings, and integer values.
20
// ----------------------------------------------------------------------
21
22
// Append is merely a version of memcpy that returns the address of the byte
23
// after the area just overwritten.  It comes in multiple flavors to minimize
24
// call overhead.
25
0
static char* Append1(char* out, const AlphaNum& x) {
26
0
    memcpy(out, x.data(), x.size());
27
0
    return out + x.size();
28
0
}
29
30
91
static char* Append2(char* out, const AlphaNum& x1, const AlphaNum& x2) {
31
91
    memcpy(out, x1.data(), x1.size());
32
91
    out += x1.size();
33
34
91
    memcpy(out, x2.data(), x2.size());
35
91
    return out + x2.size();
36
91
}
37
38
static char* Append4(char* out, const AlphaNum& x1, const AlphaNum& x2, const AlphaNum& x3,
39
0
                     const AlphaNum& x4) {
40
0
    memcpy(out, x1.data(), x1.size());
41
0
    out += x1.size();
42
43
0
    memcpy(out, x2.data(), x2.size());
44
0
    out += x2.size();
45
46
0
    memcpy(out, x3.data(), x3.size());
47
0
    out += x3.size();
48
49
0
    memcpy(out, x4.data(), x4.size());
50
0
    return out + x4.size();
51
0
}
52
53
0
string StrCat(const AlphaNum& a) {
54
0
    return string(a.data(), a.size());
55
0
}
56
57
91
string StrCat(const AlphaNum& a, const AlphaNum& b) {
58
91
    string result;
59
91
    STLStringResizeUninitialized(&result, a.size() + b.size());
60
91
    char* const begin = &*result.begin();
61
91
    char* out = Append2(begin, a, b);
62
91
    DCHECK_EQ(out, begin + result.size());
63
91
    return result;
64
91
}
65
66
0
string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {
67
0
    string result;
68
0
    STLStringResizeUninitialized(&result, a.size() + b.size() + c.size());
69
0
    char* const begin = &*result.begin();
70
0
    char* out = Append2(begin, a, b);
71
0
    out = Append1(out, c);
72
0
    DCHECK_EQ(out, begin + result.size());
73
0
    return result;
74
0
}
75
76
0
string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d) {
77
0
    string result;
78
0
    STLStringResizeUninitialized(&result, a.size() + b.size() + c.size() + d.size());
79
0
    char* const begin = &*result.begin();
80
0
    char* out = Append4(begin, a, b, c, d);
81
0
    DCHECK_EQ(out, begin + result.size());
82
0
    return result;
83
0
}
84
85
string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
86
0
              const AlphaNum& e) {
87
0
    string result;
88
0
    STLStringResizeUninitialized(&result, a.size() + b.size() + c.size() + d.size() + e.size());
89
0
    char* const begin = &*result.begin();
90
0
    char* out = Append4(begin, a, b, c, d);
91
0
    out = Append1(out, e);
92
0
    DCHECK_EQ(out, begin + result.size());
93
0
    return result;
94
0
}
95
96
string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
97
0
              const AlphaNum& e, const AlphaNum& f) {
98
0
    string result;
99
0
    STLStringResizeUninitialized(&result,
100
0
                                 a.size() + b.size() + c.size() + d.size() + e.size() + f.size());
101
0
    char* const begin = &*result.begin();
102
0
    char* out = Append4(begin, a, b, c, d);
103
0
    out = Append2(out, e, f);
104
0
    DCHECK_EQ(out, begin + result.size());
105
0
    return result;
106
0
}
107
108
string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
109
0
              const AlphaNum& e, const AlphaNum& f, const AlphaNum& g) {
110
0
    string result;
111
0
    STLStringResizeUninitialized(
112
0
            &result, a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + g.size());
113
0
    char* const begin = &*result.begin();
114
0
    char* out = Append4(begin, a, b, c, d);
115
0
    out = Append2(out, e, f);
116
0
    out = Append1(out, g);
117
0
    DCHECK_EQ(out, begin + result.size());
118
0
    return result;
119
0
}
120
121
string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
122
0
              const AlphaNum& e, const AlphaNum& f, const AlphaNum& g, const AlphaNum& h) {
123
0
    string result;
124
0
    STLStringResizeUninitialized(&result, a.size() + b.size() + c.size() + d.size() + e.size() +
125
0
                                                  f.size() + g.size() + h.size());
126
0
    char* const begin = &*result.begin();
127
0
    char* out = Append4(begin, a, b, c, d);
128
0
    out = Append4(out, e, f, g, h);
129
0
    DCHECK_EQ(out, begin + result.size());
130
0
    return result;
131
0
}
132
133
namespace strings {
134
namespace internal {
135
136
// StrCat with this many params is exceedingly rare, but it has been
137
// requested...  therefore we'll rely on default arguments to make calling
138
// slightly less efficient, to preserve code size.
139
0
string StrCatNineOrMore(const AlphaNum* a, ...) {
140
0
    string result;
141
142
0
    va_list args;
143
0
    va_start(args, a);
144
0
    size_t size = a->size();
145
0
    while (const AlphaNum* arg = va_arg(args, const AlphaNum*)) {
146
0
        size += arg->size();
147
0
    }
148
0
    STLStringResizeUninitialized(&result, size);
149
0
    va_end(args);
150
0
    va_start(args, a);
151
0
    char* const begin = &*result.begin();
152
0
    char* out = Append1(begin, *a);
153
0
    while (const AlphaNum* arg = va_arg(args, const AlphaNum*)) {
154
0
        out = Append1(out, *arg);
155
0
    }
156
0
    va_end(args);
157
0
    DCHECK_EQ(out, begin + size);
158
0
    return result;
159
0
}
160
161
} // namespace internal
162
} // namespace strings
163
164
// It's possible to call StrAppend with a StringPiece that is itself a fragment
165
// of the string we're appending to.  However the results of this are random.
166
// Therefore, check for this in debug mode.  Use unsigned math so we only have
167
// to do one comparison.
168
#define DCHECK_NO_OVERLAP(dest, src) \
169
0
    DCHECK_GT(uintptr_t((src).data() - (dest).data()), uintptr_t((dest).size()))
170
171
0
void StrAppend(string* result, const AlphaNum& a) {
172
0
    DCHECK_NO_OVERLAP(*result, a);
173
0
    result->append(a.data(), a.size());
174
0
}
175
176
0
void StrAppend(string* result, const AlphaNum& a, const AlphaNum& b) {
177
0
    DCHECK_NO_OVERLAP(*result, a);
178
0
    DCHECK_NO_OVERLAP(*result, b);
179
0
    string::size_type old_size = result->size();
180
0
    STLStringResizeUninitialized(result, old_size + a.size() + b.size());
181
0
    char* const begin = &*result->begin();
182
0
    char* out = Append2(begin + old_size, a, b);
183
0
    DCHECK_EQ(out, begin + result->size());
184
0
}
185
186
0
void StrAppend(string* result, const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {
187
0
    DCHECK_NO_OVERLAP(*result, a);
188
0
    DCHECK_NO_OVERLAP(*result, b);
189
0
    DCHECK_NO_OVERLAP(*result, c);
190
0
    string::size_type old_size = result->size();
191
0
    STLStringResizeUninitialized(result, old_size + a.size() + b.size() + c.size());
192
0
    char* const begin = &*result->begin();
193
0
    char* out = Append2(begin + old_size, a, b);
194
0
    out = Append1(out, c);
195
0
    DCHECK_EQ(out, begin + result->size());
196
0
}
197
198
void StrAppend(string* result, const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
199
0
               const AlphaNum& d) {
200
0
    DCHECK_NO_OVERLAP(*result, a);
201
0
    DCHECK_NO_OVERLAP(*result, b);
202
0
    DCHECK_NO_OVERLAP(*result, c);
203
0
    DCHECK_NO_OVERLAP(*result, d);
204
0
    string::size_type old_size = result->size();
205
0
    STLStringResizeUninitialized(result, old_size + a.size() + b.size() + c.size() + d.size());
206
0
    char* const begin = &*result->begin();
207
0
    char* out = Append4(begin + old_size, a, b, c, d);
208
0
    DCHECK_EQ(out, begin + result->size());
209
0
}
210
211
// StrAppend with this many params is even rarer than with StrCat.
212
// Therefore we'll again rely on default arguments to make calling
213
// slightly less efficient, to preserve code size.
214
void StrAppend(string* result, const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
215
               const AlphaNum& d, const AlphaNum& e, const AlphaNum& f, const AlphaNum& g,
216
0
               const AlphaNum& h, const AlphaNum& i) {
217
0
    DCHECK_NO_OVERLAP(*result, a);
218
0
    DCHECK_NO_OVERLAP(*result, b);
219
0
    DCHECK_NO_OVERLAP(*result, c);
220
0
    DCHECK_NO_OVERLAP(*result, d);
221
0
    DCHECK_NO_OVERLAP(*result, e);
222
0
    DCHECK_NO_OVERLAP(*result, f);
223
0
    DCHECK_NO_OVERLAP(*result, g);
224
0
    DCHECK_NO_OVERLAP(*result, h);
225
0
    DCHECK_NO_OVERLAP(*result, i);
226
0
    string::size_type old_size = result->size();
227
0
    STLStringResizeUninitialized(result, old_size + a.size() + b.size() + c.size() + d.size() +
228
0
                                                 e.size() + f.size() + g.size() + h.size() +
229
0
                                                 i.size());
230
0
    char* const begin = &*result->begin();
231
0
    char* out = Append4(begin + old_size, a, b, c, d);
232
0
    out = Append4(out, e, f, g, h);
233
0
    out = Append1(out, i);
234
0
    DCHECK_EQ(out, begin + result->size());
235
0
}