Coverage Report

Created: 2023-09-25 06:27

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