00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/strings/str_cat.h"
00016
00017 #include <assert.h>
00018 #include <algorithm>
00019 #include <cstdint>
00020 #include <cstring>
00021
00022 #include "absl/strings/ascii.h"
00023 #include "absl/strings/internal/resize_uninitialized.h"
00024
00025 namespace absl {
00026
00027 AlphaNum::AlphaNum(Hex hex) {
00028 char* const end = &digits_[numbers_internal::kFastToBufferSize];
00029 char* writer = end;
00030 uint64_t value = hex.value;
00031 static const char hexdigits[] = "0123456789abcdef";
00032 do {
00033 *--writer = hexdigits[value & 0xF];
00034 value >>= 4;
00035 } while (value != 0);
00036
00037 char* beg;
00038 if (end - writer < hex.width) {
00039 beg = end - hex.width;
00040 std::fill_n(beg, writer - beg, hex.fill);
00041 } else {
00042 beg = writer;
00043 }
00044
00045 piece_ = absl::string_view(beg, end - beg);
00046 }
00047
00048 AlphaNum::AlphaNum(Dec dec) {
00049 assert(dec.width <= numbers_internal::kFastToBufferSize);
00050 char* const end = &digits_[numbers_internal::kFastToBufferSize];
00051 char* const minfill = end - dec.width;
00052 char* writer = end;
00053 uint64_t value = dec.value;
00054 bool neg = dec.neg;
00055 while (value > 9) {
00056 *--writer = '0' + (value % 10);
00057 value /= 10;
00058 }
00059 *--writer = '0' + value;
00060 if (neg) *--writer = '-';
00061
00062 ptrdiff_t fillers = writer - minfill;
00063 if (fillers > 0) {
00064
00065
00066 bool add_sign_again = false;
00067 if (neg && dec.fill == '0') {
00068 ++writer;
00069 add_sign_again = true;
00070 }
00071 writer -= fillers;
00072 std::fill_n(writer, fillers, dec.fill);
00073 if (add_sign_again) *--writer = '-';
00074 }
00075
00076 piece_ = absl::string_view(writer, end - writer);
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 static char* Append(char* out, const AlphaNum& x) {
00089
00090
00091 char* after = out + x.size();
00092 if (x.size() != 0) {
00093 memcpy(out, x.data(), x.size());
00094 }
00095 return after;
00096 }
00097
00098 std::string StrCat(const AlphaNum& a, const AlphaNum& b) {
00099 std::string result;
00100 absl::strings_internal::STLStringResizeUninitialized(&result,
00101 a.size() + b.size());
00102 char* const begin = &*result.begin();
00103 char* out = begin;
00104 out = Append(out, a);
00105 out = Append(out, b);
00106 assert(out == begin + result.size());
00107 return result;
00108 }
00109
00110 std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {
00111 std::string result;
00112 strings_internal::STLStringResizeUninitialized(
00113 &result, a.size() + b.size() + c.size());
00114 char* const begin = &*result.begin();
00115 char* out = begin;
00116 out = Append(out, a);
00117 out = Append(out, b);
00118 out = Append(out, c);
00119 assert(out == begin + result.size());
00120 return result;
00121 }
00122
00123 std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
00124 const AlphaNum& d) {
00125 std::string result;
00126 strings_internal::STLStringResizeUninitialized(
00127 &result, a.size() + b.size() + c.size() + d.size());
00128 char* const begin = &*result.begin();
00129 char* out = begin;
00130 out = Append(out, a);
00131 out = Append(out, b);
00132 out = Append(out, c);
00133 out = Append(out, d);
00134 assert(out == begin + result.size());
00135 return result;
00136 }
00137
00138 namespace strings_internal {
00139
00140
00141 std::string CatPieces(std::initializer_list<absl::string_view> pieces) {
00142 std::string result;
00143 size_t total_size = 0;
00144 for (const absl::string_view piece : pieces) total_size += piece.size();
00145 strings_internal::STLStringResizeUninitialized(&result, total_size);
00146
00147 char* const begin = &*result.begin();
00148 char* out = begin;
00149 for (const absl::string_view piece : pieces) {
00150 const size_t this_size = piece.size();
00151 if (this_size != 0) {
00152 memcpy(out, piece.data(), this_size);
00153 out += this_size;
00154 }
00155 }
00156 assert(out == begin + result.size());
00157 return result;
00158 }
00159
00160
00161
00162
00163
00164
00165 #define ASSERT_NO_OVERLAP(dest, src) \
00166 assert(((src).size() == 0) || \
00167 (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size())))
00168
00169 void AppendPieces(std::string* dest,
00170 std::initializer_list<absl::string_view> pieces) {
00171 size_t old_size = dest->size();
00172 size_t total_size = old_size;
00173 for (const absl::string_view piece : pieces) {
00174 ASSERT_NO_OVERLAP(*dest, piece);
00175 total_size += piece.size();
00176 }
00177 strings_internal::STLStringResizeUninitialized(dest, total_size);
00178
00179 char* const begin = &*dest->begin();
00180 char* out = begin + old_size;
00181 for (const absl::string_view piece : pieces) {
00182 const size_t this_size = piece.size();
00183 if (this_size != 0) {
00184 memcpy(out, piece.data(), this_size);
00185 out += this_size;
00186 }
00187 }
00188 assert(out == begin + dest->size());
00189 }
00190
00191 }
00192
00193 void StrAppend(std::string* dest, const AlphaNum& a) {
00194 ASSERT_NO_OVERLAP(*dest, a);
00195 dest->append(a.data(), a.size());
00196 }
00197
00198 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) {
00199 ASSERT_NO_OVERLAP(*dest, a);
00200 ASSERT_NO_OVERLAP(*dest, b);
00201 std::string::size_type old_size = dest->size();
00202 strings_internal::STLStringResizeUninitialized(
00203 dest, old_size + a.size() + b.size());
00204 char* const begin = &*dest->begin();
00205 char* out = begin + old_size;
00206 out = Append(out, a);
00207 out = Append(out, b);
00208 assert(out == begin + dest->size());
00209 }
00210
00211 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
00212 const AlphaNum& c) {
00213 ASSERT_NO_OVERLAP(*dest, a);
00214 ASSERT_NO_OVERLAP(*dest, b);
00215 ASSERT_NO_OVERLAP(*dest, c);
00216 std::string::size_type old_size = dest->size();
00217 strings_internal::STLStringResizeUninitialized(
00218 dest, old_size + a.size() + b.size() + c.size());
00219 char* const begin = &*dest->begin();
00220 char* out = begin + old_size;
00221 out = Append(out, a);
00222 out = Append(out, b);
00223 out = Append(out, c);
00224 assert(out == begin + dest->size());
00225 }
00226
00227 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
00228 const AlphaNum& c, const AlphaNum& d) {
00229 ASSERT_NO_OVERLAP(*dest, a);
00230 ASSERT_NO_OVERLAP(*dest, b);
00231 ASSERT_NO_OVERLAP(*dest, c);
00232 ASSERT_NO_OVERLAP(*dest, d);
00233 std::string::size_type old_size = dest->size();
00234 strings_internal::STLStringResizeUninitialized(
00235 dest, old_size + a.size() + b.size() + c.size() + d.size());
00236 char* const begin = &*dest->begin();
00237 char* out = begin + old_size;
00238 out = Append(out, a);
00239 out = Append(out, b);
00240 out = Append(out, c);
00241 out = Append(out, d);
00242 assert(out == begin + dest->size());
00243 }
00244
00245 }