]>
Commit | Line | Data |
---|---|---|
2b522535 | 1 | // { dg-options "-std=gnu++17" } |
6cda876d | 2 | // { dg-do run { target c++17 } } |
6cda876d | 3 | |
a5544970 | 4 | // Copyright (C) 2018-2019 Free Software Foundation, Inc. |
6cda876d JW |
5 | // |
6 | // This file is part of the GNU ISO C++ Library. This library is free | |
7 | // software; you can redistribute it and/or modify it under the | |
8 | // terms of the GNU General Public License as published by the | |
9 | // Free Software Foundation; either version 3, or (at your option) | |
10 | // any later version. | |
11 | ||
12 | // This library is distributed in the hope that it will be useful, | |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | // GNU General Public License for more details. | |
16 | ||
17 | // You should have received a copy of the GNU General Public License along | |
18 | // with this library; see the file COPYING3. If not see | |
19 | // <http://www.gnu.org/licenses/>. | |
20 | ||
21 | // C++17 30.10.8.4.3 path appends [fs.path.append] | |
22 | ||
23 | #include <filesystem> | |
24 | #include <string_view> | |
25 | #include <testsuite_fs.h> | |
26 | #include <testsuite_iterators.h> | |
27 | ||
28 | using std::filesystem::path; | |
29 | using __gnu_test::compare_paths; | |
30 | ||
31 | // path::operator/=(const Source& source) | |
32 | // path::append(const Source& source) | |
33 | // Equivalent to: return operator/=(path(source)); | |
34 | ||
35 | // path::append(InputIterator first, InputIterator last) | |
36 | // Equivalent to: return operator/=(path(first, last)); | |
37 | ||
49d729ea JW |
38 | template<typename Char> |
39 | void test(const path& p, const Char* s) | |
6cda876d JW |
40 | { |
41 | path expected = p; | |
42 | expected /= path(s); | |
43 | ||
44 | path oper = p; | |
45 | oper /= s; | |
46 | ||
47 | path func = p; | |
48 | func.append(s); | |
49 | ||
49d729ea JW |
50 | __gnu_test::test_container<const Char, __gnu_test::input_iterator_wrapper> |
51 | input_range(s, s + std::char_traits<Char>::length(s)); | |
6cda876d JW |
52 | path range = p; |
53 | range.append(input_range.begin(), input_range.end()); | |
54 | ||
55 | compare_paths( oper, expected ); | |
56 | compare_paths( func, expected ); | |
57 | compare_paths( range, expected ); | |
58 | } | |
59 | ||
60 | void | |
61 | test01() | |
62 | { | |
63 | test( "/foo/bar", "/foo/" ); | |
64 | ||
65 | test( "baz", "baz" ); | |
66 | test( "baz/", "baz" ); | |
67 | test( "baz", "/foo/bar" ); | |
68 | test( "baz/", "/foo/bar" ); | |
69 | ||
70 | test( "", "" ); | |
71 | test( "", "rel" ); | |
72 | ||
73 | test( "dir/", "/file" ); | |
74 | test( "dir/", "file" ); | |
75 | } | |
76 | ||
77 | void | |
78 | test02() | |
79 | { | |
80 | // C++17 [fs.path.append] p4 | |
81 | test( "//host", "foo" ); | |
82 | test( "//host/", "foo" ); | |
83 | test( "foo", "" ); | |
84 | test( "foo", "/bar" ); | |
85 | test( "foo", "c:/bar" ); | |
86 | test( "foo", "c:" ); | |
87 | test( "c:", "" ); | |
88 | test( "c:foo", "/bar" ); | |
89 | test( "foo", "c:\\bar" ); | |
90 | } | |
91 | ||
92 | void | |
93 | test03() | |
94 | { | |
95 | for (const path& p : __gnu_test::test_paths) | |
96 | for (const path& q : __gnu_test::test_paths) | |
49d729ea JW |
97 | { |
98 | test(p, q.c_str()); | |
99 | if constexpr (!std::is_same_v<path::value_type, char>) | |
100 | test(p, q.string().c_str()); | |
101 | } | |
102 | } | |
103 | ||
104 | void | |
105 | test04() | |
106 | { | |
107 | #ifdef _GLIBCXX_USE_WCHAR_T | |
108 | test( "foo", L"/bar" ); | |
109 | test( L"foo", "/bar" ); | |
110 | test( L"foo", L"/bar" ); | |
111 | #endif | |
6cda876d JW |
112 | } |
113 | ||
4f87bb8d JW |
114 | void |
115 | test05() | |
116 | { | |
117 | std::basic_string_view<path::value_type> s; | |
118 | ||
119 | path p = "0/1/2/3/4/5/6"; | |
120 | // The string_view aliases the path's internal string: | |
121 | s = p.native(); | |
080cec7f JW |
122 | path::string_type expected(s); |
123 | expected += path::preferred_separator; | |
124 | expected += s; | |
4f87bb8d JW |
125 | // Append that string_view, which must work correctly even though the |
126 | // internal string will be reallocated during the operation: | |
127 | p /= s; | |
080cec7f | 128 | compare_paths(p, expected); |
4f87bb8d JW |
129 | |
130 | // Same again with a trailing slash: | |
131 | path p2 = "0/1/2/3/4/5/"; | |
132 | s = p2.native(); | |
080cec7f JW |
133 | expected = s; |
134 | expected += s; | |
4f87bb8d | 135 | p2 /= s; |
080cec7f | 136 | compare_paths(p2, expected); |
4f87bb8d JW |
137 | |
138 | // And aliasing one of the components of the path: | |
139 | path p3 = "0/123456789/a"; | |
140 | path::iterator second = std::next(p3.begin()); | |
141 | s = second->native(); | |
080cec7f JW |
142 | expected = p3.native() + path::preferred_separator; |
143 | expected += s; | |
4f87bb8d | 144 | p3 /= s; |
080cec7f JW |
145 | compare_paths(p3, expected); |
146 | } | |
2017595d JW |
147 | |
148 | void | |
149 | test06() | |
150 | { | |
151 | const std::string s0 = "a/b/c"; | |
152 | path p = s0; | |
153 | std::string s; | |
154 | for (int i = 0; i < 10; ++i) | |
155 | s += "0/1/2/3/4/5/6/7/8/9/"; | |
156 | // append a long string with many components | |
157 | test(p, s.c_str()); | |
158 | ||
159 | // Same again but with a trailing slash on the left operand: | |
160 | path p2 = s0 + '/'; | |
161 | test(p2, s.c_str()); | |
4f87bb8d JW |
162 | } |
163 | ||
6cda876d JW |
164 | int |
165 | main() | |
166 | { | |
167 | test01(); | |
168 | test02(); | |
169 | test03(); | |
49d729ea | 170 | test04(); |
4f87bb8d | 171 | test05(); |
2017595d | 172 | test06(); |
6cda876d | 173 | } |