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
00032
00033
00034
00037 class DirStack {
00038
00039 struct Dir {
00040
00041 Dir * up;
00042 Dir * dn;
00043 string name;
00044
00045 Dir( const string & n = "" ) {
00046 name = n;
00047 up = dn = 0;
00048 }
00049
00050 ~Dir() {
00051 if ( up )
00052 up->dn = dn;
00053 if ( dn )
00054 dn->up = up;
00055 }
00056 };
00057
00058 Dir * top;
00059 Dir * bot;
00060
00061 void Pop() {
00062 if ( !top )
00063 return;
00064 top = top->dn;
00065 if ( top )
00066 delete top->up;
00067 else {
00068 delete bot;
00069 bot = 0;
00070 }
00071 }
00072
00073 public:
00074
00075 DirStack() { top = bot = 0; }
00076 ~DirStack() {
00077 while ( bot )
00078 Pop();
00079 }
00080
00081 void Push( const string & n ) {
00082 if ( n.empty() || n == "." ) {
00083 if ( bot )
00084 return;
00085 } else if ( n == ".." && top ) {
00086 if ( top->name == "" )
00087 return;
00088
00089 if ( top->name != "." && top->name != ".." ) {
00090 Pop();
00091 return;
00092 }
00093
00094 }
00095
00096 Dir * d = new Dir( n );
00097 if ( !top )
00098 top = bot = d;
00099 else {
00100 top->up = d;
00101 d->dn = top;
00102 d->up = 0;
00103 top = d;
00104 }
00105 }
00106
00107 string str() {
00108 if ( !bot )
00109 return "";
00110 string ret;
00111 for ( Dir * d = bot; d; d = d->up ) {
00112 if ( d != bot )
00113 ret += "/";
00114 ret += d->name;
00115 }
00116 if ( ret.empty() )
00117 return "/";
00118 return ret;
00119 }
00120 };
00121
00123 }
00125
00127
00128
00129
00130
00131 void Pathname::_assign( const string & name_tv )
00132 {
00133 prfx_i = 0;
00134 name_t = name_tv;
00135
00136 if ( name_t.empty() )
00137 return;
00138
00139 string Tprfx;
00140 DirStack Stack_Ci;
00141
00142 char * Buf_aci = new char[name_tv.length() + 1];
00143 char * W_pci = Buf_aci;
00144 const char * R_pci = name_tv.c_str();
00145
00146
00147 if ( name_t.length() >= 2
00148 && name_t[1] == ':'
00149 && ( ( 'a' <= name_t[0] && name_t[0] <= 'z' )
00150 || ( 'A' <= name_t[0] && name_t[0] <= 'Z' ) ) ) {
00151 Tprfx = name_t.substr( 0, 2 );
00152 prfx_i = 2;
00153 R_pci += 2;
00154 }
00155
00156
00157 if ( *R_pci == '/' ) {
00158 Stack_Ci.Push( "" );
00159 ++R_pci;
00160 } else {
00161 Stack_Ci.Push( "." );
00162 }
00163
00164 do {
00165 switch ( *R_pci ) {
00166 case '/':
00167 case '\0':
00168 if ( W_pci != Buf_aci ) {
00169 *W_pci = '\0';
00170 W_pci = Buf_aci;
00171 Stack_Ci.Push( Buf_aci );
00172 }
00173 break;
00174
00175 default:
00176 *W_pci++ = *R_pci;
00177 break;
00178 }
00179 } while( *R_pci++ );
00180
00181 delete[] Buf_aci;
00182 name_t = Tprfx + Stack_Ci.str();
00183 }
00184
00186
00187
00188
00189
00190 Pathname Pathname::dirname( const Pathname & name_tv )
00191 {
00192 if ( name_tv.empty() )
00193 return "";
00194
00195 Pathname ret_t( name_tv );
00196 string::size_type idx = ret_t.name_t.find_last_of( '/' );
00197
00198 if ( idx == string::npos ) {
00199 ret_t.name_t.erase( ret_t.prfx_i );
00200 ret_t.name_t += ".";
00201 } else if ( idx == ret_t.prfx_i ) {
00202 ret_t.name_t.erase( ret_t.prfx_i );
00203 ret_t.name_t += "/";
00204 } else {
00205 ret_t.name_t.erase( idx );
00206 }
00207
00208 return ret_t;
00209 }
00210
00212
00213
00214
00215
00216 string Pathname::basename( const Pathname & name_tv )
00217 {
00218 if ( name_tv.empty() )
00219 return string();
00220
00221 string ret_t( name_tv.asString() );
00222 ret_t.erase( 0, name_tv.prfx_i );
00223 string::size_type idx = ret_t.find_last_of( '/' );
00224 if ( idx != string::npos ) {
00225 ret_t.erase( 0, idx+1 );
00226 }
00227
00228 return ret_t;
00229 }
00230
00232
00233
00234
00235
00236 Url Pathname::asUrl() const
00237 {
00238 Url ret( "dir:///" );
00239 ret.setPathName( asString() );
00240 return ret;
00241 }
00242
00243 std::string Pathname::showRoot( const Pathname & root_r, const Pathname & path_r )
00244 {
00245 return str::Str() << "(" << root_r << ")" << path_r;
00246 }
00247
00248 std::string Pathname::showRootIf( const Pathname & root_r, const Pathname & path_r )
00249 {
00250 if ( root_r.empty() || root_r == "/" )
00251 return path_r.asString();
00252 return showRoot( root_r, path_r );
00253 }
00254
00256
00257
00258
00259
00260 string Pathname::extension( const Pathname & name_tv )
00261 {
00262 if ( name_tv.empty() )
00263 return string();
00264
00265 string base( basename( name_tv ) );
00266 string::size_type pos = base.rfind( '.' );
00267 if ( pos == string::npos )
00268 return string();
00269 return base.substr( pos );
00270 }
00271
00273
00274
00275
00276
00277 Pathname Pathname::assertprefix( const Pathname & root_r, const Pathname & path_r )
00278 {
00279 if ( root_r.empty()
00280 || path_r == root_r
00281 || str::hasPrefix( path_r.asString(), root_r.asString() ) )
00282 return path_r;
00283 return root_r / path_r;
00284 }
00285
00287
00288
00289
00290
00291 Pathname Pathname::cat( const Pathname & name_tv, const Pathname & add_tv )
00292 {
00293 if ( add_tv.empty() )
00294 return name_tv;
00295 if ( name_tv.empty() )
00296 return add_tv;
00297
00298 string ret_ti( add_tv.asString() );
00299 ret_ti.replace( 0, add_tv.prfx_i, "/" );
00300
00301 return name_tv.asString() + ret_ti;
00302 }
00303
00305
00306
00307
00308
00309 Pathname Pathname::extend( const Pathname & l, const string & r )
00310 {
00311 return l.asString() + r;
00312 }
00313
00315 }
00318 }