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