str_join.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. //
  2. // Copyright 2017 The Abseil Authors.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // https://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. // -----------------------------------------------------------------------------
  17. // File: str_join.h
  18. // -----------------------------------------------------------------------------
  19. //
  20. // This header file contains functions for joining a range of elements and
  21. // returning the result as a std::string. StrJoin operations are specified by
  22. // passing a range, a separator string to use between the elements joined, and
  23. // an optional Formatter responsible for converting each argument in the range
  24. // to a string. If omitted, a default `AlphaNumFormatter()` is called on the
  25. // elements to be joined, using the same formatting that `absl::StrCat()` uses.
  26. // This package defines a number of default formatters, and you can define your
  27. // own implementations.
  28. //
  29. // Ranges are specified by passing a container with `std::begin()` and
  30. // `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
  31. // brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous
  32. // objects. The separator string is specified as an `absl::string_view`.
  33. //
  34. // Because the default formatter uses the `absl::AlphaNum` class,
  35. // `absl::StrJoin()`, like `absl::StrCat()`, will work out-of-the-box on
  36. // collections of strings, ints, floats, doubles, etc.
  37. //
  38. // Example:
  39. //
  40. // std::vector<std::string> v = {"foo", "bar", "baz"};
  41. // std::string s = absl::StrJoin(v, "-");
  42. // EXPECT_EQ("foo-bar-baz", s);
  43. //
  44. // See comments on the `absl::StrJoin()` function for more examples.
  45. #ifndef ABSL_STRINGS_STR_JOIN_H_
  46. #define ABSL_STRINGS_STR_JOIN_H_
  47. #include <cstdio>
  48. #include <cstring>
  49. #include <initializer_list>
  50. #include <iterator>
  51. #include <string>
  52. #include <tuple>
  53. #include <type_traits>
  54. #include <utility>
  55. #include "absl/base/macros.h"
  56. #include "absl/strings/internal/str_join_internal.h"
  57. #include "absl/strings/string_view.h"
  58. namespace absl {
  59. ABSL_NAMESPACE_BEGIN
  60. // -----------------------------------------------------------------------------
  61. // Concept: Formatter
  62. // -----------------------------------------------------------------------------
  63. //
  64. // A Formatter is a function object that is responsible for formatting its
  65. // argument as a string and appending it to a given output std::string.
  66. // Formatters may be implemented as function objects, lambdas, or normal
  67. // functions. You may provide your own Formatter to enable `absl::StrJoin()` to
  68. // work with arbitrary types.
  69. //
  70. // The following is an example of a custom Formatter that uses
  71. // `absl::FormatDuration` to join a list of `absl::Duration`s.
  72. //
  73. // std::vector<absl::Duration> v = {absl::Seconds(1), absl::Milliseconds(10)};
  74. // std::string s =
  75. // absl::StrJoin(v, ", ", [](std::string* out, absl::Duration dur) {
  76. // absl::StrAppend(out, absl::FormatDuration(dur));
  77. // });
  78. // EXPECT_EQ(s, "1s, 10ms");
  79. //
  80. // The following standard formatters are provided within this file:
  81. //
  82. // - `AlphaNumFormatter()` (the default)
  83. // - `StreamFormatter()`
  84. // - `PairFormatter()`
  85. // - `DereferenceFormatter()`
  86. // AlphaNumFormatter()
  87. //
  88. // Default formatter used if none is specified. Uses `absl::AlphaNum` to convert
  89. // numeric arguments to strings.
  90. inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() {
  91. return strings_internal::AlphaNumFormatterImpl();
  92. }
  93. // StreamFormatter()
  94. //
  95. // Formats its argument using the << operator.
  96. inline strings_internal::StreamFormatterImpl StreamFormatter() {
  97. return strings_internal::StreamFormatterImpl();
  98. }
  99. // Function Template: PairFormatter(Formatter, absl::string_view, Formatter)
  100. //
  101. // Formats a `std::pair` by putting a given separator between the pair's
  102. // `.first` and `.second` members. This formatter allows you to specify
  103. // custom Formatters for both the first and second member of each pair.
  104. template <typename FirstFormatter, typename SecondFormatter>
  105. inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>
  106. PairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2) {
  107. return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>(
  108. std::move(f1), sep, std::move(f2));
  109. }
  110. // Function overload of PairFormatter() for using a default
  111. // `AlphaNumFormatter()` for each Formatter in the pair.
  112. inline strings_internal::PairFormatterImpl<
  113. strings_internal::AlphaNumFormatterImpl,
  114. strings_internal::AlphaNumFormatterImpl>
  115. PairFormatter(absl::string_view sep) {
  116. return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter());
  117. }
  118. // Function Template: DereferenceFormatter(Formatter)
  119. //
  120. // Formats its argument by dereferencing it and then applying the given
  121. // formatter. This formatter is useful for formatting a container of
  122. // pointer-to-T. This pattern often shows up when joining repeated fields in
  123. // protocol buffers.
  124. template <typename Formatter>
  125. strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
  126. Formatter&& f) {
  127. return strings_internal::DereferenceFormatterImpl<Formatter>(
  128. std::forward<Formatter>(f));
  129. }
  130. // Function overload of `DereferenceFormatter()` for using a default
  131. // `AlphaNumFormatter()`.
  132. inline strings_internal::DereferenceFormatterImpl<
  133. strings_internal::AlphaNumFormatterImpl>
  134. DereferenceFormatter() {
  135. return strings_internal::DereferenceFormatterImpl<
  136. strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter());
  137. }
  138. // -----------------------------------------------------------------------------
  139. // StrJoin()
  140. // -----------------------------------------------------------------------------
  141. //
  142. // Joins a range of elements and returns the result as a std::string.
  143. // `absl::StrJoin()` takes a range, a separator string to use between the
  144. // elements joined, and an optional Formatter responsible for converting each
  145. // argument in the range to a string.
  146. //
  147. // If omitted, the default `AlphaNumFormatter()` is called on the elements to be
  148. // joined.
  149. //
  150. // Example 1:
  151. // // Joins a collection of strings. This pattern also works with a collection
  152. // // of `absl::string_view` or even `const char*`.
  153. // std::vector<std::string> v = {"foo", "bar", "baz"};
  154. // std::string s = absl::StrJoin(v, "-");
  155. // EXPECT_EQ(s, "foo-bar-baz");
  156. //
  157. // Example 2:
  158. // // Joins the values in the given `std::initializer_list<>` specified using
  159. // // brace initialization. This pattern also works with an initializer_list
  160. // // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.
  161. // std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
  162. // EXPECT_EQs, "foo-bar-baz");
  163. //
  164. // Example 3:
  165. // // Joins a collection of ints. This pattern also works with floats,
  166. // // doubles, int64s -- any `StrCat()`-compatible type.
  167. // std::vector<int> v = {1, 2, 3, -4};
  168. // std::string s = absl::StrJoin(v, "-");
  169. // EXPECT_EQ(s, "1-2-3--4");
  170. //
  171. // Example 4:
  172. // // Joins a collection of pointer-to-int. By default, pointers are
  173. // // dereferenced and the pointee is formatted using the default format for
  174. // // that type; such dereferencing occurs for all levels of indirection, so
  175. // // this pattern works just as well for `std::vector<int**>` as for
  176. // // `std::vector<int*>`.
  177. // int x = 1, y = 2, z = 3;
  178. // std::vector<int*> v = {&x, &y, &z};
  179. // std::string s = absl::StrJoin(v, "-");
  180. // EXPECT_EQ(s, "1-2-3");
  181. //
  182. // Example 5:
  183. // // Dereferencing of `std::unique_ptr<>` is also supported:
  184. // std::vector<std::unique_ptr<int>> v
  185. // v.emplace_back(new int(1));
  186. // v.emplace_back(new int(2));
  187. // v.emplace_back(new int(3));
  188. // std::string s = absl::StrJoin(v, "-");
  189. // EXPECT_EQ(s, "1-2-3");
  190. //
  191. // Example 6:
  192. // // Joins a `std::map`, with each key-value pair separated by an equals
  193. // // sign. This pattern would also work with, say, a
  194. // // `std::vector<std::pair<>>`.
  195. // std::map<std::string, int> m = {
  196. // {"a", 1},
  197. // {"b", 2},
  198. // {"c", 3}};
  199. // std::string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
  200. // EXPECT_EQ(s, "a=1,b=2,c=3");
  201. //
  202. // Example 7:
  203. // // These examples show how `absl::StrJoin()` handles a few common edge
  204. // // cases:
  205. // std::vector<std::string> v_empty;
  206. // EXPECT_EQ(absl::StrJoin(v_empty, "-"), "");
  207. //
  208. // std::vector<std::string> v_one_item = {"foo"};
  209. // EXPECT_EQ(absl::StrJoin(v_one_item, "-"), "foo");
  210. //
  211. // std::vector<std::string> v_empty_string = {""};
  212. // EXPECT_EQ(absl::StrJoin(v_empty_string, "-"), "");
  213. //
  214. // std::vector<std::string> v_one_item_empty_string = {"a", ""};
  215. // EXPECT_EQ(absl::StrJoin(v_one_item_empty_string, "-"), "a-");
  216. //
  217. // std::vector<std::string> v_two_empty_string = {"", ""};
  218. // EXPECT_EQ(absl::StrJoin(v_two_empty_string, "-"), "-");
  219. //
  220. // Example 8:
  221. // // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
  222. // // a std::string using the `absl::AlphaNum` class.
  223. // std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
  224. // EXPECT_EQ(s, "123-abc-0.456");
  225. template <typename Iterator, typename Formatter>
  226. std::string StrJoin(Iterator start, Iterator end, absl::string_view sep,
  227. Formatter&& fmt) {
  228. return strings_internal::JoinAlgorithm(start, end, sep, fmt);
  229. }
  230. template <typename Range, typename Formatter>
  231. std::string StrJoin(const Range& range, absl::string_view separator,
  232. Formatter&& fmt) {
  233. return strings_internal::JoinRange(range, separator, fmt);
  234. }
  235. template <typename T, typename Formatter,
  236. typename = typename std::enable_if<
  237. !std::is_convertible<T, absl::string_view>::value>::type>
  238. std::string StrJoin(std::initializer_list<T> il, absl::string_view separator,
  239. Formatter&& fmt) {
  240. return strings_internal::JoinRange(il, separator, fmt);
  241. }
  242. template <typename Formatter>
  243. inline std::string StrJoin(std::initializer_list<absl::string_view> il,
  244. absl::string_view separator, Formatter&& fmt) {
  245. return strings_internal::JoinRange(il, separator, fmt);
  246. }
  247. template <typename... T, typename Formatter>
  248. std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator,
  249. Formatter&& fmt) {
  250. return strings_internal::JoinAlgorithm(value, separator, fmt);
  251. }
  252. template <typename Iterator>
  253. std::string StrJoin(Iterator start, Iterator end, absl::string_view separator) {
  254. return strings_internal::JoinRange(start, end, separator);
  255. }
  256. template <typename Range>
  257. std::string StrJoin(const Range& range, absl::string_view separator) {
  258. return strings_internal::JoinRange(range, separator);
  259. }
  260. template <typename T, typename = typename std::enable_if<!std::is_convertible<
  261. T, absl::string_view>::value>::type>
  262. std::string StrJoin(std::initializer_list<T> il, absl::string_view separator) {
  263. return strings_internal::JoinRange(il, separator);
  264. }
  265. inline std::string StrJoin(std::initializer_list<absl::string_view> il,
  266. absl::string_view separator) {
  267. return strings_internal::JoinRange(il, separator);
  268. }
  269. template <typename... T>
  270. std::string StrJoin(const std::tuple<T...>& value,
  271. absl::string_view separator) {
  272. return strings_internal::JoinTuple(value, separator,
  273. std::index_sequence_for<T...>{});
  274. }
  275. ABSL_NAMESPACE_END
  276. } // namespace absl
  277. #endif // ABSL_STRINGS_STR_JOIN_H_