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