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