str_cat.cc
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/strings/str_cat.h"
16 
17 #include <assert.h>
18 #include <algorithm>
19 #include <cstdint>
20 #include <cstring>
21 
22 #include "absl/strings/ascii.h"
24 
25 namespace absl {
26 
29  char* writer = end;
30  uint64_t value = hex.value;
31  static const char hexdigits[] = "0123456789abcdef";
32  do {
33  *--writer = hexdigits[value & 0xF];
34  value >>= 4;
35  } while (value != 0);
36 
37  char* beg;
38  if (end - writer < hex.width) {
39  beg = end - hex.width;
40  std::fill_n(beg, writer - beg, hex.fill);
41  } else {
42  beg = writer;
43  }
44 
45  piece_ = absl::string_view(beg, end - beg);
46 }
47 
51  char* const minfill = end - dec.width;
52  char* writer = end;
53  uint64_t value = dec.value;
54  bool neg = dec.neg;
55  while (value > 9) {
56  *--writer = '0' + (value % 10);
57  value /= 10;
58  }
59  *--writer = '0' + value;
60  if (neg) *--writer = '-';
61 
62  ptrdiff_t fillers = writer - minfill;
63  if (fillers > 0) {
64  // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
65  // But...: if the fill character is '0', then it's <+/-><fill><digits>
66  bool add_sign_again = false;
67  if (neg && dec.fill == '0') { // If filling with '0',
68  ++writer; // ignore the sign we just added
69  add_sign_again = true; // and re-add the sign later.
70  }
71  writer -= fillers;
72  std::fill_n(writer, fillers, dec.fill);
73  if (add_sign_again) *--writer = '-';
74  }
75 
76  piece_ = absl::string_view(writer, end - writer);
77 }
78 
79 // ----------------------------------------------------------------------
80 // StrCat()
81 // This merges the given strings or integers, with no delimiter. This
82 // is designed to be the fastest possible way to construct a string out
83 // of a mix of raw C strings, string_views, strings, and integer values.
84 // ----------------------------------------------------------------------
85 
86 // Append is merely a version of memcpy that returns the address of the byte
87 // after the area just overwritten.
88 static char* Append(char* out, const AlphaNum& x) {
89  // memcpy is allowed to overwrite arbitrary memory, so doing this after the
90  // call would force an extra fetch of x.size().
91  char* after = out + x.size();
92  if (x.size() != 0) {
93  memcpy(out, x.data(), x.size());
94  }
95  return after;
96 }
97 
98 std::string StrCat(const AlphaNum& a, const AlphaNum& b) {
99  std::string result;
101  a.size() + b.size());
102  char* const begin = &*result.begin();
103  char* out = begin;
104  out = Append(out, a);
105  out = Append(out, b);
106  assert(out == begin + result.size());
107  return result;
108 }
109 
110 std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {
111  std::string result;
113  &result, a.size() + b.size() + c.size());
114  char* const begin = &*result.begin();
115  char* out = begin;
116  out = Append(out, a);
117  out = Append(out, b);
118  out = Append(out, c);
119  assert(out == begin + result.size());
120  return result;
121 }
122 
123 std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
124  const AlphaNum& d) {
125  std::string result;
127  &result, a.size() + b.size() + c.size() + d.size());
128  char* const begin = &*result.begin();
129  char* out = begin;
130  out = Append(out, a);
131  out = Append(out, b);
132  out = Append(out, c);
133  out = Append(out, d);
134  assert(out == begin + result.size());
135  return result;
136 }
137 
138 namespace strings_internal {
139 
140 // Do not call directly - these are not part of the public API.
141 std::string CatPieces(std::initializer_list<absl::string_view> pieces) {
142  std::string result;
143  size_t total_size = 0;
144  for (const absl::string_view piece : pieces) total_size += piece.size();
146 
147  char* const begin = &*result.begin();
148  char* out = begin;
149  for (const absl::string_view piece : pieces) {
150  const size_t this_size = piece.size();
151  if (this_size != 0) {
152  memcpy(out, piece.data(), this_size);
153  out += this_size;
154  }
155  }
156  assert(out == begin + result.size());
157  return result;
158 }
159 
160 // It's possible to call StrAppend with an absl::string_view that is itself a
161 // fragment of the string we're appending to. However the results of this are
162 // random. Therefore, check for this in debug mode. Use unsigned math so we
163 // only have to do one comparison. Note, there's an exception case: appending an
164 // empty string is always allowed.
165 #define ASSERT_NO_OVERLAP(dest, src) \
166  assert(((src).size() == 0) || \
167  (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size())))
168 
169 void AppendPieces(std::string* dest,
170  std::initializer_list<absl::string_view> pieces) {
171  size_t old_size = dest->size();
172  size_t total_size = old_size;
173  for (const absl::string_view piece : pieces) {
174  ASSERT_NO_OVERLAP(*dest, piece);
175  total_size += piece.size();
176  }
178 
179  char* const begin = &*dest->begin();
180  char* out = begin + old_size;
181  for (const absl::string_view piece : pieces) {
182  const size_t this_size = piece.size();
183  if (this_size != 0) {
184  memcpy(out, piece.data(), this_size);
185  out += this_size;
186  }
187  }
188  assert(out == begin + dest->size());
189 }
190 
191 } // namespace strings_internal
192 
193 void StrAppend(std::string* dest, const AlphaNum& a) {
194  ASSERT_NO_OVERLAP(*dest, a);
195  dest->append(a.data(), a.size());
196 }
197 
198 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) {
199  ASSERT_NO_OVERLAP(*dest, a);
200  ASSERT_NO_OVERLAP(*dest, b);
201  std::string::size_type old_size = dest->size();
203  dest, old_size + a.size() + b.size());
204  char* const begin = &*dest->begin();
205  char* out = begin + old_size;
206  out = Append(out, a);
207  out = Append(out, b);
208  assert(out == begin + dest->size());
209 }
210 
211 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
212  const AlphaNum& c) {
213  ASSERT_NO_OVERLAP(*dest, a);
214  ASSERT_NO_OVERLAP(*dest, b);
215  ASSERT_NO_OVERLAP(*dest, c);
216  std::string::size_type old_size = dest->size();
218  dest, old_size + a.size() + b.size() + c.size());
219  char* const begin = &*dest->begin();
220  char* out = begin + old_size;
221  out = Append(out, a);
222  out = Append(out, b);
223  out = Append(out, c);
224  assert(out == begin + dest->size());
225 }
226 
227 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
228  const AlphaNum& c, const AlphaNum& d) {
229  ASSERT_NO_OVERLAP(*dest, a);
230  ASSERT_NO_OVERLAP(*dest, b);
231  ASSERT_NO_OVERLAP(*dest, c);
232  ASSERT_NO_OVERLAP(*dest, d);
233  std::string::size_type old_size = dest->size();
235  dest, old_size + a.size() + b.size() + c.size() + d.size());
236  char* const begin = &*dest->begin();
237  char* out = begin + old_size;
238  out = Append(out, a);
239  out = Append(out, b);
240  out = Append(out, c);
241  out = Append(out, d);
242  assert(out == begin + dest->size());
243 }
244 
245 } // namespace absl
bool neg
Definition: str_cat.h:186
uint8_t width
Definition: str_cat.h:134
void StrAppend(std::string *dest, const AlphaNum &a)
Definition: str_cat.cc:193
char * begin
char fill
Definition: str_cat.h:135
uint64_t value
Definition: str_cat.h:133
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: str_cat.cc:98
uint8_t width
Definition: str_cat.h:184
AlphaNum(int x)
Definition: str_cat.h:214
std::string CatPieces(std::initializer_list< absl::string_view > pieces)
Definition: str_cat.cc:141
char * end
Definition: algorithm.h:29
uint64_t value
Definition: str_cat.h:183
size_t value
void STLStringResizeUninitialized(string_type *s, size_t new_size)
#define ASSERT_NO_OVERLAP(dest, src)
Definition: str_cat.cc:165
const char * data() const
Definition: str_cat.h:261
absl::string_view piece_
Definition: str_cat.h:284
char digits_[numbers_internal::kFastToBufferSize]
Definition: str_cat.h:285
static char * Append(char *out, const AlphaNum &x)
Definition: str_cat.cc:88
absl::string_view::size_type size() const
Definition: str_cat.h:260
static const int kFastToBufferSize
Definition: numbers.h:93
uint64_t b
Definition: layout_test.cc:50
char fill
Definition: str_cat.h:185
char * out
Definition: mutex.h:1013
void AppendPieces(std::string *dest, std::initializer_list< absl::string_view > pieces)
Definition: str_cat.cc:169


abseil_cpp
Author(s):
autogenerated on Tue Jun 18 2019 19:44:37