YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/gutil/strings/strcat.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2008 and onwards Google Inc.  All rights reserved.
2
//
3
// The following only applies to changes made to this file as part of YugaByte development.
4
//
5
// Portions Copyright (c) YugaByte, Inc.
6
//
7
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8
// in compliance with the License.  You may obtain a copy of the License at
9
//
10
// http://www.apache.org/licenses/LICENSE-2.0
11
//
12
// Unless required by applicable law or agreed to in writing, software distributed under the License
13
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14
// or implied.  See the License for the specific language governing permissions and limitations
15
// under the License.
16
//
17
18
#include "yb/gutil/strings/strcat.h"
19
20
#include <stdarg.h>
21
#include <stdint.h>
22
#include <stdio.h>
23
#include <string.h>
24
25
#include <glog/logging.h>
26
#include "yb/gutil/stl_util.h"
27
28
AlphaNum gEmptyAlphaNum("");
29
30
// ----------------------------------------------------------------------
31
// StrCat()
32
//    This merges the given strings or integers, with no delimiter.  This
33
//    is designed to be the fastest possible way to construct a string out
34
//    of a mix of raw C strings, GStringPieces, strings, and integer values.
35
// ----------------------------------------------------------------------
36
37
// Append is merely a version of memcpy that returns the address of the byte
38
// after the area just overwritten.  It comes in multiple flavors to minimize
39
// call overhead.
40
89.5k
static char *Append1(char *out, const AlphaNum &x) {
41
89.5k
  memcpy(out, x.data(), x.size());
42
89.5k
  return out + x.size();
43
89.5k
}
44
45
240k
static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) {
46
240k
  memcpy(out, x1.data(), x1.size());
47
240k
  out += x1.size();
48
49
240k
  memcpy(out, x2.data(), x2.size());
50
240k
  return out + x2.size();
51
240k
}
52
53
static char *Append4(char *out,
54
                     const AlphaNum &x1, const AlphaNum &x2,
55
152k
                     const AlphaNum &x3, const AlphaNum &x4) {
56
152k
  memcpy(out, x1.data(), x1.size());
57
152k
  out += x1.size();
58
59
152k
  memcpy(out, x2.data(), x2.size());
60
152k
  out += x2.size();
61
62
152k
  memcpy(out, x3.data(), x3.size());
63
152k
  out += x3.size();
64
65
152k
  memcpy(out, x4.data(), x4.size());
66
152k
  return out + x4.size();
67
152k
}
68
69
0
string StrCat(const AlphaNum &a) {
70
0
  return string(a.data(), a.size());
71
0
}
72
73
0
string StrCat(const AlphaNum &a, const AlphaNum &b) {
74
0
  string result;
75
0
  STLStringResizeUninitialized(&result, a.size() + b.size());
76
0
  char *const begin = &*result.begin();
77
0
  char *out = Append2(begin, a, b);
78
0
  DCHECK_EQ(out, begin + result.size());
79
0
  return result;
80
0
}
81
82
89.1k
string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
83
89.1k
  string result;
84
89.1k
  STLStringResizeUninitialized(&result, a.size() + b.size() + c.size());
85
89.1k
  char *const begin = &*result.begin();
86
89.1k
  char *out = Append2(begin, a, b);
87
89.1k
  out = Append1(out, c);
88
89.1k
  DCHECK_EQ(out, begin + result.size());
89
89.1k
  return result;
90
89.1k
}
91
92
string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
93
2.47k
              const AlphaNum &d) {
94
2.47k
  string result;
95
2.47k
  STLStringResizeUninitialized(&result,
96
2.47k
                               a.size() + b.size() + c.size() + d.size());
97
2.47k
  char *const begin = &*result.begin();
98
2.47k
  char *out = Append4(begin, a, b, c, d);
99
2.47k
  DCHECK_EQ(out, begin + result.size());
100
2.47k
  return result;
101
2.47k
}
102
103
string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
104
0
              const AlphaNum &d, const AlphaNum &e) {
105
0
  string result;
106
0
  STLStringResizeUninitialized(&result,
107
0
      a.size() + b.size() + c.size() + d.size() + e.size());
108
0
  char *const begin = &*result.begin();
109
0
  char *out = Append4(begin, a, b, c, d);
110
0
  out = Append1(out, e);
111
0
  DCHECK_EQ(out, begin + result.size());
112
0
  return result;
113
0
}
114
115
string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
116
149k
              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) {
117
149k
  string result;
118
149k
  STLStringResizeUninitialized(&result,
119
149k
      a.size() + b.size() + c.size() + d.size() + e.size() + f.size());
120
149k
  char *const begin = &*result.begin();
121
149k
  char *out = Append4(begin, a, b, c, d);
122
149k
  out = Append2(out, e, f);
123
149k
  DCHECK_EQ(out, begin + result.size());
124
149k
  return result;
125
149k
}
126
127
string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
128
              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
129
0
              const AlphaNum &g) {
130
0
  string result;
131
0
  STLStringResizeUninitialized(&result,
132
0
      a.size() + b.size() + c.size() + d.size() + e.size()
133
0
               + f.size() + g.size());
134
0
  char *const begin = &*result.begin();
135
0
  char *out = Append4(begin, a, b, c, d);
136
0
  out = Append2(out, e, f);
137
0
  out = Append1(out, g);
138
0
  DCHECK_EQ(out, begin + result.size());
139
0
  return result;
140
0
}
141
142
string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
143
              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
