Pathname.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013
00014 #include "zypp/base/String.h"
00015 #include "zypp/Pathname.h"
00016 #include "zypp/Url.h"
00017
00018 using std::string;
00019
00021 namespace zypp
00022 {
00023
00024 namespace filesystem
00025 {
00026
00028 namespace
00029 {
00030
00031
00032
00033
00034
00035
00036 inline void goParent_fnc( string & name_t )
00037 {
00038 if ( name_t.empty() )
00039 ;
00040 else if ( name_t.size() == 1 )
00041 name_t += "/..";
00042 else
00043 {
00044 std::string::size_type pos = name_t.rfind( "/" );
00045 if ( pos == name_t.size() - 3 && name_t[pos+1] == '.' && name_t[pos+2] == '.' )
00046 name_t += "/..";
00047 else
00048 name_t.erase( pos );
00049 }
00050 };
00051
00052 }
00054
00055
00057
00058
00059
00060
00061 void Pathname::_assign( const string & name_tv )
00062 {
00063 prfx_i = 0;
00064 name_t.clear();
00065 if ( name_tv.empty() )
00066 return;
00067 name_t.reserve( name_tv.size() );
00068
00069
00070 enum Pending {
00071 P_none = 0,
00072 P_slash = 1,
00073 P_dot1 = 2,
00074 P_dot2 = 3
00075 } pending = P_none;
00076
00077
00078
00079 if ( name_tv[0] != '/' )
00080 {
00081 name_t += '.';
00082 pending = P_slash;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091 #define goParent_f() goParent_fnc( name_t )
00092
00093 for_each_( it, name_tv )
00094 {
00095 const char ch( *it );
00096
00097 switch ( ch )
00098 {
00099 case '/':
00100 switch ( pending )
00101 {
00102 case P_none: pending = P_slash; break;
00103 case P_slash: break;
00104 case P_dot1: pending = P_slash; break;
00105 case P_dot2: goParent_f(); pending = P_slash; break;
00106 }
00107 break;
00108
00109 case '.':
00110 switch ( pending )
00111 {
00112 case P_none: name_t += '.'; break;
00113 case P_slash: pending = P_dot1; break;
00114 case P_dot1: pending = P_dot2; break;
00115 case P_dot2: name_t += "/..."; pending = P_none; break;
00116 }
00117 break;
00118
00119 default:
00120 switch ( pending )
00121 {
00122 case P_none: break;
00123 case P_slash: name_t += '/'; pending = P_none; break;
00124 case P_dot1: name_t += "/."; pending = P_none; break;
00125 case P_dot2: name_t += "/.."; pending = P_none; break;
00126 }
00127 name_t += ch;
00128 break;
00129 }
00130 }
00131
00132 switch ( pending )
00133 {
00134 case P_none: break;
00135 case P_slash: if ( name_t.empty() ) name_t = "/"; break;
00136 case P_dot1: if ( name_t.empty() ) name_t = "/"; break;
00137 case P_dot2: goParent_f(); if ( name_t.empty() ) name_t = "/"; break;
00138 }
00139 return;
00140 }
00141
00143
00144
00145
00146
00147 Pathname Pathname::dirname( const Pathname & name_tv )
00148 {
00149 if ( name_tv.empty() )
00150 return Pathname();
00151
00152 Pathname ret_t( name_tv );
00153 string::size_type idx = ret_t.name_t.find_last_of( '/' );
00154
00155 if ( idx == string::npos ) {
00156 ret_t.name_t = ".";
00157 } else if ( idx == 0 ) {
00158 ret_t.name_t = "/";
00159 } else {
00160 ret_t.name_t.erase( idx );
00161 }
00162
00163 return ret_t;
00164 }
00165
00167
00168
00169
00170
00171 string Pathname::basename( const Pathname & name_tv )
00172 {
00173 if ( name_tv.empty() )
00174 return string();
00175
00176 string ret_t( name_tv.asString() );
00177 string::size_type idx = ret_t.find_last_of( '/' );
00178 if ( idx != string::npos && ( idx != 0 || ret_t.size() != 1 ) ) {
00179 ret_t.erase( 0, idx+1 );
00180 }
00181
00182 return ret_t;
00183 }
00184
00186
00187
00188
00189
00190 Url Pathname::asUrl() const
00191 {
00192 Url ret( "dir:///" );
00193 ret.setPathName( asString() );
00194 return ret;
00195 }
00196
00197 std::string Pathname::showRoot( const Pathname & root_r, const Pathname & path_r )
00198 {
00199 return str::Str() << "(" << root_r << ")" << path_r;
00200 }
00201
00202 std::string Pathname::showRootIf( const Pathname & root_r, const Pathname & path_r )
00203 {
00204 if ( root_r.empty() || root_r == "/" )
00205 return path_r.asString();
00206 return showRoot( root_r, path_r );
00207 }
00208
00210
00211
00212
00213
00214 string Pathname::extension( const Pathname & name_tv )
00215 {
00216 if ( name_tv.empty() )
00217 return string();
00218
00219 string base( basename( name_tv ) );
00220 string::size_type pos = base.rfind( '.' );
00221 switch ( pos )
00222 {
00223 case 0:
00224 if ( base.size() == 1 )
00225 return string();
00226 break;
00227 case 1:
00228 if ( base.size() == 2 && base[0] == '.' )
00229 return string();
00230 break;
00231 case string::npos:
00232 return string();
00233 break;
00234 }
00235 return base.substr( pos );
00236 }
00237
00239
00240
00241
00242
00243 Pathname Pathname::assertprefix( const Pathname & root_r, const Pathname & path_r )
00244 {
00245 if ( root_r.empty()
00246 || path_r == root_r
00247 || str::hasPrefix( path_r.asString(), root_r.asString() ) )
00248 return path_r;
00249 return root_r / path_r;
00250 }
00251
00253
00254
00255
00256
00257 Pathname Pathname::cat( const Pathname & name_tv, const Pathname & add_tv )
00258 {
00259 if ( add_tv.empty() )
00260 return name_tv;
00261 if ( name_tv.empty() )
00262 return add_tv;
00263
00264 string ret_ti( name_tv.name_t );
00265 if( add_tv.name_t[0] != '/' )
00266 ret_ti += '/';
00267 return ret_ti + add_tv.name_t;
00268 }
00269
00271
00272
00273
00274
00275 Pathname Pathname::extend( const Pathname & l, const string & r )
00276 {
00277 return l.asString() + r;
00278 }
00279
00281 }
00284 }