substitute.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 
16 
17 #include <algorithm>
18 
20 #include "absl/strings/ascii.h"
21 #include "absl/strings/escaping.h"
24 
25 namespace absl {
26 namespace substitute_internal {
27 
29  const absl::string_view* args_array,
30  size_t num_args) {
31  // Determine total size needed.
32  size_t size = 0;
33  for (size_t i = 0; i < format.size(); i++) {
34  if (format[i] == '$') {
35  if (i + 1 >= format.size()) {
36 #ifndef NDEBUG
37  ABSL_RAW_LOG(FATAL,
38  "Invalid strings::Substitute() format std::string: \"%s\".",
39  absl::CEscape(format).c_str());
40 #endif
41  return;
42  } else if (absl::ascii_isdigit(format[i + 1])) {
43  int index = format[i + 1] - '0';
44  if (static_cast<size_t>(index) >= num_args) {
45 #ifndef NDEBUG
47  FATAL,
48  "Invalid strings::Substitute() format std::string: asked for \"$"
49  "%d\", but only %d args were given. Full format std::string was: "
50  "\"%s\".",
51  index, static_cast<int>(num_args), absl::CEscape(format).c_str());
52 #endif
53  return;
54  }
55  size += args_array[index].size();
56  ++i; // Skip next char.
57  } else if (format[i + 1] == '$') {
58  ++size;
59  ++i; // Skip next char.
60  } else {
61 #ifndef NDEBUG
62  ABSL_RAW_LOG(FATAL,
63  "Invalid strings::Substitute() format std::string: \"%s\".",
64  absl::CEscape(format).c_str());
65 #endif
66  return;
67  }
68  } else {
69  ++size;
70  }
71  }
72 
73  if (size == 0) return;
74 
75  // Build the std::string.
76  size_t original_size = output->size();
77  strings_internal::STLStringResizeUninitialized(output, original_size + size);
78  char* target = &(*output)[original_size];
79  for (size_t i = 0; i < format.size(); i++) {
80  if (format[i] == '$') {
81  if (absl::ascii_isdigit(format[i + 1])) {
82  const absl::string_view src = args_array[format[i + 1] - '0'];
83  target = std::copy(src.begin(), src.end(), target);
84  ++i; // Skip next char.
85  } else if (format[i + 1] == '$') {
86  *target++ = '$';
87  ++i; // Skip next char.
88  }
89  } else {
90  *target++ = format[i];
91  }
92  }
93 
94  assert(target == output->data() + output->size());
95 }
96 
97 static const char kHexDigits[] = "0123456789abcdef";
98 Arg::Arg(const void* value) {
99  static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,
100  "fix sizeof(scratch_)");
101  if (value == nullptr) {
102  piece_ = "NULL";
103  } else {
104  char* ptr = scratch_ + sizeof(scratch_);
105  uintptr_t num = reinterpret_cast<uintptr_t>(value);
106  do {
107  *--ptr = kHexDigits[num & 0xf];
108  num >>= 4;
109  } while (num != 0);
110  *--ptr = 'x';
111  *--ptr = '0';
112  piece_ = absl::string_view(ptr, scratch_ + sizeof(scratch_) - ptr);
113  }
114 }
115 
116 // TODO(jorg): Don't duplicate so much code between here and str_cat.cc
117 Arg::Arg(Hex hex) {
119  char* writer = end;
120  uint64_t value = hex.value;
121  do {
122  *--writer = kHexDigits[value & 0xF];
123  value >>= 4;
124  } while (value != 0);
125 
126  char* beg;
127  if (end - writer < hex.width) {
128  beg = end - hex.width;
129  std::fill_n(beg, writer - beg, hex.fill);
130  } else {
131  beg = writer;
132  }
133 
134  piece_ = absl::string_view(beg, end - beg);
135 }
136 
137 // TODO(jorg): Don't duplicate so much code between here and str_cat.cc
138 Arg::Arg(Dec dec) {
141  char* const minfill = end - dec.width;
142  char* writer = end;
143  uint64_t value = dec.value;
144  bool neg = dec.neg;
145  while (value > 9) {
146  *--writer = '0' + (value % 10);
147  value /= 10;
148  }
149  *--writer = '0' + value;
150  if (neg) *--writer = '-';
151 
152  ptrdiff_t fillers = writer - minfill;
153  if (fillers > 0) {
154  // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
155  // But...: if the fill character is '0', then it's <+/-><fill><digits>
156  bool add_sign_again = false;
157  if (neg && dec.fill == '0') { // If filling with '0',
158  ++writer; // ignore the sign we just added
159  add_sign_again = true; // and re-add the sign later.
160  }
161  writer -= fillers;
162  std::fill_n(writer, fillers, dec.fill);
163  if (add_sign_again) *--writer = '-';
164  }
165 
166  piece_ = absl::string_view(writer, end - writer);
167 }
168 
169 } // namespace substitute_internal
170 } // namespace absl
bool neg
Definition: str_cat.h:186
uint8_t width
Definition: str_cat.h:134
char fill
Definition: str_cat.h:135
std::string CEscape(absl::string_view src)
Definition: escaping.cc:1039
#define ABSL_RAW_LOG(severity,...)
Definition: raw_logging.h:42
uint64_t value
Definition: str_cat.h:133
Arg(const char *value)
Definition: substitute.h:101
uint8_t width
Definition: str_cat.h:184
absl::string_view piece_
Definition: substitute.h:177
char * end
Definition: algorithm.h:29
uint64_t value
Definition: str_cat.h:183
constexpr size_type size() const noexcept
Definition: string_view.h:260
char scratch_[numbers_internal::kFastToBufferSize]
Definition: substitute.h:178
char * ptr
size_t value
void STLStringResizeUninitialized(string_type *s, size_t new_size)
std::string format(const std::string &, const time_point< seconds > &, const femtoseconds &, const time_zone &)
constexpr const_iterator begin() const noexcept
Definition: string_view.h:203
static const char kHexDigits[]
Definition: substitute.cc:97
uintptr_t size
bool ascii_isdigit(unsigned char c)
Definition: ascii.h:130
static const int kFastToBufferSize
Definition: numbers.h:93
char fill
Definition: str_cat.h:185
void SubstituteAndAppendArray(std::string *output, absl::string_view format, const absl::string_view *args_array, size_t num_args)
Definition: substitute.cc:28
constexpr const_iterator end() const noexcept
Definition: string_view.h:210


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:20