libzypp: zypp/Pathname.cc Source File

libzypp 17.25.10

Pathname.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13
14 #include <zypp/base/String.h>
15 #include <zypp/Pathname.h>
16 #include <zypp/Url.h>
17
18 using std::string;
19
21 namespace zypp
22 {
24 namespace filesystem
25 {
26
28 //
29 // METHOD NAME : Pathname::_assign
30 // METHOD TYPE : void
31 //
32 void Pathname::_assign( const string & name_r )
33 {
34 _name.clear();
35 if ( name_r.empty() )
36 return;
37 _name.reserve( name_r.size() );
38
39 // Collect up to "/.."
40 enum Pending {
41 P_none = 0, // ""
42 P_slash = 1, // "/"
43 P_dot1 = 2, // "/."
44 P_dot2 = 3 // "/.."
45 } pending = P_none;
46
47 // Assert relative path starting with "./"
48 // We rely on this below!
49 if ( name_r[0] != '/' )
50 {
51 _name += '.';
52 pending = P_slash;
53 }
54
55 // Lambda handling the "/.." case:
56 // [] + "/.." ==> []
57 // [.] + "/.." ==> [./..]
58 // [foo] is always [./foo] due to init above
59 // [*/..] + "/.." ==> [*/../..]
60 // [*/foo] + "/.." ==> [*]
61 auto goParent_f = [&](){
62 if ( _name.empty() )
63 /*NOOP*/;
64 else if ( _name.size() == 1 ) // content is '.'
65 _name += "/..";
66 else
67 {
68 std::string::size_type pos = _name.rfind( "/" );
69 if ( pos == _name.size() - 3 && _name[pos+1] == '.' && _name[pos+2] == '.' )
70 _name += "/..";
71 else
72 _name.erase( pos );
73 }
74 };
75
76 for ( char ch : name_r )
77 {
78 switch ( ch )
79 {
80 case '/':
81 switch ( pending )
82 {
83 case P_none: pending = P_slash; break;
84 case P_slash: break;
85 case P_dot1: pending = P_slash; break;
86 case P_dot2: goParent_f(); pending = P_slash; break;
87 }
88 break;
89
90 case '.':
91 switch ( pending )
92 {
93 case P_none: _name += '.'; break;
94 case P_slash: pending = P_dot1; break;
95 case P_dot1: pending = P_dot2; break;
96 case P_dot2: _name += "/..."; pending = P_none; break;
97 }
98 break;
99
100 default:
101 switch ( pending )
102 {
103 case P_none: break;
104 case P_slash: _name += '/'; pending = P_none; break;
105 case P_dot1: _name += "/."; pending = P_none; break;
106 case P_dot2: _name += "/.."; pending = P_none; break;
107 }
108 _name += ch;
109 break;
110 }
111 }
112
113 switch ( pending )
114 {
115 case P_none: break;
116 case P_slash: if ( _name.empty() ) _name = "/"; break;
117 case P_dot1: if ( _name.empty() ) _name = "/"; break;
118 case P_dot2: goParent_f(); if ( _name.empty() ) _name = "/"; break;
119 }
120 return;
121 }
122
124 //
125 // METHOD NAME : Pathname::dirname
126 // METHOD TYPE : Pathname
127 //
128 Pathname Pathname::dirname( const Pathname & name_r )
129 {
130 if ( name_r.empty() )
131 return Pathname();
132
133 Pathname ret_t( name_r );
134 std::string::size_type idx = ret_t._name.find_last_of( '/' );
135
136 if ( idx == std::string::npos ) {
137 ret_t._name = ".";
138 } else if ( idx == 0 ) {
139 ret_t._name = "/";
140 } else {
141 ret_t._name.erase( idx );
142 }
143
144 return ret_t;
145 }
146
148 //
149 // METHOD NAME : Pathname::basename
150 // METHOD TYPE : string
151 //
152 string Pathname::basename( const Pathname & name_r )
153 {
154 if ( name_r.empty() )
155 return string();
156
157 string ret_t( name_r.asString() );
158 std::string::size_type idx = ret_t.find_last_of( '/' );
159 if ( idx != std::string::npos && ( idx != 0 || ret_t.size() != 1 ) ) {
160 ret_t.erase( 0, idx+1 );
161 }
162
163 return ret_t;
164 }
165
167 //
168 // METHOD NAME : Pathname::asUrl
169 // METHOD TYPE : Url
170 //
171 Url Pathname::asUrl( const std::string & scheme_r ) const
172 {
173 Url ret;
174 ret.setPathName( asString() );
175 ret.setScheme( scheme_r );
176 return ret;
177 }
178
179 Url Pathname::asUrl() const
180 { return asUrl( "dir" ); }
181
182 Url Pathname::asDirUrl() const
183 { return asUrl( "dir" ); }
184
185 Url Pathname::asFileUrl() const
186 { return asUrl( "file" ); }
187
188
189 std::string Pathname::showRoot( const Pathname & root_r, const Pathname & path_r )
190 {
191 return str::Str() << "(" << root_r << ")" << path_r;
192 }
193
194 std::string Pathname::showRootIf( const Pathname & root_r, const Pathname & path_r )
195 {
196 if ( root_r.empty() || root_r == "/" )
197 return path_r.asString();
198 return showRoot( root_r, path_r );
199 }
200
202 //
203 // METHOD NAME : Pathname::extension
204 // METHOD TYPE : string
205 //
206 string Pathname::extension( const Pathname & name_r )
207 {
208 if ( name_r.empty() )
209 return string();
210
211 string base( basename( name_r ) );
212 std::string::size_type pos = base.rfind( '.' );
213 switch ( pos )
214 {
215 case 0:
216 if ( base.size() == 1 ) // .
217 return string();
218 break;
219 case 1:
220 if ( base.size() == 2 && base[0] == '.' ) // ..
221 return string();
222 break;
223 case std::string::npos:
224 return string();
225 break;
226 }
227 return base.substr( pos );
228 }
229
231 //
232 // METHOD NAME : Pathname::assertprefix
233 // METHOD TYPE : Pathname
234 //
235 Pathname Pathname::assertprefix( const Pathname & root_r, const Pathname & path_r )
236 {
237 if ( root_r.empty()
238 || path_r == root_r
239 || str::hasPrefix( path_r.asString(), root_r.asString() ) )
240 return path_r;
241 return root_r / path_r;
242 }
243
244 Pathname Pathname::stripprefix( const Pathname & root_r, const Pathname & path_r )
245 {
246 if ( root_r.emptyOrRoot() )
247 return path_r;
248 if ( root_r == path_r )
249 return "/";
250 std::string rest( str::stripPrefix( path_r.asString(), root_r.asString() ) );
251 if ( rest[0] == '/' ) // needs to be a dir prefix!
252 return rest;
253 return path_r;
254 }
255
257 //
258 // METHOD NAME : Pathname::cat
259 // METHOD TYPE : Pathname
260 //
261 Pathname Pathname::cat( const Pathname & name_r, const Pathname & add_tv )
262 {
263 if ( add_tv.empty() )
264 return name_r;
265 if ( name_r.empty() )
266 return add_tv;
267
268 string ret_ti( name_r._name );
269 if( add_tv._name[0] != '/' )
270 ret_ti += '/';
271 return ret_ti + add_tv._name;
272 }
273
275 //
276 // METHOD NAME : Pathname::Extend
277 // METHOD TYPE : Pathname
278 //
279 Pathname Pathname::extend( const Pathname & l, const string & r )
280 {
281 return l.asString() + r;
282 }
283
285 } // namespace filesystem
288 } // namespace zypp
Pathname.h
String.h
Url.h
zypp::Url
Url manipulation class.
Definition: Url.h:92
zypp::Url::setPathName
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:759
zypp::Url::setScheme
void setScheme(const std::string &scheme)
Set the scheme name in the URL.
Definition: Url.cc:663
zypp::filesystem::Pathname
Pathname.
Definition: Pathname.h:45
zypp::filesystem::Pathname::showRoot
static std::string showRoot(const Pathname &root_r, const Pathname &path_r)
String representation as "(root)/path".
Definition: Pathname.cc:189
zypp::filesystem::Pathname::extend
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:170
zypp::filesystem::Pathname::stripprefix
static Pathname stripprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r with any root_r dir prefix striped.
Definition: Pathname.cc:244
zypp::filesystem::Pathname::dirname
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
zypp::filesystem::Pathname::emptyOrRoot
bool emptyOrRoot() const
Test for "" or "/".
Definition: Pathname.h:121
zypp::filesystem::Pathname::asDirUrl
Url asDirUrl() const
Definition: Pathname.cc:182
zypp::filesystem::Pathname::cat
Pathname cat(const Pathname &r) const
Concatenation of pathnames.
Definition: Pathname.h:162
zypp::filesystem::Pathname::asFileUrl
Url asFileUrl() const
Definition: Pathname.cc:185
zypp::filesystem::Pathname::Pathname
Pathname()
Default ctor: an empty path.
Definition: Pathname.h:48
zypp::filesystem::Pathname::asString
const std::string & asString() const
String representation.
Definition: Pathname.h:91
zypp::filesystem::Pathname::basename
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
zypp::filesystem::Pathname::empty
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
zypp::filesystem::Pathname::assertprefix
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Definition: Pathname.cc:235
zypp::filesystem::Pathname::_assign
void _assign(const std::string &name_r)
Definition: Pathname.cc:32
zypp::filesystem::Pathname::showRootIf
static std::string showRootIf(const Pathname &root_r, const Pathname &path_r)
String representation as "(root)/path", unless root is "/" or empty.
Definition: Pathname.cc:194
zypp::filesystem::Pathname::asUrl
Url asUrl() const
Definition: Pathname.cc:179
zypp::filesystem::Pathname::extension
std::string extension() const
Return all of the characters in name after and including the last dot in the last element of name.
Definition: Pathname.h:135
zypp::filesystem::Pathname::_name
std::string _name
Definition: Pathname.h:174
zypp::sat::detail::size_type
SolvableIdType size_type
Definition: PoolMember.h:126
zypp::str::hasPrefix
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1023
zypp::str::stripPrefix
std::string stripPrefix(const C_Str &str_r, const C_Str &prefix_r)
Strip a prefix_r from str_r and return the resulting string.
Definition: String.h:1030
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
zypp::ResolverNamespace::filesystem
@ filesystem
filesystems
zypp::str::Str
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:209