xref: /llvm-project/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp (revision 9ed20568e7de53dce85f1631d7d8c1415e7930ae)
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 // basic_string(const basic_string<charT,traits,Allocator>& str,
12 //              size_type pos, size_type n,
13 //              const Allocator& a = Allocator()); // constexpr since C++20
14 //
15 // basic_string(const basic_string<charT,traits,Allocator>& str,
16 //              size_type pos,
17 //              const Allocator& a = Allocator()); // constexpr since C++20
18 
19 #include <string>
20 #include <stdexcept>
21 #include <algorithm>
22 #include <vector>
23 #include <scoped_allocator>
24 #include <cassert>
25 
26 #include "test_macros.h"
27 #include "test_allocator.h"
28 #include "min_allocator.h"
29 #include "asan_testing.h"
30 
31 template <class S>
test(S str,unsigned pos)32 TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos) {
33   typedef typename S::traits_type T;
34   typedef typename S::allocator_type A;
35 
36   if (pos <= str.size()) {
37     S s2(str, pos);
38     LIBCPP_ASSERT(s2.__invariants());
39     typename S::size_type rlen = str.size() - pos;
40     assert(s2.size() == rlen);
41     assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
42     assert(s2.get_allocator() == A());
43     assert(s2.capacity() >= s2.size());
44     LIBCPP_ASSERT(is_string_asan_correct(s2));
45   }
46 #ifndef TEST_HAS_NO_EXCEPTIONS
47   else if (!TEST_IS_CONSTANT_EVALUATED) {
48     try {
49       S s2(str, pos);
50       assert(false);
51     } catch (std::out_of_range&) {
52       assert(pos > str.size());
53     }
54   }
55 #endif
56 }
57 
58 template <class S>
test(S str,unsigned pos,unsigned n)59 TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos, unsigned n) {
60   typedef typename S::traits_type T;
61   typedef typename S::allocator_type A;
62   if (pos <= str.size()) {
63     S s2(str, pos, n);
64     LIBCPP_ASSERT(s2.__invariants());
65     typename S::size_type rlen = std::min<typename S::size_type>(str.size() - pos, n);
66     assert(s2.size() == rlen);
67     assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
68     assert(s2.get_allocator() == A());
69     assert(s2.capacity() >= s2.size());
70     LIBCPP_ASSERT(is_string_asan_correct(s2));
71   }
72 #ifndef TEST_HAS_NO_EXCEPTIONS
73   else if (!TEST_IS_CONSTANT_EVALUATED) {
74     try {
75       S s2(str, pos, n);
76       assert(false);
77     } catch (std::out_of_range&) {
78       assert(pos > str.size());
79     }
80   }
81 #endif
82 }
83 
84 template <class S>
test(S str,unsigned pos,unsigned n,const typename S::allocator_type & a)85 TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos, unsigned n, const typename S::allocator_type& a) {
86   typedef typename S::traits_type T;
87 
88   if (pos <= str.size()) {
89     S s2(str, pos, n, a);
90     LIBCPP_ASSERT(s2.__invariants());
91     typename S::size_type rlen = std::min<typename S::size_type>(str.size() - pos, n);
92     assert(s2.size() == rlen);
93     assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
94     assert(s2.get_allocator() == a);
95     assert(s2.capacity() >= s2.size());
96     LIBCPP_ASSERT(is_string_asan_correct(s2));
97   }
98 #ifndef TEST_HAS_NO_EXCEPTIONS
99   else if (!TEST_IS_CONSTANT_EVALUATED) {
100     try {
101       S s2(str, pos, n, a);
102       assert(false);
103     } catch (std::out_of_range&) {
104       assert(pos > str.size());
105     }
106   }
107 #endif
108 }
109 
test_lwg2583()110 void test_lwg2583() {
111 #if TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
112   typedef std::basic_string<char, std::char_traits<char>, test_allocator<char> > StringA;
113   std::vector<StringA, std::scoped_allocator_adaptor<test_allocator<StringA> > > vs;
114   StringA s{"1234"};
115   vs.emplace_back(s, 2);
116 
117   try {
118     vs.emplace_back(s, 5);
119   } catch (const std::out_of_range&) {
120     return;
121   }
122   assert(false);
123 #endif
124 }
125 
126 template <class Alloc>
test_string(const Alloc & a1,const Alloc & a2)127 TEST_CONSTEXPR_CXX20 void test_string(const Alloc& a1, const Alloc& a2) {
128   using S = std::basic_string<char, std::char_traits<char>, Alloc>;
129 
130   test(S(Alloc(a1)), 0);
131   test(S(Alloc(a1)), 1);
132   test(S("1", Alloc(a1)), 0);
133   test(S("1", Alloc(a1)), 1);
134   test(S("1", Alloc(a1)), 2);
135   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 0);
136   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 5);
137   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50);
138   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 500);
139 
140   test(S(Alloc(a1)), 0, 0);
141   test(S(Alloc(a1)), 0, 1);
142   test(S(Alloc(a1)), 1, 0);
143   test(S(Alloc(a1)), 1, 1);
144   test(S(Alloc(a1)), 1, 2);
145   test(S("1", Alloc(a1)), 0, 0);
146   test(S("1", Alloc(a1)), 0, 1);
147   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50, 0);
148   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50, 1);
149   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50, 10);
150   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50, 100);
151 
152   test(S(Alloc(a1)), 0, 0, Alloc(a2));
153   test(S(Alloc(a1)), 0, 1, Alloc(a2));
154   test(S(Alloc(a1)), 1, 0, Alloc(a2));
155   test(S(Alloc(a1)), 1, 1, Alloc(a2));
156   test(S(Alloc(a1)), 1, 2, Alloc(a2));
157   test(S("1", Alloc(a1)), 0, 0, Alloc(a2));
158   test(S("1", Alloc(a1)), 0, 1, Alloc(a2));
159   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50, 0, Alloc(a2));
160   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50, 1, Alloc(a2));
161   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50, 10, Alloc(a2));
162   test(S("1234567890123456789012345678901234567890123456789012345678901234567890", Alloc(a1)), 50, 100, Alloc(a2));
163 }
164 
test()165 TEST_CONSTEXPR_CXX20 bool test() {
166   test_string(std::allocator<char>(), std::allocator<char>());
167   test_string(test_allocator<char>(), test_allocator<char>());
168   test_string(test_allocator<char>(3), test_allocator<char>(5));
169 #if TEST_STD_VER >= 11
170   test_string(min_allocator<char>(), min_allocator<char>());
171   test_string(safe_allocator<char>(), safe_allocator<char>());
172 #endif
173 
174   return true;
175 }
176 
main(int,char **)177 int main(int, char**) {
178   test();
179 #if TEST_STD_VER > 17
180   static_assert(test());
181 #endif
182   test_lwg2583();
183 
184   return 0;
185 }
186