00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013
00014 #include "zypp/Pathname.h"
00015 #include "zypp/Url.h"
00016
00017 using std::string;
00018
00020 namespace zypp
00021 {
00022
00023 namespace filesystem
00024 {
00025
00027 namespace
00028 {
00029
00031
00032
00033
00036 class DirStack {
00037
00038 struct Dir {
00039
00040 Dir * up;
00041 Dir * dn;
00042 string name;
00043
00044 Dir( const string & n = "" ) {
00045 name = n;
00046 up = dn = 0;
00047 }
00048
00049 ~Dir() {
00050 if ( up )
00051 up->dn = dn;
00052 if ( dn )
00053 dn->up = up;
00054 }
00055 };
00056
00057 Dir * top;
00058 Dir * bot;
00059
00060 void Pop() {
00061 if ( !top )
00062 return;
00063 top = top->dn;
00064 if ( top )
00065 delete top->up;
00066 else {
00067 delete bot;
00068 bot = 0;
00069 }
00070 }
00071
00072 public:
00073
00074 DirStack() { top = bot = 0; }
00075 ~DirStack() {
00076 while ( bot )
00077 Pop();
00078 }
00079
00080 void Push( const string & n ) {
00081 if ( n.empty() || n == "." ) {
00082 if ( bot )
00083 return;
00084 } else if ( n == ".." && top ) {
00085 if ( top->name == "" )
00086 return;
00087
00088 if ( top->name != "." && top->name != ".." ) {
00089 Pop();
00090 return;
00091 }
00092
00093 }
00094
00095 Dir * d = new Dir( n );
00096 if ( !top )
00097 top = bot = d;
00098 else {
00099 top->up = d;
00100 d->dn = top;
00101 d->up = 0;
00102 top = d;
00103 }
00104 }
00105
00106 string str() {
00107 if ( !bot )
00108 return "";
00109 string ret;
00110 for ( Dir * d = bot; d; d = d->up ) {
00111 if ( d != bot )
00112 ret += "/";
00113 ret += d->name;
00114 }
00115 if ( ret.empty() )
00116 return "/";
00117 return ret;
00118 }
00119 };
00120
00122 }
00124
00126
00127
00128
00129
00130 void Pathname::_assign( const string & name_tv )
00131 {
00132 prfx_i = 0;
00133 name_t = name_tv;
00134
00135 if ( name_t.empty() )
00136 return;
00137
00138 string Tprfx;
00139 DirStack Stack_Ci;
00140
00141 char * Buf_aci = new char[name_tv.length() + 1];
00142 char * W_pci = Buf_aci;
00143 const char * R_pci = name_tv.c_str();
00144
00145
00146 if ( name_t.length() >= 2
00147 && name_t[1] == ':'
00148 && ( 'a' <= name_t[0] && name_t[0] <= 'z'
00149 || 'A' <= name_t[0] && name_t[0] <= 'Z' ) ) {
00150 Tprfx = name_t.substr( 0, 2 );
00151 prfx_i = 2;
00152 R_pci += 2;
00153 }
00154
00155
00156 if ( *R_pci == '/' || *R_pci == '\\' ) {
00157 Stack_Ci.Push( "" );
00158 ++R_pci;
00159 } else {
00160 Stack_Ci.Push( "." );
00161 }
00162
00163 do {
00164 switch ( *R_pci ) {
00165 case '/':
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
00244
00245
00246
00247
00248 string Pathname::extension( const Pathname & name_tv )
00249 {
00250 if ( name_tv.empty() )
00251 return string();
00252
00253 string base( basename( name_tv ) );
00254 string::size_type pos = base.rfind( '.' );
00255 if ( pos == string::npos )
00256 return string();
00257 return base.substr( pos );
00258 }
00259
00261
00262
00263
00264
00265 Pathname Pathname::cat( const Pathname & name_tv, const Pathname & add_tv )
00266 {
00267 if ( add_tv.empty() )
00268 return name_tv;
00269 if ( name_tv.empty() )
00270 return add_tv;
00271
00272 string ret_ti( add_tv.asString() );
00273 ret_ti.replace( 0, add_tv.prfx_i, "/" );
00274
00275 return name_tv.asString() + ret_ti;
00276 }
00277
00279
00280
00281
00282
00283 Pathname Pathname::extend( const Pathname & l, const string & r )
00284 {
00285 return l.asString() + r;
00286 }
00287
00289 }
00292 }