144
0
              const AlphaNum &g, const AlphaNum &h) {
145
0
  string result;
146
0
  STLStringResizeUninitialized(&result,
147
0
      a.size() + b.size() + c.size() + d.size() + e.size()
148
0
               + f.size() + g.size() + h.size());
149
0
  char *const begin = &*result.begin();
150
0
  char *out = Append4(begin, a, b, c, d);
151
0
  out = Append4(out, e, f, g, h);
152
0
  DCHECK_EQ(out, begin + result.size());
153
0
  return result;
154
0
}
155
156
namespace strings {
157
namespace internal {
158
159
// StrCat with this many params is exceedingly rare, but it has been
160
// requested...  therefore we'll rely on default arguments to make calling
161
// slightly less efficient, to preserve code size.
162
0
string StrCatNineOrMore(const AlphaNum *a, ...) {
163
0
  string result;
164
165
0
  va_list args;
166
0
  va_start(args, a);
167
0
  size_t size = a->size();
168
0
  while (const AlphaNum *arg = va_arg(args, const AlphaNum *)) {
169
0
    size += arg->size();
170
0
  }
171
0
  STLStringResizeUninitialized(&result, size);
172
0
  va_end(args);
173
0
  va_start(args, a);
174
0
  char *const begin = &*result.begin();
175
0
  char *out = Append1(begin, *a);
176
0
  while (const AlphaNum *arg = va_arg(args, const AlphaNum *)) {
177
0
    out = Append1(out, *arg);
178
0
  }
179
0
  va_end(args);
180
0
  DCHECK_EQ(out, begin + size);
181
0
  return result;
182
0
}
183
184
}  // namespace internal
185
}  // namespace strings
186
187
// It's possible to call StrAppend with a GStringPiece that is itself a fragment
188
// of the string we're appending to.  However the results of this are random.
189
// Therefore, check for this in debug mode.  Use unsigned math so we only have
190
// to do one comparison.
191
#define DCHECK_NO_OVERLAP(dest, src) \
192
9.90k
    DCHECK_GT(uintptr_t((src).data() - (dest).data()), uintptr_t((dest).size()))
193
194
5.76k
void StrAppend(string *result, const AlphaNum &a) {
195
5.76k
  DCHECK_NO_OVERLAP(*result, a);
196
5.76k
  result->append(a.data(), a.size());
197
5.76k
}
198
199
1.59k
void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) {
200
1.59k
  DCHECK_NO_OVERLAP(*result, a);
201
1.59k
  DCHECK_NO_OVERLAP(*result, b);
202
1.59k
  string::size_type old_size = result->size();
203
1.59k
  STLStringResizeUninitialized(result, old_size + a.size() + b.size());
204
1.59k
  char *const begin = &*result->begin();
205
1.59k
  char *out = Append2(begin + old_size, a, b);
206
1.59k
  DCHECK_EQ(out, begin + result->size());
207
1.59k
}
208
209
void StrAppend(string *result,
210
318
               const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
211
318
  DCHECK_NO_OVERLAP(*result, a);
212
318
  DCHECK_NO_OVERLAP(*result, b);
213
318
  DCHECK_NO_OVERLAP(*result, c);
214
318
  string::size_type old_size = result->size();
215
318
  STLStringResizeUninitialized(result,
216
318
                               old_size + a.size() + b.size() + c.size());
217
318
  char *const begin = &*result->begin();
218
318
  char *out = Append2(begin + old_size, a, b);
219
318
  out = Append1(out, c);
220
318
  DCHECK_EQ(out, begin + result->size());
221
318
}
222
223
void StrAppend(string *result,
224
               const AlphaNum &a, const AlphaNum &b,
225
0
               const AlphaNum &c, const AlphaNum &d) {
226
0
  DCHECK_NO_OVERLAP(*result, a);
227
0
  DCHECK_NO_OVERLAP(*result, b);
228
0
  DCHECK_NO_OVERLAP(*result, c);
229
0
  DCHECK_NO_OVERLAP(*result, d);
230
0
  string::size_type old_size = result->size();
231
0
  STLStringResizeUninitialized(result,
232
0
      old_size + a.size() + b.size() + c.size() + d.size());
233
0
  char *const begin = &*result->begin();
234
0
  char *out = Append4(begin + old_size, a, b, c, d);
235
0
  DCHECK_EQ(out, begin + result->size());
236
0
}
237
238
// StrAppend with this many params is even rarer than with StrCat.
239
// Therefore we'll again rely on default arguments to make calling
240
// slightly less efficient, to preserve code size.
241
void StrAppend(string *result,
242
               const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
243
               const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
244
0
               const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) {
245
0
  DCHECK_NO_OVERLAP(*result, a);
246
0
  DCHECK_NO_OVERLAP(*result, b);
247
0
  DCHECK_NO_OVERLAP(*result, c);
248
0
  DCHECK_NO_OVERLAP(*result, d);
249
0
  DCHECK_NO_OVERLAP(*result, e);
250
0
  DCHECK_NO_OVERLAP(*result, f);
251
0
  DCHECK_NO_OVERLAP(*result, g);
252
0
  DCHECK_NO_OVERLAP(*result, h);
253
0
  DCHECK_NO_OVERLAP(*result, i);
254
0
  string::size_type old_size = result->size();
255
0
  STLStringResizeUninitialized(result,
256
0
      old_size + a.size() + b.size() + c.size() + d.size()
257
0
               + e.size() + f.size() + g.size() + h.size() + i.size());
258
0
  char *const begin = &*result->begin();
259
0
  char *out = Append4(begin + old_size, a, b, c, d);
260
0
  out = Append4(out, e, f, g, h);
261
0
  out = Append1(out, i);
262
0
  DCHECK_EQ(out, begin + result->size());
263
0
}