|
||||
File indexing completed on 2024-11-15 09:01:16
0001 // 0002 // Copyright 2017 The Abseil Authors. 0003 // 0004 // Licensed under the Apache License, Version 2.0 (the "License"); 0005 // you may not use this file except in compliance with the License. 0006 // You may obtain a copy of the License at 0007 // 0008 // https://www.apache.org/licenses/LICENSE-2.0 0009 // 0010 // Unless required by applicable law or agreed to in writing, software 0011 // distributed under the License is distributed on an "AS IS" BASIS, 0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0013 // See the License for the specific language governing permissions and 0014 // limitations under the License. 0015 // 0016 // ----------------------------------------------------------------------------- 0017 // File: str_join.h 0018 // ----------------------------------------------------------------------------- 0019 // 0020 // This header file contains functions for joining a range of elements and 0021 // returning the result as a std::string. StrJoin operations are specified by 0022 // passing a range, a separator string to use between the elements joined, and 0023 // an optional Formatter responsible for converting each argument in the range 0024 // to a string. If omitted, a default `AlphaNumFormatter()` is called on the 0025 // elements to be joined, using the same formatting that `absl::StrCat()` uses. 0026 // This package defines a number of default formatters, and you can define your 0027 // own implementations. 0028 // 0029 // Ranges are specified by passing a container with `std::begin()` and 0030 // `std::end()` iterators, container-specific `begin()` and `end()` iterators, a 0031 // brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous 0032 // objects. The separator string is specified as an `absl::string_view`. 0033 // 0034 // Because the default formatter uses the `absl::AlphaNum` class, 0035 // `absl::StrJoin()`, like `absl::StrCat()`, will work out-of-the-box on 0036 // collections of strings, ints, floats, doubles, etc. 0037 // 0038 // Example: 0039 // 0040 // std::vector<std::string> v = {"foo", "bar", "baz"}; 0041 // std::string s = absl::StrJoin(v, "-"); 0042 // EXPECT_EQ("foo-bar-baz", s); 0043 // 0044 // See comments on the `absl::StrJoin()` function for more examples. 0045 0046 #ifndef ABSL_STRINGS_STR_JOIN_H_ 0047 #define ABSL_STRINGS_STR_JOIN_H_ 0048 0049 #include <cstdio> 0050 #include <cstring> 0051 #include <initializer_list> 0052 #include <iterator> 0053 #include <string> 0054 #include <tuple> 0055 #include <type_traits> 0056 #include <utility> 0057 0058 #include "absl/base/macros.h" 0059 #include "absl/strings/internal/str_join_internal.h" 0060 #include "absl/strings/string_view.h" 0061 0062 namespace absl { 0063 ABSL_NAMESPACE_BEGIN 0064 0065 // ----------------------------------------------------------------------------- 0066 // Concept: Formatter 0067 // ----------------------------------------------------------------------------- 0068 // 0069 // A Formatter is a function object that is responsible for formatting its 0070 // argument as a string and appending it to a given output std::string. 0071 // Formatters may be implemented as function objects, lambdas, or normal 0072 // functions. You may provide your own Formatter to enable `absl::StrJoin()` to 0073 // work with arbitrary types. 0074 // 0075 // The following is an example of a custom Formatter that uses 0076 // `absl::FormatDuration` to join a list of `absl::Duration`s. 0077 // 0078 // std::vector<absl::Duration> v = {absl::Seconds(1), absl::Milliseconds(10)}; 0079 // std::string s = 0080 // absl::StrJoin(v, ", ", [](std::string* out, absl::Duration dur) { 0081 // absl::StrAppend(out, absl::FormatDuration(dur)); 0082 // }); 0083 // EXPECT_EQ(s, "1s, 10ms"); 0084 // 0085 // The following standard formatters are provided within this file: 0086 // 0087 // - `AlphaNumFormatter()` (the default) 0088 // - `StreamFormatter()` 0089 // - `PairFormatter()` 0090 // - `DereferenceFormatter()` 0091 0092 // AlphaNumFormatter() 0093 // 0094 // Default formatter used if none is specified. Uses `absl::AlphaNum` to convert 0095 // numeric arguments to strings. 0096 inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() { 0097 return strings_internal::AlphaNumFormatterImpl(); 0098 } 0099 0100 // StreamFormatter() 0101 // 0102 // Formats its argument using the << operator. 0103 inline strings_internal::StreamFormatterImpl StreamFormatter() { 0104 return strings_internal::StreamFormatterImpl(); 0105 } 0106 0107 // Function Template: PairFormatter(Formatter, absl::string_view, Formatter) 0108 // 0109 // Formats a `std::pair` by putting a given separator between the pair's 0110 // `.first` and `.second` members. This formatter allows you to specify 0111 // custom Formatters for both the first and second member of each pair. 0112 template <typename FirstFormatter, typename SecondFormatter> 0113 inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter> 0114 PairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2) { 0115 return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>( 0116 std::move(f1), sep, std::move(f2)); 0117 } 0118 0119 // Function overload of PairFormatter() for using a default 0120 // `AlphaNumFormatter()` for each Formatter in the pair. 0121 inline strings_internal::PairFormatterImpl< 0122 strings_internal::AlphaNumFormatterImpl, 0123 strings_internal::AlphaNumFormatterImpl> 0124 PairFormatter(absl::string_view sep) { 0125 return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter()); 0126 } 0127 0128 // Function Template: DereferenceFormatter(Formatter) 0129 // 0130 // Formats its argument by dereferencing it and then applying the given 0131 // formatter. This formatter is useful for formatting a container of 0132 // pointer-to-T. This pattern often shows up when joining repeated fields in 0133 // protocol buffers. 0134 template <typename Formatter> 0135 strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter( 0136 Formatter&& f) { 0137 return strings_internal::DereferenceFormatterImpl<Formatter>( 0138 std::forward<Formatter>(f)); 0139 } 0140 0141 // Function overload of `DereferenceFormatter()` for using a default 0142 // `AlphaNumFormatter()`. 0143 inline strings_internal::DereferenceFormatterImpl< 0144 strings_internal::AlphaNumFormatterImpl> 0145 DereferenceFormatter() { 0146 return strings_internal::DereferenceFormatterImpl< 0147 strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter()); 0148 } 0149 0150 // ----------------------------------------------------------------------------- 0151 // StrJoin() 0152 // ----------------------------------------------------------------------------- 0153 // 0154 // Joins a range of elements and returns the result as a std::string. 0155 // `absl::StrJoin()` takes a range, a separator string to use between the 0156 // elements joined, and an optional Formatter responsible for converting each 0157 // argument in the range to a string. 0158 // 0159 // If omitted, the default `AlphaNumFormatter()` is called on the elements to be 0160 // joined. 0161 // 0162 // Example 1: 0163 // // Joins a collection of strings. This pattern also works with a collection 0164 // // of `absl::string_view` or even `const char*`. 0165 // std::vector<std::string> v = {"foo", "bar", "baz"}; 0166 // std::string s = absl::StrJoin(v, "-"); 0167 // EXPECT_EQ(s, "foo-bar-baz"); 0168 // 0169 // Example 2: 0170 // // Joins the values in the given `std::initializer_list<>` specified using 0171 // // brace initialization. This pattern also works with an initializer_list 0172 // // of ints or `absl::string_view` -- any `AlphaNum`-compatible type. 0173 // std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-"); 0174 // EXPECT_EQs, "foo-bar-baz"); 0175 // 0176 // Example 3: 0177 // // Joins a collection of ints. This pattern also works with floats, 0178 // // doubles, int64s -- any `StrCat()`-compatible type. 0179 // std::vector<int> v = {1, 2, 3, -4}; 0180 // std::string s = absl::StrJoin(v, "-"); 0181 // EXPECT_EQ(s, "1-2-3--4"); 0182 // 0183 // Example 4: 0184 // // Joins a collection of pointer-to-int. By default, pointers are 0185 // // dereferenced and the pointee is formatted using the default format for 0186 // // that type; such dereferencing occurs for all levels of indirection, so 0187 // // this pattern works just as well for `std::vector<int**>` as for 0188 // // `std::vector<int*>`. 0189 // int x = 1, y = 2, z = 3; 0190 // std::vector<int*> v = {&x, &y, &z}; 0191 // std::string s = absl::StrJoin(v, "-"); 0192 // EXPECT_EQ(s, "1-2-3"); 0193 // 0194 // Example 5: 0195 // // Dereferencing of `std::unique_ptr<>` is also supported: 0196 // std::vector<std::unique_ptr<int>> v 0197 // v.emplace_back(new int(1)); 0198 // v.emplace_back(new int(2)); 0199 // v.emplace_back(new int(3)); 0200 // std::string s = absl::StrJoin(v, "-"); 0201 // EXPECT_EQ(s, "1-2-3"); 0202 // 0203 // Example 6: 0204 // // Joins a `std::map`, with each key-value pair separated by an equals 0205 // // sign. This pattern would also work with, say, a 0206 // // `std::vector<std::pair<>>`. 0207 // std::map<std::string, int> m = { 0208 // {"a", 1}, 0209 // {"b", 2}, 0210 // {"c", 3}}; 0211 // std::string s = absl::StrJoin(m, ",", absl::PairFormatter("=")); 0212 // EXPECT_EQ(s, "a=1,b=2,c=3"); 0213 // 0214 // Example 7: 0215 // // These examples show how `absl::StrJoin()` handles a few common edge 0216 // // cases: 0217 // std::vector<std::string> v_empty; 0218 // EXPECT_EQ(absl::StrJoin(v_empty, "-"), ""); 0219 // 0220 // std::vector<std::string> v_one_item = {"foo"}; 0221 // EXPECT_EQ(absl::StrJoin(v_one_item, "-"), "foo"); 0222 // 0223 // std::vector<std::string> v_empty_string = {""}; 0224 // EXPECT_EQ(absl::StrJoin(v_empty_string, "-"), ""); 0225 // 0226 // std::vector<std::string> v_one_item_empty_string = {"a", ""}; 0227 // EXPECT_EQ(absl::StrJoin(v_one_item_empty_string, "-"), "a-"); 0228 // 0229 // std::vector<std::string> v_two_empty_string = {"", ""}; 0230 // EXPECT_EQ(absl::StrJoin(v_two_empty_string, "-"), "-"); 0231 // 0232 // Example 8: 0233 // // Joins a `std::tuple<T...>` of heterogeneous types, converting each to 0234 // // a std::string using the `absl::AlphaNum` class. 0235 // std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-"); 0236 // EXPECT_EQ(s, "123-abc-0.456"); 0237 0238 template <typename Iterator, typename Formatter> 0239 std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, 0240 Formatter&& fmt) { 0241 return strings_internal::JoinAlgorithm(start, end, sep, fmt); 0242 } 0243 0244 template <typename Range, typename Formatter> 0245 std::string StrJoin(const Range& range, absl::string_view separator, 0246 Formatter&& fmt) { 0247 return strings_internal::JoinRange(range, separator, fmt); 0248 } 0249 0250 template <typename T, typename Formatter> 0251 std::string StrJoin(std::initializer_list<T> il, absl::string_view separator, 0252 Formatter&& fmt) { 0253 return strings_internal::JoinRange(il, separator, fmt); 0254 } 0255 0256 template <typename... T, typename Formatter> 0257 std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator, 0258 Formatter&& fmt) { 0259 return strings_internal::JoinAlgorithm(value, separator, fmt); 0260 } 0261 0262 template <typename Iterator> 0263 std::string StrJoin(Iterator start, Iterator end, absl::string_view separator) { 0264 return strings_internal::JoinRange(start, end, separator); 0265 } 0266 0267 template <typename Range> 0268 std::string StrJoin(const Range& range, absl::string_view separator) { 0269 return strings_internal::JoinRange(range, separator); 0270 } 0271 0272 template <typename T> 0273 std::string StrJoin(std::initializer_list<T> il, 0274 absl::string_view separator) { 0275 return strings_internal::JoinRange(il, separator); 0276 } 0277 0278 template <typename... T> 0279 std::string StrJoin(const std::tuple<T...>& value, 0280 absl::string_view separator) { 0281 return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter()); 0282 } 0283 0284 ABSL_NAMESPACE_END 0285 } // namespace absl 0286 0287 #endif // ABSL_STRINGS_STR_JOIN_H_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |