1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Pathname.cc
14 #include "zypp/base/String.h"
15 #include "zypp/Pathname.h"
20 ///////////////////////////////////////////////////////////////////
22 { /////////////////////////////////////////////////////////////////
23 ///////////////////////////////////////////////////////////////////
25 { /////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////
29 // METHOD NAME : Pathname::_assign
32 void Pathname::_assign( const string & name_r )
37 _name.reserve( name_r.size() );
39 // Collect up to "/.."
47 // Assert relative path starting with "./"
48 // We rely on this below!
49 if ( name_r[0] != '/' )
55 // Lambda handling the "/.." case:
57 // [.] + "/.." ==> [./..]
58 // [foo] is always [./foo] due to init above
59 // [*/..] + "/.." ==> [*/../..]
60 // [*/foo] + "/.." ==> [*]
61 auto goParent_f = [&](){
64 else if ( _name.size() == 1 ) // content is '.'
68 std::string::size_type pos = _name.rfind( "/" );
69 if ( pos == _name.size() - 3 && _name[pos+1] == '.' && _name[pos+2] == '.' )
76 for ( char ch : name_r )
83 case P_none: pending = P_slash; break;
85 case P_dot1: pending = P_slash; break;
86 case P_dot2: goParent_f(); pending = P_slash; break;
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;
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;
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;
123 ///////////////////////////////////////////////////////////////////
125 // METHOD NAME : Pathname::dirname
126 // METHOD TYPE : Pathname
128 Pathname Pathname::dirname( const Pathname & name_r )
130 if ( name_r.empty() )
133 Pathname ret_t( name_r );
134 string::size_type idx = ret_t._name.find_last_of( '/' );
136 if ( idx == string::npos ) {
138 } else if ( idx == 0 ) {
141 ret_t._name.erase( idx );
147 ///////////////////////////////////////////////////////////////////
149 // METHOD NAME : Pathname::basename
150 // METHOD TYPE : string
152 string Pathname::basename( const Pathname & name_r )
154 if ( name_r.empty() )
157 string ret_t( name_r.asString() );
158 string::size_type idx = ret_t.find_last_of( '/' );
159 if ( idx != string::npos && ( idx != 0 || ret_t.size() != 1 ) ) {
160 ret_t.erase( 0, idx+1 );
166 ///////////////////////////////////////////////////////////////////
168 // METHOD NAME : Pathname::asUrl
171 Url Pathname::asUrl( const std::string & scheme_r ) const
174 ret.setPathName( asString() );
175 ret.setScheme( scheme_r );
179 Url Pathname::asUrl() const
180 { return asUrl( "dir" ); }
182 Url Pathname::asDirUrl() const
183 { return asUrl( "dir" ); }
185 Url Pathname::asFileUrl() const
186 { return asUrl( "file" ); }
189 std::string Pathname::showRoot( const Pathname & root_r, const Pathname & path_r )
191 return str::Str() << "(" << root_r << ")" << path_r;
194 std::string Pathname::showRootIf( const Pathname & root_r, const Pathname & path_r )
196 if ( root_r.empty() || root_r == "/" )
197 return path_r.asString();
198 return showRoot( root_r, path_r );
201 ///////////////////////////////////////////////////////////////////
203 // METHOD NAME : Pathname::extension
204 // METHOD TYPE : string
206 string Pathname::extension( const Pathname & name_r )
208 if ( name_r.empty() )
211 string base( basename( name_r ) );
212 string::size_type pos = base.rfind( '.' );
216 if ( base.size() == 1 ) // .
220 if ( base.size() == 2 && base[0] == '.' ) // ..
227 return base.substr( pos );
230 ///////////////////////////////////////////////////////////////////
232 // METHOD NAME : Pathname::assertprefix
233 // METHOD TYPE : Pathname
235 Pathname Pathname::assertprefix( const Pathname & root_r, const Pathname & path_r )
239 || str::hasPrefix( path_r.asString(), root_r.asString() ) )
241 return root_r / path_r;
244 ///////////////////////////////////////////////////////////////////
246 // METHOD NAME : Pathname::cat
247 // METHOD TYPE : Pathname
249 Pathname Pathname::cat( const Pathname & name_r, const Pathname & add_tv )
251 if ( add_tv.empty() )
253 if ( name_r.empty() )
256 string ret_ti( name_r._name );
257 if( add_tv._name[0] != '/' )
259 return ret_ti + add_tv._name;
262 ///////////////////////////////////////////////////////////////////
264 // METHOD NAME : Pathname::Extend
265 // METHOD TYPE : Pathname
267 Pathname Pathname::extend( const Pathname & l, const string & r )
269 return l.asString() + r;
272 /////////////////////////////////////////////////////////////////
273 } // namespace filesystem
274 ///////////////////////////////////////////////////////////////////
275 /////////////////////////////////////////////////////////////////
277 ///////////////////////////////////////////////////////////////////