You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

str_join.h 12 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. {
  60. ABSL_NAMESPACE_BEGIN
  61. // -----------------------------------------------------------------------------
  62. // Concept: Formatter
  63. // -----------------------------------------------------------------------------
  64. //
  65. // A Formatter is a function object that is responsible for formatting its
  66. // argument as a string and appending it to a given output std::string.
  67. // Formatters may be implemented as function objects, lambdas, or normal
  68. // functions. You may provide your own Formatter to enable `absl::StrJoin()` to
  69. // work with arbitrary types.
  70. //
  71. // The following is an example of a custom Formatter that uses
  72. // `absl::FormatDuration` to join a list of `absl::Duration`s.
  73. //
  74. // std::vector<absl::Duration> v = {absl::Seconds(1), absl::Milliseconds(10)};
  75. // std::string s =
  76. // absl::StrJoin(v, ", ", [](std::string* out, absl::Duration dur) {
  77. // absl::StrAppend(out, absl::FormatDuration(dur));
  78. // });
  79. // EXPECT_EQ("1s, 10ms", s);
  80. //
  81. // The following standard formatters are provided within this file:
  82. //
  83. // - `AlphaNumFormatter()` (the default)
  84. // - `StreamFormatter()`
  85. // - `PairFormatter()`
  86. // - `DereferenceFormatter()`
  87. // AlphaNumFormatter()
  88. //
  89. // Default formatter used if none is specified. Uses `absl::AlphaNum` to convert
  90. // numeric arguments to strings.
  91. inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter()
  92. {
  93. return strings_internal::AlphaNumFormatterImpl();
  94. }
  95. // StreamFormatter()
  96. //
  97. // Formats its argument using the << operator.
  98. inline strings_internal::StreamFormatterImpl StreamFormatter()
  99. {
  100. return strings_internal::StreamFormatterImpl();
  101. }
  102. // Function Template: PairFormatter(Formatter, absl::string_view, Formatter)
  103. //
  104. // Formats a `std::pair` by putting a given separator between the pair's
  105. // `.first` and `.second` members. This formatter allows you to specify
  106. // custom Formatters for both the first and second member of each pair.
  107. template<typename FirstFormatter, typename SecondFormatter>
  108. inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>
  109. PairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2)
  110. {
  111. return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>(
  112. std::move(f1), sep, std::move(f2)
  113. );
  114. }
  115. // Function overload of PairFormatter() for using a default
  116. // `AlphaNumFormatter()` for each Formatter in the pair.
  117. inline strings_internal::PairFormatterImpl<
  118. strings_internal::AlphaNumFormatterImpl,
  119. strings_internal::AlphaNumFormatterImpl>
  120. PairFormatter(absl::string_view sep)
  121. {
  122. return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter());
  123. }
  124. // Function Template: DereferenceFormatter(Formatter)
  125. //
  126. // Formats its argument by dereferencing it and then applying the given
  127. // formatter. This formatter is useful for formatting a container of
  128. // pointer-to-T. This pattern often shows up when joining repeated fields in
  129. // protocol buffers.
  130. template<typename Formatter>
  131. strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
  132. Formatter&& f
  133. )
  134. {
  135. return strings_internal::DereferenceFormatterImpl<Formatter>(
  136. std::forward<Formatter>(f)
  137. );
  138. }
  139. // Function overload of `DereferenceFormatter()` for using a default
  140. // `AlphaNumFormatter()`.
  141. inline strings_internal::DereferenceFormatterImpl<
  142. strings_internal::AlphaNumFormatterImpl>
  143. DereferenceFormatter()
  144. {
  145. return strings_internal::DereferenceFormatterImpl<
  146. strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter());
  147. }
  148. // -----------------------------------------------------------------------------
  149. // StrJoin()
  150. // -----------------------------------------------------------------------------
  151. //
  152. // Joins a range of elements and returns the result as a std::string.
  153. // `absl::StrJoin()` takes a range, a separator string to use between the
  154. // elements joined, and an optional Formatter responsible for converting each
  155. // argument in the range to a string.
  156. //
  157. // If omitted, the default `AlphaNumFormatter()` is called on the elements to be
  158. // joined.
  159. //
  160. // Example 1:
  161. // // Joins a collection of strings. This pattern also works with a collection
  162. // // of `absl::string_view` or even `const char*`.
  163. // std::vector<std::string> v = {"foo", "bar", "baz"};
  164. // std::string s = absl::StrJoin(v, "-");
  165. // EXPECT_EQ("foo-bar-baz", s);
  166. //
  167. // Example 2:
  168. // // Joins the values in the given `std::initializer_list<>` specified using
  169. // // brace initialization. This pattern also works with an initializer_list
  170. // // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.
  171. // std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
  172. // EXPECT_EQ("foo-bar-baz", s);
  173. //
  174. // Example 3:
  175. // // Joins a collection of ints. This pattern also works with floats,
  176. // // doubles, int64s -- any `StrCat()`-compatible type.
  177. // std::vector<int> v = {1, 2, 3, -4};
  178. // std::string s = absl::StrJoin(v, "-");
  179. // EXPECT_EQ("1-2-3--4", s);
  180. //
  181. // Example 4:
  182. // // Joins a collection of pointer-to-int. By default, pointers are
  183. // // dereferenced and the pointee is formatted using the default format for
  184. // // that type; such dereferencing occurs for all levels of indirection, so
  185. // // this pattern works just as well for `std::vector<int**>` as for
  186. // // `std::vector<int*>`.
  187. // int x = 1, y = 2, z = 3;
  188. // std::vector<int*> v = {&x, &y, &z};
  189. // std::string s = absl::StrJoin(v, "-");
  190. // EXPECT_EQ("1-2-3", s);
  191. //
  192. // Example 5:
  193. // // Dereferencing of `std::unique_ptr<>` is also supported:
  194. // std::vector<std::unique_ptr<int>> v
  195. // v.emplace_back(new int(1));
  196. // v.emplace_back(new int(2));
  197. // v.emplace_back(new int(3));
  198. // std::string s = absl::StrJoin(v, "-");
  199. // EXPECT_EQ("1-2-3", s);
  200. //
  201. // Example 6:
  202. // // Joins a `std::map`, with each key-value pair separated by an equals
  203. // // sign. This pattern would also work with, say, a
  204. // // `std::vector<std::pair<>>`.
  205. // std::map<std::string, int> m = {
  206. // std::make_pair("a", 1),
  207. // std::make_pair("b", 2),
  208. // std::make_pair("c", 3)};
  209. // std::string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
  210. // EXPECT_EQ("a=1,b=2,c=3", s);
  211. //
  212. // Example 7:
  213. // // These examples show how `absl::StrJoin()` handles a few common edge
  214. // // cases:
  215. // std::vector<std::string> v_empty;
  216. // EXPECT_EQ("", absl::StrJoin(v_empty, "-"));
  217. //
  218. // std::vector<std::string> v_one_item = {"foo"};
  219. // EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-"));
  220. //
  221. // std::vector<std::string> v_empty_string = {""};
  222. // EXPECT_EQ("", absl::StrJoin(v_empty_string, "-"));
  223. //
  224. // std::vector<std::string> v_one_item_empty_string = {"a", ""};
  225. // EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-"));
  226. //
  227. // std::vector<std::string> v_two_empty_string = {"", ""};
  228. // EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-"));
  229. //
  230. // Example 8:
  231. // // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
  232. // // a std::string using the `absl::AlphaNum` class.
  233. // std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
  234. // EXPECT_EQ("123-abc-0.456", s);
  235. template<typename Iterator, typename Formatter>
  236. std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, Formatter&& fmt)
  237. {
  238. return strings_internal::JoinAlgorithm(start, end, sep, fmt);
  239. }
  240. template<typename Range, typename Formatter>
  241. std::string StrJoin(const Range& range, absl::string_view separator, Formatter&& fmt)
  242. {
  243. return strings_internal::JoinRange(range, separator, fmt);
  244. }
  245. template<typename T, typename Formatter>
  246. std::string StrJoin(std::initializer_list<T> il, absl::string_view separator, Formatter&& fmt)
  247. {
  248. return strings_internal::JoinRange(il, separator, fmt);
  249. }
  250. template<typename... T, typename Formatter>
  251. std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator, Formatter&& fmt)
  252. {
  253. return strings_internal::JoinAlgorithm(value, separator, fmt);
  254. }
  255. template<typename Iterator>
  256. std::string StrJoin(Iterator start, Iterator end, absl::string_view separator)
  257. {
  258. return strings_internal::JoinRange(start, end, separator);
  259. }
  260. template<typename Range>
  261. std::string StrJoin(const Range& range, absl::string_view separator)
  262. {
  263. return strings_internal::JoinRange(range, separator);
  264. }
  265. template<typename T>
  266. std::string StrJoin(std::initializer_list<T> il, absl::string_view separator)
  267. {
  268. return strings_internal::JoinRange(il, separator);
  269. }
  270. template<typename... T>
  271. std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator)
  272. {
  273. return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
  274. }
  275. ABSL_NAMESPACE_END
  276. } // namespace absl
  277. #endif // ABSL_STRINGS_STR_JOIN_H_