xref: /llvm-project/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp (revision cc69d211d0d65d7bf0335fecbc323f784ac3afcc)
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 // UNSUPPORTED: c++03
10 
11 // <filesystem>
12 
13 // class path
14 
15 // template <class Source>
16 //      path& operator=(Source const&);
17 //  path& operator=(string_type&&);
18 // template <class Source>
19 //      path& assign(Source const&);
20 // template <class InputIterator>
21 //      path& assign(InputIterator first, InputIterator last);
22 
23 
24 #include "filesystem_include.h"
25 #include <type_traits>
26 #include <string_view>
27 #include <cassert>
28 
29 #include "test_macros.h"
30 #include "test_iterators.h"
31 #include "count_new.h"
32 #include "filesystem_test_helper.h"
33 
34 
35 template <class CharT>
36 void RunTestCase(MultiStringType const& MS) {
37   using namespace fs;
38   const char* Expect = MS;
39   const CharT* TestPath = MS;
40   const CharT* TestPathEnd = StrEnd(TestPath);
41   const std::size_t Size = TestPathEnd - TestPath;
42   const std::size_t SSize = StrEnd(Expect) - Expect;
43   assert(Size == SSize);
44   //////////////////////////////////////////////////////////////////////////////
45   // basic_string<Char, Traits, Alloc>
46   {
47     const std::basic_string<CharT> S(TestPath);
48     path p; PathReserve(p, S.length() + 1);
49     {
50       // string provides a contiguous iterator. No allocation needed.
51       DisableAllocationGuard g;
52       path& pref = (p = S);
53       assert(&pref == &p);
54     }
55     assert(p.native() == Expect);
56     assert(p.string<CharT>() == TestPath);
57     assert(p.string<CharT>() == S);
58   }
59   {
60     const std::basic_string<CharT> S(TestPath);
61     path p; PathReserve(p, S.length() + 1);
62     {
63       DisableAllocationGuard g;
64       path& pref = p.assign(S);
65       assert(&pref == &p);
66     }
67     assert(p.native() == Expect);
68     assert(p.string<CharT>() == TestPath);
69     assert(p.string<CharT>() == S);
70   }
71   // basic_string<Char, Traits, Alloc>
72   {
73     const std::basic_string_view<CharT> S(TestPath);
74     path p; PathReserve(p, S.length() + 1);
75     {
76       // string provides a contiguous iterator. No allocation needed.
77       DisableAllocationGuard g;
78       path& pref = (p = S);
79       assert(&pref == &p);
80     }
81     assert(p.native() == Expect);
82     assert(p.string<CharT>() == TestPath);
83     assert(p.string<CharT>() == S);
84   }
85   {
86     const std::basic_string_view<CharT> S(TestPath);
87     path p; PathReserve(p, S.length() + 1);
88     {
89       DisableAllocationGuard g;
90       path& pref = p.assign(S);
91       assert(&pref == &p);
92     }
93     assert(p.native() == Expect);
94     assert(p.string<CharT>() == TestPath);
95     assert(p.string<CharT>() == S);
96   }
97   //////////////////////////////////////////////////////////////////////////////
98   // Char* pointers
99   {
100     path p; PathReserve(p, Size + 1);
101     {
102       // char* pointers are contiguous and can be used with code_cvt directly.
103       // no allocations needed.
104       DisableAllocationGuard g;
105       path& pref = (p = TestPath);
106       assert(&pref == &p);
107     }
108     assert(p.native() == Expect);
109     assert(p.string<CharT>() == TestPath);
110   }
111   {
112     path p; PathReserve(p, Size + 1);
113     {
114       DisableAllocationGuard g;
115       path& pref = p.assign(TestPath);
116       assert(&pref == &p);
117     }
118     assert(p.native() == Expect);
119     assert(p.string<CharT>() == TestPath);
120   }
121   {
122     path p; PathReserve(p, Size + 1);
123     {
124       DisableAllocationGuard g;
125       path& pref = p.assign(TestPath, TestPathEnd);
126       assert(&pref == &p);
127     }
128     assert(p.native() == Expect);
129     assert(p.string<CharT>() == TestPath);
130   }
131   //////////////////////////////////////////////////////////////////////////////
132   // Iterators
133   {
134     using It = input_iterator<const CharT*>;
135     path p; PathReserve(p, Size + 1);
136     It it(TestPath);
137     {
138       // Iterators cannot be used with code_cvt directly. This assignment
139       // may allocate if it's larger than a "short-string".
140       path& pref = (p = it);
141       assert(&pref == &p);
142     }
143     assert(p.native() == Expect);
144     assert(p.string<CharT>() == TestPath);
145   }
146   {
147     using It = input_iterator<const CharT*>;
148     path p; PathReserve(p, Size + 1);
149     It it(TestPath);
150     {
151       path& pref = p.assign(it);
152       assert(&pref == &p);
153     }
154     assert(p.native() == Expect);
155     assert(p.string<CharT>() == TestPath);
156   }
157   {
158     using It = input_iterator<const CharT*>;
159     path p; PathReserve(p, Size + 1);
160     It it(TestPath);
161     It e(TestPathEnd);
162     {
163       path& pref = p.assign(it, e);
164       assert(&pref == &p);
165     }
166     assert(p.native() == Expect);
167     assert(p.string<CharT>() == TestPath);
168   }
169 }
170 
171 template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))>
172 constexpr bool has_assign(int) { return true; }
173 template <class It>
174 constexpr bool has_assign(long) { return false; }
175 template <class It>
176 constexpr bool has_assign() { return has_assign<It>(0); }
177 
178 void test_sfinae() {
179   using namespace fs;
180   {
181     using It = const char* const;
182     static_assert(std::is_assignable<path, It>::value, "");
183     static_assert(has_assign<It>(), "");
184   }
185   {
186     using It = input_iterator<const char*>;
187     static_assert(std::is_assignable<path, It>::value, "");
188     static_assert(has_assign<It>(), "");
189   }
190   {
191     struct Traits {
192       using iterator_category = std::input_iterator_tag;
193       using value_type = const char;
194       using pointer = const char*;
195       using reference = const char&;
196       using difference_type = std::ptrdiff_t;
197     };
198     using It = input_iterator<const char*, Traits>;
199     static_assert(std::is_assignable<path, It>::value, "");
200     static_assert(has_assign<It>(), "");
201   }
202   {
203     using It = output_iterator<const char*>;
204     static_assert(!std::is_assignable<path, It>::value, "");
205     static_assert(!has_assign<It>(), "");
206 
207   }
208   {
209     static_assert(!std::is_assignable<path, int*>::value, "");
210     static_assert(!has_assign<int*>(), "");
211   }
212 }
213 
214 void RunStringMoveTest(const char* Expect) {
215   using namespace fs;
216   std::string ss(Expect);
217   path p;
218   {
219     DisableAllocationGuard g; ((void)g);
220     path& pr = (p = std::move(ss));
221     assert(&pr == &p);
222   }
223   assert(p == Expect);
224   {
225     // Signature test
226     ASSERT_NOEXCEPT(p = std::move(ss));
227   }
228 }
229 
230 int main(int, char**) {
231   for (auto const& MS : PathList) {
232     RunTestCase<char>(MS);
233     RunTestCase<wchar_t>(MS);
234     RunTestCase<char16_t>(MS);
235     RunTestCase<char32_t>(MS);
236     RunStringMoveTest(MS);
237   }
238   test_sfinae();
239 
240   return 0;
241 }
242