1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <string>
10 
11 // template<class InputIterator>
12 //   iterator insert(const_iterator p, InputIterator first, InputIterator last); // constexpr since C++20
13 
14 #include <string>
15 #include <cassert>
16 
17 #include "test_macros.h"
18 #include "test_iterators.h"
19 #include "min_allocator.h"
20 
21 template <class S, class It>
22 TEST_CONSTEXPR_CXX20 void
test(S s,typename S::difference_type pos,It first,It last,S expected)23 test(S s, typename S::difference_type pos, It first, It last, S expected)
24 {
25     typename S::const_iterator p = s.cbegin() + pos;
26     typename S::iterator i = s.insert(p, first, last);
27     LIBCPP_ASSERT(s.__invariants());
28     assert(i - s.begin() == pos);
29     assert(s == expected);
30 }
31 
32 #ifndef TEST_HAS_NO_EXCEPTIONS
operator charWidget33 struct Widget { operator char() const { throw 42; } };
34 
35 template <class S, class It>
36 TEST_CONSTEXPR_CXX20 void
test_exceptions(S s,typename S::difference_type pos,It first,It last)37 test_exceptions(S s, typename S::difference_type pos, It first, It last)
38 {
39     typename S::const_iterator p = s.cbegin() + pos;
40 
41     S original = s;
42     typename S::iterator begin = s.begin();
43     typename S::iterator end = s.end();
44 
45     try {
46         s.insert(p, first, last);
47         assert(false);
48     } catch (...) {}
49 
50     // Part of "no effects" is that iterators and pointers
51     // into the string must not have been invalidated.
52     LIBCPP_ASSERT(s.__invariants());
53     assert(s == original);
54     assert(s.begin() == begin);
55     assert(s.end() == end);
56 }
57 #endif
58 
test()59 TEST_CONSTEXPR_CXX20 bool test() {
60   {
61     typedef std::string S;
62     const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
63     test(S(), 0, s, s, S());
64     test(S(), 0, s, s+1, S("A"));
65     test(S(), 0, s, s+10, S("ABCDEFGHIJ"));
66     test(S(), 0, s, s+52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
67 
68     test(S("12345"), 0, s, s, S("12345"));
69     test(S("12345"), 1, s, s+1, S("1A2345"));
70     test(S("12345"), 4, s, s+10, S("1234ABCDEFGHIJ5"));
71     test(S("12345"), 5, s, s+52, S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
72 
73     test(S("1234567890"), 0, s, s, S("1234567890"));
74     test(S("1234567890"), 1, s, s+1, S("1A234567890"));
75     test(S("1234567890"), 10, s, s+10, S("1234567890ABCDEFGHIJ"));
76     test(S("1234567890"), 8, s, s+52, S("12345678ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz90"));
77 
78     test(S("12345678901234567890"), 3, s, s, S("12345678901234567890"));
79     test(S("12345678901234567890"), 3, s, s+1, S("123A45678901234567890"));
80     test(S("12345678901234567890"), 15, s, s+10, S("123456789012345ABCDEFGHIJ67890"));
81     test(S("12345678901234567890"), 20, s, s+52,
82          S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
83 
84     test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
85     test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("A"));
86     test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), S("ABCDEFGHIJ"));
87     test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52), S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
88 
89     test(S("12345"), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S("12345"));
90     test(S("12345"), 1, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("1A2345"));
91     test(S("12345"), 4, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), S("1234ABCDEFGHIJ5"));
92     test(S("12345"), 5, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52), S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
93 
94     test(S("1234567890"), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S("1234567890"));
95     test(S("1234567890"), 1, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("1A234567890"));
96     test(S("1234567890"), 10, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), S("1234567890ABCDEFGHIJ"));
97     test(S("1234567890"), 8, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52), S("12345678ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz90"));
98 
99     test(S("12345678901234567890"), 3, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S("12345678901234567890"));
100     test(S("12345678901234567890"), 3, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("123A45678901234567890"));
101     test(S("12345678901234567890"), 15, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), S("123456789012345ABCDEFGHIJ67890"));
102     test(S("12345678901234567890"), 20, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
103          S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
104   }
105 #if TEST_STD_VER >= 11
106   {
107     typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
108     const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
109     test(S(), 0, s, s, S());
110     test(S(), 0, s, s+1, S("A"));
111     test(S(), 0, s, s+10, S("ABCDEFGHIJ"));
112     test(S(), 0, s, s+52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
113 
114     test(S("12345"), 0, s, s, S("12345"));
115     test(S("12345"), 1, s, s+1, S("1A2345"));
116     test(S("12345"), 4, s, s+10, S("1234ABCDEFGHIJ5"));
117     test(S("12345"), 5, s, s+52, S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
118 
119     test(S("1234567890"), 0, s, s, S("1234567890"));
120     test(S("1234567890"), 1, s, s+1, S("1A234567890"));
121     test(S("1234567890"), 10, s, s+10, S("1234567890ABCDEFGHIJ"));
122     test(S("1234567890"), 8, s, s+52, S("12345678ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz90"));
123 
124     test(S("12345678901234567890"), 3, s, s, S("12345678901234567890"));
125     test(S("12345678901234567890"), 3, s, s+1, S("123A45678901234567890"));
126     test(S("12345678901234567890"), 15, s, s+10, S("123456789012345ABCDEFGHIJ67890"));
127     test(S("12345678901234567890"), 20, s, s+52,
128          S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
129 
130     test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
131     test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("A"));
132     test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), S("ABCDEFGHIJ"));
133     test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52), S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
134 
135     test(S("12345"), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S("12345"));
136     test(S("12345"), 1, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("1A2345"));
137     test(S("12345"), 4, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), S("1234ABCDEFGHIJ5"));
138     test(S("12345"), 5, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52), S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
139 
140     test(S("1234567890"), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S("1234567890"));
141     test(S("1234567890"), 1, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("1A234567890"));
142     test(S("1234567890"), 10, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), S("1234567890ABCDEFGHIJ"));
143     test(S("1234567890"), 8, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52), S("12345678ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz90"));
144 
145     test(S("12345678901234567890"), 3, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S("12345678901234567890"));
146     test(S("12345678901234567890"), 3, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("123A45678901234567890"));
147     test(S("12345678901234567890"), 15, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), S("123456789012345ABCDEFGHIJ67890"));
148     test(S("12345678901234567890"), 20, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
149          S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
150   }
151 #endif
152 #ifndef TEST_HAS_NO_EXCEPTIONS
153   if (!TEST_IS_CONSTANT_EVALUATED) { // test iterator operations that throw
154     typedef std::string S;
155     typedef ThrowingIterator<char> TIter;
156     typedef cpp17_input_iterator<TIter> IIter;
157     const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
158     test_exceptions(S(), 0, IIter(TIter(s, s+10, 4, TIter::TAIncrement)), IIter(TIter()));
159     test_exceptions(S(), 0, IIter(TIter(s, s+10, 5, TIter::TADereference)), IIter(TIter()));
160     test_exceptions(S(), 0, IIter(TIter(s, s+10, 6, TIter::TAComparison)), IIter(TIter()));
161 
162     test_exceptions(S(), 0, TIter(s, s+10, 4, TIter::TAIncrement), TIter());
163     test_exceptions(S(), 0, TIter(s, s+10, 5, TIter::TADereference), TIter());
164     test_exceptions(S(), 0, TIter(s, s+10, 6, TIter::TAComparison), TIter());
165 
166     Widget w[100];
167     test_exceptions(S(), 0, w, w+100);
168   }
169 #endif
170 
171   { // test inserting into self
172     typedef std::string S;
173     S s_short = "123/";
174     S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
175 
176     s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
177     assert(s_short == "123/123/");
178     s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
179     assert(s_short == "123/123/123/123/");
180     s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
181     assert(s_short == "123/123/123/123/123/123/123/123/");
182 
183     s_long.insert(s_long.begin(), s_long.begin(), s_long.end());
184     assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
185   }
186 
187   { // test assigning a different type
188     typedef std::string S;
189     const uint8_t p[] = "ABCD";
190 
191     S s;
192     s.insert(s.begin(), p, p + 4);
193     assert(s == "ABCD");
194   }
195 
196   if (!TEST_IS_CONSTANT_EVALUATED) { // regression-test inserting into self in sneaky ways
197     std::string s_short = "hello";
198     std::string s_long = "Lorem ipsum dolor sit amet, consectetur/";
199     std::string s_othertype = "hello";
200     const unsigned char *first = reinterpret_cast<const unsigned char*>(s_othertype.data());
201 
202     test(s_short, 0, s_short.data() + s_short.size(), s_short.data() + s_short.size() + 1,
203          std::string("\0hello", 6));
204     test(s_long, 0, s_long.data() + s_long.size(), s_long.data() + s_long.size() + 1,
205          std::string("\0Lorem ipsum dolor sit amet, consectetur/", 41));
206     test(s_othertype, 1, first + 2, first + 5, std::string("hlloello"));
207   }
208 
209   { // test with a move iterator that returns char&&
210     typedef cpp17_input_iterator<const char*> It;
211     typedef std::move_iterator<It> MoveIt;
212     const char p[] = "ABCD";
213     std::string s;
214     s.insert(s.begin(), MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
215     assert(s == "ABCD");
216   }
217   { // test with a move iterator that returns char&&
218     typedef forward_iterator<const char*> It;
219     typedef std::move_iterator<It> MoveIt;
220     const char p[] = "ABCD";
221     std::string s;
222     s.insert(s.begin(), MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
223     assert(s == "ABCD");
224   }
225   { // test with a move iterator that returns char&&
226     typedef const char* It;
227     typedef std::move_iterator<It> MoveIt;
228     const char p[] = "ABCD";
229     std::string s;
230     s.insert(s.begin(), MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
231     assert(s == "ABCD");
232   }
233 
234   return true;
235 }
236 
main(int,char **)237 int main(int, char**)
238 {
239   test();
240 #if TEST_STD_VER > 17
241   static_assert(test());
242 #endif
243 
244   return 0;
245 }
246