xref: /aosp_15_r20/external/libchrome/base/strings/strcat.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker namespace base {
8*635a8641SAndroid Build Coastguard Worker 
9*635a8641SAndroid Build Coastguard Worker namespace {
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker // Reserves an additional amount of size in the given string, growing by at
12*635a8641SAndroid Build Coastguard Worker // least 2x. Used by StrAppend().
13*635a8641SAndroid Build Coastguard Worker //
14*635a8641SAndroid Build Coastguard Worker // The "at least 2x" growing rule duplicates the exponential growth of
15*635a8641SAndroid Build Coastguard Worker // std::string. The problem is that most implementations of reserve() will grow
16*635a8641SAndroid Build Coastguard Worker // exactly to the requested amount instead of exponentially growing like would
17*635a8641SAndroid Build Coastguard Worker // happen when appending normally. If we didn't do this, an append after the
18*635a8641SAndroid Build Coastguard Worker // call to StrAppend() would definitely cause a reallocation, and loops with
19*635a8641SAndroid Build Coastguard Worker // StrAppend() calls would have O(n^2) complexity to execute. Instead, we want
20*635a8641SAndroid Build Coastguard Worker // StrAppend() to have the same semantics as std::string::append().
21*635a8641SAndroid Build Coastguard Worker //
22*635a8641SAndroid Build Coastguard Worker // If the string is empty, we assume that exponential growth is not necessary.
23*635a8641SAndroid Build Coastguard Worker template <typename String>
ReserveAdditional(String * str,typename String::size_type additional)24*635a8641SAndroid Build Coastguard Worker void ReserveAdditional(String* str, typename String::size_type additional) {
25*635a8641SAndroid Build Coastguard Worker   str->reserve(std::max(str->size() + additional, str->size() * 2));
26*635a8641SAndroid Build Coastguard Worker }
27*635a8641SAndroid Build Coastguard Worker 
28*635a8641SAndroid Build Coastguard Worker template <typename DestString, typename InputString>
StrAppendT(DestString * dest,span<const InputString> pieces)29*635a8641SAndroid Build Coastguard Worker void StrAppendT(DestString* dest, span<const InputString> pieces) {
30*635a8641SAndroid Build Coastguard Worker   size_t additional_size = 0;
31*635a8641SAndroid Build Coastguard Worker   for (const auto& cur : pieces)
32*635a8641SAndroid Build Coastguard Worker     additional_size += cur.size();
33*635a8641SAndroid Build Coastguard Worker   ReserveAdditional(dest, additional_size);
34*635a8641SAndroid Build Coastguard Worker 
35*635a8641SAndroid Build Coastguard Worker   for (const auto& cur : pieces)
36*635a8641SAndroid Build Coastguard Worker     dest->append(cur.data(), cur.size());
37*635a8641SAndroid Build Coastguard Worker }
38*635a8641SAndroid Build Coastguard Worker 
39*635a8641SAndroid Build Coastguard Worker }  // namespace
40*635a8641SAndroid Build Coastguard Worker 
StrCat(span<const StringPiece> pieces)41*635a8641SAndroid Build Coastguard Worker std::string StrCat(span<const StringPiece> pieces) {
42*635a8641SAndroid Build Coastguard Worker   std::string result;
43*635a8641SAndroid Build Coastguard Worker   StrAppendT(&result, pieces);
44*635a8641SAndroid Build Coastguard Worker   return result;
45*635a8641SAndroid Build Coastguard Worker }
46*635a8641SAndroid Build Coastguard Worker 
StrCat(span<const StringPiece16> pieces)47*635a8641SAndroid Build Coastguard Worker string16 StrCat(span<const StringPiece16> pieces) {
48*635a8641SAndroid Build Coastguard Worker   string16 result;
49*635a8641SAndroid Build Coastguard Worker   StrAppendT(&result, pieces);
50*635a8641SAndroid Build Coastguard Worker   return result;
51*635a8641SAndroid Build Coastguard Worker }
52*635a8641SAndroid Build Coastguard Worker 
StrCat(span<const std::string> pieces)53*635a8641SAndroid Build Coastguard Worker std::string StrCat(span<const std::string> pieces) {
54*635a8641SAndroid Build Coastguard Worker   std::string result;
55*635a8641SAndroid Build Coastguard Worker   StrAppendT(&result, pieces);
56*635a8641SAndroid Build Coastguard Worker   return result;
57*635a8641SAndroid Build Coastguard Worker }
58*635a8641SAndroid Build Coastguard Worker 
StrCat(span<const string16> pieces)59*635a8641SAndroid Build Coastguard Worker string16 StrCat(span<const string16> pieces) {
60*635a8641SAndroid Build Coastguard Worker   string16 result;
61*635a8641SAndroid Build Coastguard Worker   StrAppendT(&result, pieces);
62*635a8641SAndroid Build Coastguard Worker   return result;
63*635a8641SAndroid Build Coastguard Worker }
64*635a8641SAndroid Build Coastguard Worker 
StrAppend(std::string * dest,span<const StringPiece> pieces)65*635a8641SAndroid Build Coastguard Worker void StrAppend(std::string* dest, span<const StringPiece> pieces) {
66*635a8641SAndroid Build Coastguard Worker   StrAppendT(dest, pieces);
67*635a8641SAndroid Build Coastguard Worker }
68*635a8641SAndroid Build Coastguard Worker 
StrAppend(string16 * dest,span<const StringPiece16> pieces)69*635a8641SAndroid Build Coastguard Worker void StrAppend(string16* dest, span<const StringPiece16> pieces) {
70*635a8641SAndroid Build Coastguard Worker   StrAppendT(dest, pieces);
71*635a8641SAndroid Build Coastguard Worker }
72*635a8641SAndroid Build Coastguard Worker 
StrAppend(std::string * dest,span<const std::string> pieces)73*635a8641SAndroid Build Coastguard Worker void StrAppend(std::string* dest, span<const std::string> pieces) {
74*635a8641SAndroid Build Coastguard Worker   StrAppendT(dest, pieces);
75*635a8641SAndroid Build Coastguard Worker }
76*635a8641SAndroid Build Coastguard Worker 
StrAppend(string16 * dest,span<const string16> pieces)77*635a8641SAndroid Build Coastguard Worker void StrAppend(string16* dest, span<const string16> pieces) {
78*635a8641SAndroid Build Coastguard Worker   StrAppendT(dest, pieces);
79*635a8641SAndroid Build Coastguard Worker }
80*635a8641SAndroid Build Coastguard Worker 
81*635a8641SAndroid Build Coastguard Worker }  // namespace base
82