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 ( auto 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
///////////////////////////////////////////////////////////////////