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