Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/strings/substitute.h"
00016
00017 #include <algorithm>
00018
00019 #include "absl/base/internal/raw_logging.h"
00020 #include "absl/strings/ascii.h"
00021 #include "absl/strings/escaping.h"
00022 #include "absl/strings/internal/resize_uninitialized.h"
00023 #include "absl/strings/string_view.h"
00024
00025 namespace absl {
00026 namespace substitute_internal {
00027
00028 void SubstituteAndAppendArray(std::string* output, absl::string_view format,
00029 const absl::string_view* args_array,
00030 size_t num_args) {
00031
00032 size_t size = 0;
00033 for (size_t i = 0; i < format.size(); i++) {
00034 if (format[i] == '$') {
00035 if (i + 1 >= format.size()) {
00036 #ifndef NDEBUG
00037 ABSL_RAW_LOG(FATAL,
00038 "Invalid strings::Substitute() format std::string: \"%s\".",
00039 absl::CEscape(format).c_str());
00040 #endif
00041 return;
00042 } else if (absl::ascii_isdigit(format[i + 1])) {
00043 int index = format[i + 1] - '0';
00044 if (static_cast<size_t>(index) >= num_args) {
00045 #ifndef NDEBUG
00046 ABSL_RAW_LOG(
00047 FATAL,
00048 "Invalid strings::Substitute() format std::string: asked for \"$"
00049 "%d\", but only %d args were given. Full format std::string was: "
00050 "\"%s\".",
00051 index, static_cast<int>(num_args), absl::CEscape(format).c_str());
00052 #endif
00053 return;
00054 }
00055 size += args_array[index].size();
00056 ++i;
00057 } else if (format[i + 1] == '$') {
00058 ++size;
00059 ++i;
00060 } else {
00061 #ifndef NDEBUG
00062 ABSL_RAW_LOG(FATAL,
00063 "Invalid strings::Substitute() format std::string: \"%s\".",
00064 absl::CEscape(format).c_str());
00065 #endif
00066 return;
00067 }
00068 } else {
00069 ++size;
00070 }
00071 }
00072
00073 if (size == 0) return;
00074
00075
00076 size_t original_size = output->size();
00077 strings_internal::STLStringResizeUninitialized(output, original_size + size);
00078 char* target = &(*output)[original_size];
00079 for (size_t i = 0; i < format.size(); i++) {
00080 if (format[i] == '$') {
00081 if (absl::ascii_isdigit(format[i + 1])) {
00082 const absl::string_view src = args_array[format[i + 1] - '0'];
00083 target = std::copy(src.begin(), src.end(), target);
00084 ++i;
00085 } else if (format[i + 1] == '$') {
00086 *target++ = '$';
00087 ++i;
00088 }
00089 } else {
00090 *target++ = format[i];
00091 }
00092 }
00093
00094 assert(target == output->data() + output->size());
00095 }
00096
00097 static const char kHexDigits[] = "0123456789abcdef";
00098 Arg::Arg(const void* value) {
00099 static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,
00100 "fix sizeof(scratch_)");
00101 if (value == nullptr) {
00102 piece_ = "NULL";
00103 } else {
00104 char* ptr = scratch_ + sizeof(scratch_);
00105 uintptr_t num = reinterpret_cast<uintptr_t>(value);
00106 do {
00107 *--ptr = kHexDigits[num & 0xf];
00108 num >>= 4;
00109 } while (num != 0);
00110 *--ptr = 'x';
00111 *--ptr = '0';
00112 piece_ = absl::string_view(ptr, scratch_ + sizeof(scratch_) - ptr);
00113 }
00114 }
00115
00116
00117 Arg::Arg(Hex hex) {
00118 char* const end = &scratch_[numbers_internal::kFastToBufferSize];
00119 char* writer = end;
00120 uint64_t value = hex.value;
00121 do {
00122 *--writer = kHexDigits[value & 0xF];
00123 value >>= 4;
00124 } while (value != 0);
00125
00126 char* beg;
00127 if (end - writer < hex.width) {
00128 beg = end - hex.width;
00129 std::fill_n(beg, writer - beg, hex.fill);
00130 } else {
00131 beg = writer;
00132 }
00133
00134 piece_ = absl::string_view(beg, end - beg);
00135 }
00136
00137
00138 Arg::Arg(Dec dec) {
00139 assert(dec.width <= numbers_internal::kFastToBufferSize);
00140 char* const end = &scratch_[numbers_internal::kFastToBufferSize];
00141 char* const minfill = end - dec.width;
00142 char* writer = end;
00143 uint64_t value = dec.value;
00144 bool neg = dec.neg;
00145 while (value > 9) {
00146 *--writer = '0' + (value % 10);
00147 value /= 10;
00148 }
00149 *--writer = '0' + value;
00150 if (neg) *--writer = '-';
00151
00152 ptrdiff_t fillers = writer - minfill;
00153 if (fillers > 0) {
00154
00155
00156 bool add_sign_again = false;
00157 if (neg && dec.fill == '0') {
00158 ++writer;
00159 add_sign_again = true;
00160 }
00161 writer -= fillers;
00162 std::fill_n(writer, fillers, dec.fill);
00163 if (add_sign_again) *--writer = '-';
00164 }
00165
00166 piece_ = absl::string_view(writer, end - writer);
00167 }
00168
00169 }
00170 }