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