• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_STRINGS_STRCAT_H_
6 #define BASE_STRINGS_STRCAT_H_
7 
8 #include <initializer_list>
9 #include <string_view>
10 
11 #include "base/base_export.h"
12 #include "base/containers/span.h"
13 #include "build/build_config.h"
14 
15 #if BUILDFLAG(IS_WIN)
16 // Guard against conflict with Win32 API StrCat macro:
17 // check StrCat wasn't and will not be redefined.
18 #define StrCat StrCat
19 #endif
20 
21 namespace base {
22 
23 // StrCat ----------------------------------------------------------------------
24 //
25 // StrCat is a function to perform concatenation on a sequence of strings.
26 // It is preferrable to a sequence of "a + b + c" because it is both faster and
27 // generates less code.
28 //
29 //   std::string result = base::StrCat({"foo ", result, "\nfoo ", bar});
30 //
31 // To join an array of strings with a separator, see base::JoinString in
32 // base/strings/string_util.h.
33 //
34 // MORE INFO
35 //
36 // StrCat can see all arguments at once, so it can allocate one return buffer
37 // of exactly the right size and copy once, as opposed to a sequence of
38 // operator+ which generates a series of temporary strings, copying as it goes.
39 // And by using std::string_view arguments, StrCat can avoid creating temporary
40 // string objects for char* constants.
41 //
42 // ALTERNATIVES
43 //
44 // Internal Google / Abseil has a similar StrCat function. That version takes
45 // an overloaded number of arguments instead of initializer list (overflowing
46 // to initializer list for many arguments). We don't have any legacy
47 // requirements and using only initializer_list is simpler and generates
48 // roughly the same amount of code at the call sites.
49 //
50 // Abseil's StrCat also allows numbers by using an intermediate class that can
51 // be implicitly constructed from either a string or various number types. This
52 // class formats the numbers into a static buffer for increased performance,
53 // and the call sites look nice.
54 //
55 // As-written Abseil's helper class for numbers generates slightly more code
56 // than the raw std::string_view version. We can de-inline the helper class'
57 // constructors which will cause the std::string_view constructors to be
58 // de-inlined for this call and generate slightly less code. This is something
59 // we can explore more in the future.
60 
61 [[nodiscard]] BASE_EXPORT std::string StrCat(
62     span<const std::string_view> pieces);
63 [[nodiscard]] BASE_EXPORT std::u16string StrCat(
64     span<const std::u16string_view> pieces);
65 [[nodiscard]] BASE_EXPORT std::string StrCat(span<const std::string> pieces);
66 [[nodiscard]] BASE_EXPORT std::u16string StrCat(
67     span<const std::u16string> pieces);
68 
69 // Initializer list forwards to the array version.
StrCat(std::initializer_list<std::string_view> pieces)70 inline std::string StrCat(std::initializer_list<std::string_view> pieces) {
71   return StrCat(span(pieces));
72 }
73 
StrCat(std::initializer_list<std::u16string_view> pieces)74 inline std::u16string StrCat(
75     std::initializer_list<std::u16string_view> pieces) {
76   return StrCat(span(pieces));
77 }
78 
79 // StrAppend -------------------------------------------------------------------
80 //
81 // Appends a sequence of strings to a destination. Prefer:
82 //   StrAppend(&foo, ...);
83 // over:
84 //   foo += StrCat(...);
85 // because it avoids a temporary string allocation and copy.
86 
87 BASE_EXPORT void StrAppend(std::string* dest,
88                            span<const std::string_view> pieces);
89 BASE_EXPORT void StrAppend(std::u16string* dest,
90                            span<const std::u16string_view> pieces);
91 BASE_EXPORT void StrAppend(std::string* dest, span<const std::string> pieces);
92 BASE_EXPORT void StrAppend(std::u16string* dest,
93                            span<const std::u16string> pieces);
94 
95 // Initializer list forwards to the array version.
StrAppend(std::string * dest,std::initializer_list<std::string_view> pieces)96 inline void StrAppend(std::string* dest,
97                       std::initializer_list<std::string_view> pieces) {
98   StrAppend(dest, span(pieces));
99 }
100 
StrAppend(std::u16string * dest,std::initializer_list<std::u16string_view> pieces)101 inline void StrAppend(std::u16string* dest,
102                       std::initializer_list<std::u16string_view> pieces) {
103   StrAppend(dest, span(pieces));
104 }
105 
106 }  // namespace base
107 
108 #if BUILDFLAG(IS_WIN)
109 #include "base/strings/strcat_win.h"
110 #endif
111 
112 #endif  // BASE_STRINGS_STRCAT_H_
113