00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013
00014 #include "zypp/Pathname.h"
00015
00016 using std::string;
00017
00019 namespace zypp
00020 {
00021
00022 namespace filesystem
00023 {
00024
00026 namespace
00027 {
00028
00030
00031
00032
00035 class DirStack {
00036
00037 struct Dir {
00038
00039 Dir * up;
00040 Dir * dn;
00041 string name;
00042
00043 Dir( const string & n = "" ) {
00044 name = n;
00045 up = dn = 0;
00046 }
00047
00048 ~Dir() {
00049 if ( up )
00050 up->dn = dn;
00051 if ( dn )
00052 dn->up = up;
00053 }
00054 };
00055
00056 Dir * top;
00057 Dir * bot;
00058
00059 void Pop() {
00060 if ( !top )
00061 return;
00062 top = top->dn;
00063 if ( top )
00064 delete top->up;
00065 else {
00066 delete bot;
00067 bot = 0;
00068 }
00069 }
00070
00071 public:
00072
00073 DirStack() { top = bot = 0; }
00074 ~DirStack() {
00075 while ( bot )
00076 Pop();
00077 }
00078
00079 void Push( const string & n ) {
00080 if ( n.empty() || n == "." ) {
00081 if ( bot )
00082 return;
00083 } else if ( n == ".." && top ) {
00084 if ( top->name == "" )
00085 return;
00086
00087 if ( top->name != "." && top->name != ".." ) {
00088 Pop();
00089 return;
00090 }
00091
00092 }
00093
00094 Dir * d = new Dir( n );
00095 if ( !top )
00096 top = bot = d;
00097 else {
00098 top->up = d;
00099 d->dn = top;
00100 d->up = 0;
00101 top = d;
00102 }
00103 }
00104
00105 string str() {
00106 if ( !bot )
00107 return "";
00108 string ret;
00109 for ( Dir * d = bot; d; d = d->up ) {
00110 if ( d != bot )
00111 ret += "/";
00112 ret += d->name;
00113 }
00114 if ( ret.empty() )
00115 return "/";
00116 return ret;
00117 }
00118 };
00119
00121 }
00123
00125
00126
00127
00128
00129 void Pathname::_assign( const string & name_tv )
00130 {
00131 prfx_i = 0;
00132 name_t = name_tv;
00133
00134 if ( name_t.empty() )
00135 return;
00136
00137 string Tprfx;
00138 DirStack Stack_Ci;
00139
00140 char * Buf_aci = new char[name_tv.length() + 1];
00141 char * W_pci = Buf_aci;
00142 const char * R_pci = name_tv.c_str();
00143
00144
00145 if ( name_t.length() >= 2
00146 && name_t[1] == ':'
00147 && ( 'a' <= name_t[0] && name_t[0] <= 'z'
00148 || 'A' <= name_t[0] && name_t[0] <= 'Z' ) ) {
00149 Tprfx = name_t.substr( 0, 2 );
00150 prfx_i = 2;
00151 R_pci += 2;
00152 }
00153
00154
00155 if ( *R_pci == '/' || *R_pci == '\\' ) {
00156 Stack_Ci.Push( "" );
00157 ++R_pci;
00158 } else {
00159 Stack_Ci.Push( "." );
00160 }
00161
00162 do {
00163 switch ( *R_pci ) {
00164 case '/':
00165 case '\\':
00166 case '\0':
00167 if ( W_pci != Buf_aci ) {
00168 *W_pci = '\0';
00169 W_pci = Buf_aci;
00170 Stack_Ci.Push( Buf_aci );
00171 }
00172 break;
00173
00174 default:
00175 *W_pci++ = *R_pci;
00176 break;
00177 }
00178 } while( *R_pci++ );
00179
00180 delete[] Buf_aci;
00181 name_t = Tprfx + Stack_Ci.str();
00182 }
00183
00185
00186
00187
00188
00189 Pathname Pathname::dirname( const Pathname & name_tv )
00190 {
00191 if ( name_tv.empty() )
00192 return "";
00193
00194 Pathname ret_t( name_tv );
00195 string::size_type idx = ret_t.name_t.find_last_of( '/' );
00196
00197 if ( idx == string::npos ) {
00198 ret_t.name_t.erase( ret_t.prfx_i );
00199 ret_t.name_t += ".";
00200 } else if ( idx == ret_t.prfx_i ) {
00201 ret_t.name_t.erase( ret_t.prfx_i );
00202 ret_t.name_t += "/";
00203 } else {
00204 ret_t.name_t.erase( idx );
00205 }
00206
00207 return ret_t;
00208 }
00209
00211
00212
00213
00214
00215 string Pathname::basename( const Pathname & name_tv )
00216 {
00217 if ( name_tv.empty() )
00218 return string();
00219
00220 string ret_t( name_tv.asString() );
00221 ret_t.erase( 0, name_tv.prfx_i );
00222 string::size_type idx = ret_t.find_last_of( '/' );
00223 if ( idx != string::npos ) {
00224 ret_t.erase( 0, idx+1 );
00225 }
00226
00227 return ret_t;
00228 }
00229
00231
00232
00233
00234
00235 string Pathname::extension( const Pathname & name_tv )
00236 {
00237 if ( name_tv.empty() )
00238 return string();
00239
00240 string base( basename( name_tv ) );
00241 string::size_type pos = base.rfind( '.' );
00242 if ( pos == string::npos )
00243 return string();
00244 return base.substr( pos );
00245 }
00246
00248
00249
00250
00251
00252 Pathname Pathname::cat( const Pathname & name_tv, const Pathname & add_tv )
00253 {
00254 if ( add_tv.empty() )
00255 return name_tv;
00256 if ( name_tv.empty() )
00257 return add_tv;
00258
00259 string ret_ti( add_tv.asString() );
00260 ret_ti.replace( 0, add_tv.prfx_i, "/" );
00261
00262 return name_tv.asString() + ret_ti;
00263 }
00264
00266
00267
00268
00269
00270 Pathname Pathname::extend( const Pathname & l, const string & r )
00271 {
00272 return l.asString() + r;
00273 }
00274
00276 }
00279 }