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

source code of libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp