| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_STRINGS_STRCAT_H_ |
| #define BASE_STRINGS_STRCAT_H_ |
| |
| #include <initializer_list> |
| |
| #include "base/base_export.h" |
| #include "base/containers/span.h" |
| #include "base/strings/string_piece.h" |
| #include "build/build_config.h" |
| |
| #if BUILDFLAG(IS_WIN) |
| // Guard against conflict with Win32 API StrCat macro: |
| // check StrCat wasn't and will not be redefined. |
| #define StrCat StrCat |
| #endif |
| |
| namespace base { |
| |
| // StrCat ---------------------------------------------------------------------- |
| // |
| // StrCat is a function to perform concatenation on a sequence of strings. |
| // It is preferrable to a sequence of "a + b + c" because it is both faster and |
| // generates less code. |
| // |
| // std::string result = base::StrCat({"foo ", result, "\nfoo ", bar}); |
| // |
| // To join an array of strings with a separator, see base::JoinString in |
| // base/strings/string_util.h. |
| // |
| // MORE INFO |
| // |
| // StrCat can see all arguments at once, so it can allocate one return buffer |
| // of exactly the right size and copy once, as opposed to a sequence of |
| // operator+ which generates a series of temporary strings, copying as it goes. |
| // And by using StringPiece arguments, StrCat can avoid creating temporary |
| // string objects for char* constants. |
| // |
| // ALTERNATIVES |
| // |
| // Internal Google / Abseil has a similar StrCat function. That version takes |
| // an overloaded number of arguments instead of initializer list (overflowing |
| // to initializer list for many arguments). We don't have any legacy |
| // requirements and using only initializer_list is simpler and generates |
| // roughly the same amount of code at the call sites. |
| // |
| // Abseil's StrCat also allows numbers by using an intermediate class that can |
| // be implicitly constructed from either a string or various number types. This |
| // class formats the numbers into a static buffer for increased performance, |
| // and the call sites look nice. |
| // |
| // As-written Abseil's helper class for numbers generates slightly more code |
| // than the raw StringPiece version. We can de-inline the helper class' |
| // constructors which will cause the StringPiece constructors to be de-inlined |
| // for this call and generate slightly less code. This is something we can |
| // explore more in the future. |
| |
| [[nodiscard]] BASE_EXPORT std::string StrCat(span<const StringPiece> pieces); |
| [[nodiscard]] BASE_EXPORT std::u16string StrCat( |
| span<const StringPiece16> pieces); |
| [[nodiscard]] BASE_EXPORT std::string StrCat(span<const std::string> pieces); |
| [[nodiscard]] BASE_EXPORT std::u16string StrCat( |
| span<const std::u16string> pieces); |
| |
| // Initializer list forwards to the array version. |
| inline std::string StrCat(std::initializer_list<StringPiece> pieces) { |
| return StrCat(make_span(pieces)); |
| } |
| |
| inline std::u16string StrCat(std::initializer_list<StringPiece16> pieces) { |
| return StrCat(make_span(pieces)); |
| } |
| |
| // StrAppend ------------------------------------------------------------------- |
| // |
| // Appends a sequence of strings to a destination. Prefer: |
| // StrAppend(&foo, ...); |
| // over: |
| // foo += StrCat(...); |
| // because it avoids a temporary string allocation and copy. |
| |
| BASE_EXPORT void StrAppend(std::string* dest, span<const StringPiece> pieces); |
| BASE_EXPORT void StrAppend(std::u16string* dest, |
| span<const StringPiece16> pieces); |
| BASE_EXPORT void StrAppend(std::string* dest, span<const std::string> pieces); |
| BASE_EXPORT void StrAppend(std::u16string* dest, |
| span<const std::u16string> pieces); |
| |
| // Initializer list forwards to the array version. |
| inline void StrAppend(std::string* dest, |
| std::initializer_list<StringPiece> pieces) { |
| StrAppend(dest, make_span(pieces)); |
| } |
| |
| inline void StrAppend(std::u16string* dest, |
| std::initializer_list<StringPiece16> pieces) { |
| StrAppend(dest, make_span(pieces)); |
| } |
| |
| } // namespace base |
| |
| #if BUILDFLAG(IS_WIN) |
| #include "base/strings/strcat_win.h" |
| #endif |
| |
| #endif // BASE_STRINGS_STRCAT_H_ |