00001 // 00002 // Copyright 2017 The Abseil Authors. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // https://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 // 00016 // ----------------------------------------------------------------------------- 00017 // File: str_join.h 00018 // ----------------------------------------------------------------------------- 00019 // 00020 // This header file contains functions for joining a range of elements and 00021 // returning the result as a std::string. StrJoin operations are specified by 00022 // passing a range, a separator string to use between the elements joined, and 00023 // an optional Formatter responsible for converting each argument in the range 00024 // to a string. If omitted, a default `AlphaNumFormatter()` is called on the 00025 // elements to be joined, using the same formatting that `absl::StrCat()` uses. 00026 // This package defines a number of default formatters, and you can define your 00027 // own implementations. 00028 // 00029 // Ranges are specified by passing a container with `std::begin()` and 00030 // `std::end()` iterators, container-specific `begin()` and `end()` iterators, a 00031 // brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous 00032 // objects. The separator string is specified as an `absl::string_view`. 00033 // 00034 // Because the default formatter uses the `absl::AlphaNum` class, 00035 // `absl::StrJoin()`, like `absl::StrCat()`, will work out-of-the-box on 00036 // collections of strings, ints, floats, doubles, etc. 00037 // 00038 // Example: 00039 // 00040 // std::vector<std::string> v = {"foo", "bar", "baz"}; 00041 // std::string s = absl::StrJoin(v, "-"); 00042 // EXPECT_EQ("foo-bar-baz", s); 00043 // 00044 // See comments on the `absl::StrJoin()` function for more examples. 00045 00046 #ifndef ABSL_STRINGS_STR_JOIN_H_ 00047 #define ABSL_STRINGS_STR_JOIN_H_ 00048 00049 #include <cstdio> 00050 #include <cstring> 00051 #include <initializer_list> 00052 #include <iterator> 00053 #include <string> 00054 #include <tuple> 00055 #include <type_traits> 00056 #include <utility> 00057 00058 #include "absl/base/macros.h" 00059 #include "absl/strings/internal/str_join_internal.h" 00060 #include "absl/strings/string_view.h" 00061 00062 namespace absl { 00063 00064 // ----------------------------------------------------------------------------- 00065 // Concept: Formatter 00066 // ----------------------------------------------------------------------------- 00067 // 00068 // A Formatter is a function object that is responsible for formatting its 00069 // argument as a string and appending it to a given output std::string. 00070 // Formatters may be implemented as function objects, lambdas, or normal 00071 // functions. You may provide your own Formatter to enable `absl::StrJoin()` to 00072 // work with arbitrary types. 00073 // 00074 // The following is an example of a custom Formatter that simply uses 00075 // `std::to_string()` to format an integer as a std::string. 00076 // 00077 // struct MyFormatter { 00078 // void operator()(std::string* out, int i) const { 00079 // out->append(std::to_string(i)); 00080 // } 00081 // }; 00082 // 00083 // You would use the above formatter by passing an instance of it as the final 00084 // argument to `absl::StrJoin()`: 00085 // 00086 // std::vector<int> v = {1, 2, 3, 4}; 00087 // std::string s = absl::StrJoin(v, "-", MyFormatter()); 00088 // EXPECT_EQ("1-2-3-4", s); 00089 // 00090 // The following standard formatters are provided within this file: 00091 // 00092 // - `AlphaNumFormatter()` (the default) 00093 // - `StreamFormatter()` 00094 // - `PairFormatter()` 00095 // - `DereferenceFormatter()` 00096 00097 // AlphaNumFormatter() 00098 // 00099 // Default formatter used if none is specified. Uses `absl::AlphaNum` to convert 00100 // numeric arguments to strings. 00101 inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() { 00102 return strings_internal::AlphaNumFormatterImpl(); 00103 } 00104 00105 // StreamFormatter() 00106 // 00107 // Formats its argument using the << operator. 00108 inline strings_internal::StreamFormatterImpl StreamFormatter() { 00109 return strings_internal::StreamFormatterImpl(); 00110 } 00111 00112 // Function Template: PairFormatter(Formatter, absl::string_view, Formatter) 00113 // 00114 // Formats a `std::pair` by putting a given separator between the pair's 00115 // `.first` and `.second` members. This formatter allows you to specify 00116 // custom Formatters for both the first and second member of each pair. 00117 template <typename FirstFormatter, typename SecondFormatter> 00118 inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter> 00119 PairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2) { 00120 return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>( 00121 std::move(f1), sep, std::move(f2)); 00122 } 00123 00124 // Function overload of PairFormatter() for using a default 00125 // `AlphaNumFormatter()` for each Formatter in the pair. 00126 inline strings_internal::PairFormatterImpl< 00127 strings_internal::AlphaNumFormatterImpl, 00128 strings_internal::AlphaNumFormatterImpl> 00129 PairFormatter(absl::string_view sep) { 00130 return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter()); 00131 } 00132 00133 // Function Template: DereferenceFormatter(Formatter) 00134 // 00135 // Formats its argument by dereferencing it and then applying the given 00136 // formatter. This formatter is useful for formatting a container of 00137 // pointer-to-T. This pattern often shows up when joining repeated fields in 00138 // protocol buffers. 00139 template <typename Formatter> 00140 strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter( 00141 Formatter&& f) { 00142 return strings_internal::DereferenceFormatterImpl<Formatter>( 00143 std::forward<Formatter>(f)); 00144 } 00145 00146 // Function overload of `DererefenceFormatter()` for using a default 00147 // `AlphaNumFormatter()`. 00148 inline strings_internal::DereferenceFormatterImpl< 00149 strings_internal::AlphaNumFormatterImpl> 00150 DereferenceFormatter() { 00151 return strings_internal::DereferenceFormatterImpl< 00152 strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter()); 00153 } 00154 00155 // ----------------------------------------------------------------------------- 00156 // StrJoin() 00157 // ----------------------------------------------------------------------------- 00158 // 00159 // Joins a range of elements and returns the result as a std::string. 00160 // `absl::StrJoin()` takes a range, a separator string to use between the 00161 // elements joined, and an optional Formatter responsible for converting each 00162 // argument in the range to a string. 00163 // 00164 // If omitted, the default `AlphaNumFormatter()` is called on the elements to be 00165 // joined. 00166 // 00167 // Example 1: 00168 // // Joins a collection of strings. This pattern also works with a collection 00169 // // of `absl::string_view` or even `const char*`. 00170 // std::vector<std::string> v = {"foo", "bar", "baz"}; 00171 // std::string s = absl::StrJoin(v, "-"); 00172 // EXPECT_EQ("foo-bar-baz", s); 00173 // 00174 // Example 2: 00175 // // Joins the values in the given `std::initializer_list<>` specified using 00176 // // brace initialization. This pattern also works with an initializer_list 00177 // // of ints or `absl::string_view` -- any `AlphaNum`-compatible type. 00178 // std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-"); 00179 // EXPECT_EQ("foo-bar-baz", s); 00180 // 00181 // Example 3: 00182 // // Joins a collection of ints. This pattern also works with floats, 00183 // // doubles, int64s -- any `StrCat()`-compatible type. 00184 // std::vector<int> v = {1, 2, 3, -4}; 00185 // std::string s = absl::StrJoin(v, "-"); 00186 // EXPECT_EQ("1-2-3--4", s); 00187 // 00188 // Example 4: 00189 // // Joins a collection of pointer-to-int. By default, pointers are 00190 // // dereferenced and the pointee is formatted using the default format for 00191 // // that type; such dereferencing occurs for all levels of indirection, so 00192 // // this pattern works just as well for `std::vector<int**>` as for 00193 // // `std::vector<int*>`. 00194 // int x = 1, y = 2, z = 3; 00195 // std::vector<int*> v = {&x, &y, &z}; 00196 // std::string s = absl::StrJoin(v, "-"); 00197 // EXPECT_EQ("1-2-3", s); 00198 // 00199 // Example 5: 00200 // // Dereferencing of `std::unique_ptr<>` is also supported: 00201 // std::vector<std::unique_ptr<int>> v 00202 // v.emplace_back(new int(1)); 00203 // v.emplace_back(new int(2)); 00204 // v.emplace_back(new int(3)); 00205 // std::string s = absl::StrJoin(v, "-"); 00206 // EXPECT_EQ("1-2-3", s); 00207 // 00208 // Example 6: 00209 // // Joins a `std::map`, with each key-value pair separated by an equals 00210 // // sign. This pattern would also work with, say, a 00211 // // `std::vector<std::pair<>>`. 00212 // std::map<std::string, int> m = { 00213 // std::make_pair("a", 1), 00214 // std::make_pair("b", 2), 00215 // std::make_pair("c", 3)}; 00216 // std::string s = absl::StrJoin(m, ",", absl::PairFormatter("=")); 00217 // EXPECT_EQ("a=1,b=2,c=3", s); 00218 // 00219 // Example 7: 00220 // // These examples show how `absl::StrJoin()` handles a few common edge 00221 // // cases: 00222 // std::vector<std::string> v_empty; 00223 // EXPECT_EQ("", absl::StrJoin(v_empty, "-")); 00224 // 00225 // std::vector<std::string> v_one_item = {"foo"}; 00226 // EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-")); 00227 // 00228 // std::vector<std::string> v_empty_string = {""}; 00229 // EXPECT_EQ("", absl::StrJoin(v_empty_string, "-")); 00230 // 00231 // std::vector<std::string> v_one_item_empty_string = {"a", ""}; 00232 // EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-")); 00233 // 00234 // std::vector<std::string> v_two_empty_string = {"", ""}; 00235 // EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-")); 00236 // 00237 // Example 8: 00238 // // Joins a `std::tuple<T...>` of heterogeneous types, converting each to 00239 // // a std::string using the `absl::AlphaNum` class. 00240 // std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-"); 00241 // EXPECT_EQ("123-abc-0.456", s); 00242 00243 template <typename Iterator, typename Formatter> 00244 std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, 00245 Formatter&& fmt) { 00246 return strings_internal::JoinAlgorithm(start, end, sep, fmt); 00247 } 00248 00249 template <typename Range, typename Formatter> 00250 std::string StrJoin(const Range& range, absl::string_view separator, 00251 Formatter&& fmt) { 00252 return strings_internal::JoinRange(range, separator, fmt); 00253 } 00254 00255 template <typename T, typename Formatter> 00256 std::string StrJoin(std::initializer_list<T> il, absl::string_view separator, 00257 Formatter&& fmt) { 00258 return strings_internal::JoinRange(il, separator, fmt); 00259 } 00260 00261 template <typename... T, typename Formatter> 00262 std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator, 00263 Formatter&& fmt) { 00264 return strings_internal::JoinAlgorithm(value, separator, fmt); 00265 } 00266 00267 template <typename Iterator> 00268 std::string StrJoin(Iterator start, Iterator end, absl::string_view separator) { 00269 return strings_internal::JoinRange(start, end, separator); 00270 } 00271 00272 template <typename Range> 00273 std::string StrJoin(const Range& range, absl::string_view separator) { 00274 return strings_internal::JoinRange(range, separator); 00275 } 00276 00277 template <typename T> 00278 std::string StrJoin(std::initializer_list<T> il, absl::string_view separator) { 00279 return strings_internal::JoinRange(il, separator); 00280 } 00281 00282 template <typename... T> 00283 std::string StrJoin(const std::tuple<T...>& value, 00284 absl::string_view separator) { 00285 return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter()); 00286 } 00287 00288 } // namespace absl 00289 00290 #endif // ABSL_STRINGS_STR_JOIN_H_