1e53c461bSKonstantin Varlamov //===----------------------------------------------------------------------===//
2e53c461bSKonstantin Varlamov //
3e53c461bSKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e53c461bSKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information.
5e53c461bSKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e53c461bSKonstantin Varlamov //
7e53c461bSKonstantin Varlamov //===----------------------------------------------------------------------===//
8e53c461bSKonstantin Varlamov
9e53c461bSKonstantin Varlamov // UNSUPPORTED: c++03, c++11, c++14, c++17
10e53c461bSKonstantin Varlamov
11e53c461bSKonstantin Varlamov // template <class View, class Pattern>
12e53c461bSKonstantin Varlamov // class std::ranges::lazy_split_view;
13e53c461bSKonstantin Varlamov //
14e53c461bSKonstantin Varlamov // These test check the output `lazy_split_view` produces for a variety of inputs, including many corner cases, with no
15e53c461bSKonstantin Varlamov // restrictions on which member functions can be called.
16e53c461bSKonstantin Varlamov
17e53c461bSKonstantin Varlamov #include <ranges>
18e53c461bSKonstantin Varlamov
19e53c461bSKonstantin Varlamov #include <algorithm>
20e53c461bSKonstantin Varlamov #include <array>
21e53c461bSKonstantin Varlamov #include <cassert>
22aeecef08SLouis Dionne #include <concepts>
23e53c461bSKonstantin Varlamov #include <map>
24e53c461bSKonstantin Varlamov #include <string_view>
25aeecef08SLouis Dionne #include <string>
26e53c461bSKonstantin Varlamov #include <utility>
27e53c461bSKonstantin Varlamov #include <vector>
28e53c461bSKonstantin Varlamov #include "types.h"
29e53c461bSKonstantin Varlamov
30aeecef08SLouis Dionne // Basic utility to convert a range to a string-like type. This handles ranges
31aeecef08SLouis Dionne // that do not contain character types and can work with non-contiguous inputs.
32ae2ae84fSJoe Loser template <class Char>
33ae2ae84fSJoe Loser class BasicSmallString {
34aeecef08SLouis Dionne std::vector<Char> buffer_{};
35ae2ae84fSJoe Loser
36ae2ae84fSJoe Loser public:
BasicSmallString(std::basic_string_view<Char> v)37aeecef08SLouis Dionne constexpr BasicSmallString(std::basic_string_view<Char> v)
38aeecef08SLouis Dionne requires (std::same_as<Char, char> ||
39aeecef08SLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
40aeecef08SLouis Dionne std::same_as<Char, wchar_t> ||
41aeecef08SLouis Dionne #endif
42aeecef08SLouis Dionne std::same_as<Char, char8_t> ||
43aeecef08SLouis Dionne std::same_as<Char, char16_t> ||
44aeecef08SLouis Dionne std::same_as<Char, char32_t>)
45aeecef08SLouis Dionne : buffer_(v.begin(), v.end())
46aeecef08SLouis Dionne {}
47ae2ae84fSJoe Loser
48ae2ae84fSJoe Loser template <class I, class S>
BasicSmallString(I b,const S & e)49ae2ae84fSJoe Loser constexpr BasicSmallString(I b, const S& e) {
50ae2ae84fSJoe Loser for (; b != e; ++b) {
51aeecef08SLouis Dionne buffer_.push_back(*b);
52ae2ae84fSJoe Loser }
53ae2ae84fSJoe Loser }
54ae2ae84fSJoe Loser
55ae2ae84fSJoe Loser template <std::ranges::range R>
BasicSmallString(R && from)56ae2ae84fSJoe Loser constexpr BasicSmallString(R&& from) : BasicSmallString(from.begin(), from.end()) {}
57ae2ae84fSJoe Loser
operator ==(const BasicSmallString & lhs,const BasicSmallString & rhs)58ae2ae84fSJoe Loser friend constexpr bool operator==(const BasicSmallString& lhs, const BasicSmallString& rhs) {
59ae2ae84fSJoe Loser return lhs.buffer_ == rhs.buffer_;
60ae2ae84fSJoe Loser }
61ae2ae84fSJoe Loser };
62ae2ae84fSJoe Loser
63e53c461bSKonstantin Varlamov template <std::ranges::view View, std::ranges::range Expected>
is_equal(View & view,const Expected & expected)64e53c461bSKonstantin Varlamov constexpr bool is_equal(View& view, const Expected& expected) {
65e53c461bSKonstantin Varlamov using Char = std::ranges::range_value_t<std::ranges::range_value_t<View>>;
66e53c461bSKonstantin Varlamov using Str = BasicSmallString<Char>;
67e53c461bSKonstantin Varlamov
68e53c461bSKonstantin Varlamov auto actual_it = view.begin();
69e53c461bSKonstantin Varlamov auto expected_it = expected.begin();
70e53c461bSKonstantin Varlamov for (; actual_it != view.end() && expected_it != expected.end(); ++actual_it, ++expected_it) {
71e53c461bSKonstantin Varlamov if (Str(*actual_it) != Str(*expected_it))
72e53c461bSKonstantin Varlamov return false;
73e53c461bSKonstantin Varlamov }
74e53c461bSKonstantin Varlamov
75e53c461bSKonstantin Varlamov return actual_it == view.end() && expected_it == expected.end();
76e53c461bSKonstantin Varlamov }
77e53c461bSKonstantin Varlamov
78*fb855eb9SMark de Wever template <class T, class Separator, class U, std::size_t M>
test_function_call(T && input,Separator && separator,std::array<U,M> expected)79e53c461bSKonstantin Varlamov constexpr bool test_function_call(T&& input, Separator&& separator, std::array<U, M> expected) {
80e53c461bSKonstantin Varlamov std::ranges::lazy_split_view v(input, separator);
81e53c461bSKonstantin Varlamov return is_equal(v, expected);
82e53c461bSKonstantin Varlamov }
83e53c461bSKonstantin Varlamov
84*fb855eb9SMark de Wever template <class T, class Separator, class U, std::size_t M>
test_with_piping(T && input,Separator && separator,std::array<U,M> expected)85e53c461bSKonstantin Varlamov constexpr bool test_with_piping(T&& input, Separator&& separator, std::array<U, M> expected) {
86e53c461bSKonstantin Varlamov auto expected_it = expected.begin();
87e53c461bSKonstantin Varlamov for (auto e : input | std::ranges::views::lazy_split(separator)) {
88e53c461bSKonstantin Varlamov if (expected_it == expected.end())
89e53c461bSKonstantin Varlamov return false;
90ae2ae84fSJoe Loser if (!std::ranges::equal(e, *expected_it))
91e53c461bSKonstantin Varlamov return false;
92e53c461bSKonstantin Varlamov
93e53c461bSKonstantin Varlamov ++expected_it;
94e53c461bSKonstantin Varlamov }
95e53c461bSKonstantin Varlamov
96e53c461bSKonstantin Varlamov return expected_it == expected.end();
97e53c461bSKonstantin Varlamov }
98e53c461bSKonstantin Varlamov
test_l_r_values()99e53c461bSKonstantin Varlamov constexpr bool test_l_r_values() {
100e53c461bSKonstantin Varlamov using namespace std::string_view_literals;
101e53c461bSKonstantin Varlamov
102e53c461bSKonstantin Varlamov // Both lvalues and rvalues can be used as input.
103e53c461bSKonstantin Varlamov {
104e53c461bSKonstantin Varlamov // Lvalues.
105e53c461bSKonstantin Varlamov {
106e53c461bSKonstantin Varlamov auto input = "abc"sv;
107e53c461bSKonstantin Varlamov auto sep = " "sv;
108e53c461bSKonstantin Varlamov [[maybe_unused]] std::ranges::lazy_split_view v(input, sep);
109e53c461bSKonstantin Varlamov }
110e53c461bSKonstantin Varlamov
111e53c461bSKonstantin Varlamov // Const lvalues.
112e53c461bSKonstantin Varlamov {
113e53c461bSKonstantin Varlamov const auto input = "abc"sv;
114e53c461bSKonstantin Varlamov const auto sep = " "sv;
115e53c461bSKonstantin Varlamov [[maybe_unused]] std::ranges::lazy_split_view v(input, sep);
116e53c461bSKonstantin Varlamov }
117e53c461bSKonstantin Varlamov
118e53c461bSKonstantin Varlamov // Rvalues.
119e53c461bSKonstantin Varlamov {
120e53c461bSKonstantin Varlamov auto input = "abc"sv;
121e53c461bSKonstantin Varlamov auto sep = " "sv;
122e53c461bSKonstantin Varlamov [[maybe_unused]] std::ranges::lazy_split_view v(std::move(input), std::move(sep));
123e53c461bSKonstantin Varlamov }
124e53c461bSKonstantin Varlamov
125e53c461bSKonstantin Varlamov // Const rvalues.
126e53c461bSKonstantin Varlamov {
127e53c461bSKonstantin Varlamov const auto input = "abc"sv;
128e53c461bSKonstantin Varlamov const auto sep = " "sv;
129e53c461bSKonstantin Varlamov [[maybe_unused]] std::ranges::lazy_split_view v(std::move(input), std::move(sep));
130e53c461bSKonstantin Varlamov }
131e53c461bSKonstantin Varlamov }
132e53c461bSKonstantin Varlamov
133e53c461bSKonstantin Varlamov return true;
134e53c461bSKonstantin Varlamov }
135e53c461bSKonstantin Varlamov
test_string_literal_separator()136e53c461bSKonstantin Varlamov constexpr bool test_string_literal_separator() {
137e53c461bSKonstantin Varlamov using namespace std::string_view_literals;
138e53c461bSKonstantin Varlamov
139e53c461bSKonstantin Varlamov // Splitting works as expected when the separator is a single character literal.
140e53c461bSKonstantin Varlamov {
141e53c461bSKonstantin Varlamov std::ranges::lazy_split_view v("abc def"sv, ' ');
142e53c461bSKonstantin Varlamov assert(is_equal(v, std::array{"abc"sv, "def"sv}));
143e53c461bSKonstantin Varlamov }
144e53c461bSKonstantin Varlamov
145e53c461bSKonstantin Varlamov // Counterintuitively, a seemingly equivalent separator expressed as a string literal doesn't match anything. This is
146e53c461bSKonstantin Varlamov // because of the implicit terminating null in the literal.
147e53c461bSKonstantin Varlamov {
148e53c461bSKonstantin Varlamov std::ranges::lazy_split_view v("abc def"sv, " ");
149e53c461bSKonstantin Varlamov assert(is_equal(v, std::array{"abc def"sv}));
150e53c461bSKonstantin Varlamov }
151e53c461bSKonstantin Varlamov
152e53c461bSKonstantin Varlamov // To illustrate the previous point further, the separator is actually a two-character string literal: `{' ', '\0'}`.
153e53c461bSKonstantin Varlamov // Should the input string contain that two-character sequence, the separator would match.
154e53c461bSKonstantin Varlamov {
155e53c461bSKonstantin Varlamov std::ranges::lazy_split_view v("abc \0def"sv, " ");
156e53c461bSKonstantin Varlamov assert(is_equal(v, std::array{"abc"sv, "def"sv}));
157e53c461bSKonstantin Varlamov }
158e53c461bSKonstantin Varlamov
159e53c461bSKonstantin Varlamov return true;
160e53c461bSKonstantin Varlamov }
161e53c461bSKonstantin Varlamov
162e53c461bSKonstantin Varlamov // Make sure that a string literal and a `string_view` produce the same results (which isn't always the case, see
163e53c461bSKonstantin Varlamov // below).
164e53c461bSKonstantin Varlamov template <class T>
sv(T && str)165e53c461bSKonstantin Varlamov constexpr std::string_view sv(T&& str) {
166e53c461bSKonstantin Varlamov return std::string_view(str);
167e53c461bSKonstantin Varlamov };
168e53c461bSKonstantin Varlamov
169*fb855eb9SMark de Wever template <class T, class Separator, class U, std::size_t M>
test_one(T && input,Separator && separator,std::array<U,M> expected)170e53c461bSKonstantin Varlamov constexpr void test_one(T&& input, Separator&& separator, std::array<U, M> expected) {
171e53c461bSKonstantin Varlamov assert(test_function_call(input, separator, expected));
172e53c461bSKonstantin Varlamov assert(test_with_piping(input, separator, expected));
173e53c461bSKonstantin Varlamov
174e53c461bSKonstantin Varlamov // In addition to the `(ForwardView, ForwardView)` case, test the `(ForwardView, tiny-range)` and `(InputView,
175e53c461bSKonstantin Varlamov // tiny-range)` cases (all of which have unique code paths).
176e53c461bSKonstantin Varlamov if constexpr (std::is_same_v<std::remove_reference_t<Separator>, char>) {
177e53c461bSKonstantin Varlamov assert(test_function_call(CopyableView(input), ForwardTinyView(separator), expected));
178e53c461bSKonstantin Varlamov assert(test_with_piping(CopyableView(input), ForwardTinyView(separator), expected));
179e53c461bSKonstantin Varlamov
180e53c461bSKonstantin Varlamov assert(test_function_call(InputView(input), ForwardTinyView(separator), expected));
181e53c461bSKonstantin Varlamov assert(test_with_piping(InputView(input), ForwardTinyView(separator), expected));
182e53c461bSKonstantin Varlamov }
183e53c461bSKonstantin Varlamov }
184e53c461bSKonstantin Varlamov
test_string_literals()185e53c461bSKonstantin Varlamov constexpr bool test_string_literals() {
186e53c461bSKonstantin Varlamov // These tests show characteristic examples of how using string literals with `lazy_split_view` produces unexpected
187e53c461bSKonstantin Varlamov // results due to the implicit terminating null that is treated as part of the range.
188e53c461bSKonstantin Varlamov
189e53c461bSKonstantin Varlamov using namespace std::string_view_literals;
190e53c461bSKonstantin Varlamov
191e53c461bSKonstantin Varlamov char short_sep = ' ';
192e53c461bSKonstantin Varlamov auto long_sep = "12"sv;
193e53c461bSKonstantin Varlamov
194e53c461bSKonstantin Varlamov // When splitting a string literal, only the last segment will be null-terminated (getting the terminating null from
195e53c461bSKonstantin Varlamov // the original range).
196e53c461bSKonstantin Varlamov {
197e53c461bSKonstantin Varlamov std::array expected = {"abc"sv, std::string_view("def", sizeof("def"))};
198e53c461bSKonstantin Varlamov
199e53c461bSKonstantin Varlamov assert(test_function_call("abc def", short_sep, expected));
200e53c461bSKonstantin Varlamov assert(test_with_piping("abc def", short_sep, expected));
201e53c461bSKonstantin Varlamov assert(test_function_call("abc12def", long_sep, expected));
202e53c461bSKonstantin Varlamov assert(test_with_piping("abc12def", long_sep, expected));
203e53c461bSKonstantin Varlamov }
204e53c461bSKonstantin Varlamov
205e53c461bSKonstantin Varlamov // Empty string.
206e53c461bSKonstantin Varlamov {
207e53c461bSKonstantin Varlamov // Because an empty string literal contains an implicit terminating null, the output will contain one segment.
208e53c461bSKonstantin Varlamov std::array expected = {std::string_view("", 1)};
209e53c461bSKonstantin Varlamov
210e53c461bSKonstantin Varlamov assert(test_function_call("", short_sep, expected));
211e53c461bSKonstantin Varlamov assert(test_with_piping("", short_sep, expected));
212e53c461bSKonstantin Varlamov assert(test_function_call("", long_sep, expected));
213e53c461bSKonstantin Varlamov assert(test_with_piping("", long_sep, expected));
214e53c461bSKonstantin Varlamov }
215e53c461bSKonstantin Varlamov
216e53c461bSKonstantin Varlamov // Terminating null in the separator -- the character literal `' '` and the seemingly equivalent string literal `" "`
217e53c461bSKonstantin Varlamov // are treated differently due to the presence of an implicit `\0` in the latter.
218e53c461bSKonstantin Varlamov {
219e53c461bSKonstantin Varlamov const char input[] = "abc def";
220e53c461bSKonstantin Varlamov std::array expected_unsplit = {std::string_view(input, sizeof(input))};
221e53c461bSKonstantin Varlamov std::array expected_split = {"abc"sv, std::string_view("def", sizeof("def"))};
222e53c461bSKonstantin Varlamov
223e53c461bSKonstantin Varlamov assert(test_function_call(input, " ", expected_unsplit));
224e53c461bSKonstantin Varlamov assert(test_function_call("abc \0def", " ", expected_split));
225e53c461bSKonstantin Varlamov // Note: string literals don't work with piping because arrays decay to pointers, and pointers don't model `range`.
226e53c461bSKonstantin Varlamov }
227e53c461bSKonstantin Varlamov
228e53c461bSKonstantin Varlamov // Empty separator.
229e53c461bSKonstantin Varlamov {
230e53c461bSKonstantin Varlamov auto empty_sep = ""sv;
231e53c461bSKonstantin Varlamov std::array expected = {"a"sv, "b"sv, "c"sv, "\0"sv};
232e53c461bSKonstantin Varlamov
233e53c461bSKonstantin Varlamov assert(test_function_call("abc", empty_sep, expected));
234e53c461bSKonstantin Varlamov assert(test_with_piping("abc", empty_sep, expected));
235e53c461bSKonstantin Varlamov }
236e53c461bSKonstantin Varlamov
237e53c461bSKonstantin Varlamov return true;
238e53c461bSKonstantin Varlamov }
239e53c461bSKonstantin Varlamov
test_nontrivial_characters()240e53c461bSKonstantin Varlamov bool test_nontrivial_characters() {
241e53c461bSKonstantin Varlamov // Try a deliberately heavyweight "character" type to see if it triggers any corner cases.
242e53c461bSKonstantin Varlamov
243e53c461bSKonstantin Varlamov using Map = std::map<std::string, int>;
244e53c461bSKonstantin Varlamov using Vec = std::vector<Map>;
245e53c461bSKonstantin Varlamov
246e53c461bSKonstantin Varlamov Map sep = {{"yyy", 999}};
247e53c461bSKonstantin Varlamov Map m1 = {
248e53c461bSKonstantin Varlamov {"a", 1},
249e53c461bSKonstantin Varlamov {"bc", 2},
250e53c461bSKonstantin Varlamov };
251e53c461bSKonstantin Varlamov Map m2 = {
252e53c461bSKonstantin Varlamov {"def", 3},
253e53c461bSKonstantin Varlamov };
254e53c461bSKonstantin Varlamov Map m3 = {
255e53c461bSKonstantin Varlamov {"g", 4},
256e53c461bSKonstantin Varlamov {"hijk", 5},
257e53c461bSKonstantin Varlamov };
258e53c461bSKonstantin Varlamov
259e53c461bSKonstantin Varlamov Vec expected1 = {m1, m2};
260e53c461bSKonstantin Varlamov Vec expected2 = {m3};
261e53c461bSKonstantin Varlamov
262e53c461bSKonstantin Varlamov std::ranges::lazy_split_view v(Vec{m1, m2, sep, m3}, sep);
263e53c461bSKonstantin Varlamov
264e53c461bSKonstantin Varlamov // Segment 1: {m1, m2}
265e53c461bSKonstantin Varlamov auto outer = v.begin();
266e53c461bSKonstantin Varlamov assert(outer != v.end());
267e53c461bSKonstantin Varlamov auto inner = (*outer).begin();
268e53c461bSKonstantin Varlamov assert(*inner++ == m1);
269e53c461bSKonstantin Varlamov assert(*inner++ == m2);
270e53c461bSKonstantin Varlamov assert(inner == (*outer).end());
271e53c461bSKonstantin Varlamov
272e53c461bSKonstantin Varlamov // Segment 2: {m3}
273e53c461bSKonstantin Varlamov ++outer;
274e53c461bSKonstantin Varlamov assert(outer != v.end());
275e53c461bSKonstantin Varlamov inner = (*outer).begin();
276e53c461bSKonstantin Varlamov assert(*inner++ == m3);
277e53c461bSKonstantin Varlamov assert(inner == (*outer).end());
278e53c461bSKonstantin Varlamov
279e53c461bSKonstantin Varlamov ++outer;
280e53c461bSKonstantin Varlamov assert(outer == v.end());
281e53c461bSKonstantin Varlamov
282e53c461bSKonstantin Varlamov return true;
283e53c461bSKonstantin Varlamov }
284e53c461bSKonstantin Varlamov
main_test()285e53c461bSKonstantin Varlamov constexpr bool main_test() {
286e53c461bSKonstantin Varlamov using namespace std::string_view_literals;
287e53c461bSKonstantin Varlamov
288e53c461bSKonstantin Varlamov char short_sep = ' ';
289e53c461bSKonstantin Varlamov auto long_sep = "12"sv;
290e53c461bSKonstantin Varlamov
291e53c461bSKonstantin Varlamov // One separator.
292e53c461bSKonstantin Varlamov {
293e53c461bSKonstantin Varlamov std::array expected = {"abc"sv, "def"sv};
294e53c461bSKonstantin Varlamov test_one("abc def"sv, short_sep, expected);
295e53c461bSKonstantin Varlamov test_one("abc12def"sv, long_sep, expected);
296e53c461bSKonstantin Varlamov }
297e53c461bSKonstantin Varlamov
298e53c461bSKonstantin Varlamov // Several separators in a row.
299e53c461bSKonstantin Varlamov {
300e53c461bSKonstantin Varlamov std::array expected = {"abc"sv, ""sv, ""sv, ""sv, "def"sv};
301e53c461bSKonstantin Varlamov test_one("abc def"sv, short_sep, expected);
302e53c461bSKonstantin Varlamov test_one("abc12121212def"sv, long_sep, expected);
303e53c461bSKonstantin Varlamov }
304e53c461bSKonstantin Varlamov
305e53c461bSKonstantin Varlamov // Trailing separator.
306e53c461bSKonstantin Varlamov {
307e53c461bSKonstantin Varlamov std::array expected = {"abc"sv, "def"sv, ""sv};
308e53c461bSKonstantin Varlamov test_one("abc def "sv, short_sep, expected);
309e53c461bSKonstantin Varlamov test_one("abc12def12"sv, long_sep, expected);
310e53c461bSKonstantin Varlamov }
311e53c461bSKonstantin Varlamov
312e53c461bSKonstantin Varlamov // Leading separator.
313e53c461bSKonstantin Varlamov {
314e53c461bSKonstantin Varlamov std::array expected = {""sv, "abc"sv, "def"sv};
315e53c461bSKonstantin Varlamov test_one(" abc def"sv, short_sep, expected);
316e53c461bSKonstantin Varlamov test_one("12abc12def"sv, long_sep, expected);
317e53c461bSKonstantin Varlamov }
318e53c461bSKonstantin Varlamov
319e53c461bSKonstantin Varlamov // No separator.
320e53c461bSKonstantin Varlamov {
321e53c461bSKonstantin Varlamov std::array expected = {"abc"sv};
322e53c461bSKonstantin Varlamov test_one("abc"sv, short_sep, expected);
323e53c461bSKonstantin Varlamov test_one("abc"sv, long_sep, expected);
324e53c461bSKonstantin Varlamov }
325e53c461bSKonstantin Varlamov
326e53c461bSKonstantin Varlamov // Input consisting of a single separator.
327e53c461bSKonstantin Varlamov {
328e53c461bSKonstantin Varlamov std::array expected = {""sv, ""sv};
329e53c461bSKonstantin Varlamov test_one(" "sv, short_sep, expected);
330e53c461bSKonstantin Varlamov test_one("12"sv, long_sep, expected);
331e53c461bSKonstantin Varlamov }
332e53c461bSKonstantin Varlamov
333e53c461bSKonstantin Varlamov // Input consisting of only separators.
334e53c461bSKonstantin Varlamov {
335e53c461bSKonstantin Varlamov std::array expected = {""sv, ""sv, ""sv, ""sv};
336e53c461bSKonstantin Varlamov test_one(" "sv, short_sep, expected);
337e53c461bSKonstantin Varlamov test_one("121212"sv, long_sep, expected);
338e53c461bSKonstantin Varlamov }
339e53c461bSKonstantin Varlamov
340e53c461bSKonstantin Varlamov // The separator and the string use the same character only.
341e53c461bSKonstantin Varlamov {
342e53c461bSKonstantin Varlamov auto overlapping_sep = "aaa"sv;
343e53c461bSKonstantin Varlamov std::array expected = {""sv, "aa"sv};
344e53c461bSKonstantin Varlamov test_one("aaaaa"sv, overlapping_sep, expected);
345e53c461bSKonstantin Varlamov }
346e53c461bSKonstantin Varlamov
347e53c461bSKonstantin Varlamov // Many redundant separators.
348e53c461bSKonstantin Varlamov {
349e53c461bSKonstantin Varlamov std::array expected = {""sv, ""sv, "abc"sv, ""sv, ""sv, "def"sv, ""sv, ""sv};
350e53c461bSKonstantin Varlamov test_one(" abc def "sv, short_sep, expected);
351e53c461bSKonstantin Varlamov test_one("1212abc121212def1212"sv, long_sep, expected);
352e53c461bSKonstantin Varlamov }
353e53c461bSKonstantin Varlamov
354e53c461bSKonstantin Varlamov // Separators after every character.
355e53c461bSKonstantin Varlamov {
356e53c461bSKonstantin Varlamov std::array expected = {""sv, "a"sv, "b"sv, "c"sv, ""sv};
357e53c461bSKonstantin Varlamov test_one(" a b c "sv, short_sep, expected);
358e53c461bSKonstantin Varlamov test_one("12a12b12c12"sv, long_sep, expected);
359e53c461bSKonstantin Varlamov }
360e53c461bSKonstantin Varlamov
361e53c461bSKonstantin Varlamov // Overlap between the separator and the string (see https://wg21.link/lwg3505).
362e53c461bSKonstantin Varlamov {
363e53c461bSKonstantin Varlamov auto overlapping_sep = "ab"sv;
364e53c461bSKonstantin Varlamov std::array expected = {"a"sv, "aa"sv, ""sv, "b"sv};
365e53c461bSKonstantin Varlamov test_one("aabaaababb"sv, overlapping_sep, expected);
366e53c461bSKonstantin Varlamov }
367e53c461bSKonstantin Varlamov
368e53c461bSKonstantin Varlamov // Empty input.
369e53c461bSKonstantin Varlamov {
370e53c461bSKonstantin Varlamov std::array<std::string_view, 0> expected = {};
371e53c461bSKonstantin Varlamov test_one(""sv, short_sep, expected);
372e53c461bSKonstantin Varlamov test_one(""sv, long_sep, expected);
373e53c461bSKonstantin Varlamov }
374e53c461bSKonstantin Varlamov
375e53c461bSKonstantin Varlamov // Empty separator.
376e53c461bSKonstantin Varlamov {
377e53c461bSKonstantin Varlamov auto empty_sep = ""sv;
378e53c461bSKonstantin Varlamov std::array expected = {"a"sv, "b"sv, "c"sv};
379e53c461bSKonstantin Varlamov test_one("abc"sv, empty_sep, expected);
380e53c461bSKonstantin Varlamov test_one("abc"sv, empty_sep, expected);
381e53c461bSKonstantin Varlamov }
382e53c461bSKonstantin Varlamov
383e53c461bSKonstantin Varlamov // Terminating null as a separator.
384e53c461bSKonstantin Varlamov {
385e53c461bSKonstantin Varlamov std::array expected = {"abc"sv, "def"sv};
386e53c461bSKonstantin Varlamov test_one("abc\0def"sv, '\0', expected);
387e53c461bSKonstantin Varlamov test_one("abc\0\0def"sv, "\0\0"sv, expected);
388e53c461bSKonstantin Varlamov }
389e53c461bSKonstantin Varlamov
390e53c461bSKonstantin Varlamov // Different character types.
391e53c461bSKonstantin Varlamov {
392e53c461bSKonstantin Varlamov // `char`.
393e53c461bSKonstantin Varlamov test_function_call("abc def", ' ', std::array{"abc", "def"});
394e53c461bSKonstantin Varlamov #ifndef TEST_HAS_NO_WIDE_CHARACTERS
395e53c461bSKonstantin Varlamov // `wchar_t`.
396e53c461bSKonstantin Varlamov test_function_call(L"abc def", L' ', std::array{L"abc", L"def"});
397e53c461bSKonstantin Varlamov #endif
398e53c461bSKonstantin Varlamov // `char8_t`.
399e53c461bSKonstantin Varlamov test_function_call(u8"abc def", u8' ', std::array{u8"abc", u8"def"});
400e53c461bSKonstantin Varlamov // `char16_t`.
401e53c461bSKonstantin Varlamov test_function_call(u"abc def", u' ', std::array{u"abc", u"def"});
402e53c461bSKonstantin Varlamov // `char32_t`.
403e53c461bSKonstantin Varlamov test_function_call(U"abc def", U' ', std::array{U"abc", U"def"});
404e53c461bSKonstantin Varlamov }
405e53c461bSKonstantin Varlamov
406e53c461bSKonstantin Varlamov // Non-character input.
407e53c461bSKonstantin Varlamov {
408e53c461bSKonstantin Varlamov std::array expected = {std::array{1, 2, 3}, std::array{4, 5, 6}};
409e53c461bSKonstantin Varlamov test_one(std::array{1, 2, 3, 0, 4, 5, 6}, 0, expected);
410e53c461bSKonstantin Varlamov test_one(std::array{1, 2, 3, 0, 0, 0, 4, 5, 6}, std::array{0, 0, 0}, expected);
411e53c461bSKonstantin Varlamov }
412e53c461bSKonstantin Varlamov
413e53c461bSKonstantin Varlamov return true;
414e53c461bSKonstantin Varlamov }
415e53c461bSKonstantin Varlamov
416e53c461bSKonstantin Varlamov int main(int, char**) {
417e53c461bSKonstantin Varlamov main_test();
418e53c461bSKonstantin Varlamov static_assert(main_test());
419e53c461bSKonstantin Varlamov
420e53c461bSKonstantin Varlamov test_string_literals();
421e53c461bSKonstantin Varlamov static_assert(test_string_literals());
422e53c461bSKonstantin Varlamov
423e53c461bSKonstantin Varlamov test_l_r_values();
424e53c461bSKonstantin Varlamov static_assert(test_l_r_values());
425e53c461bSKonstantin Varlamov
426e53c461bSKonstantin Varlamov test_string_literal_separator();
427e53c461bSKonstantin Varlamov static_assert(test_string_literal_separator());
428e53c461bSKonstantin Varlamov
429e53c461bSKonstantin Varlamov // Note: map is not `constexpr`, so this test is runtime-only.
430e53c461bSKonstantin Varlamov test_nontrivial_characters();
431e53c461bSKonstantin Varlamov
432e53c461bSKonstantin Varlamov return 0;
433e53c461bSKonstantin Varlamov }
434