libzypp 8.13.6
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 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 // CLASS NAME : DirStack 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 == "." ) { // '.' or '/' only for bot 00083 if ( bot ) 00084 return; 00085 } else if ( n == ".." && top ) { 00086 if ( top->name == "" ) // "/.." ==> "/" 00087 return; 00088 00089 if ( top->name != "." && top->name != ".." ) { // "somedir/.." ==> "" 00090 Pop(); 00091 return; 00092 } 00093 // "../.." "./.." stays 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 } // namespace 00125 00127 // 00128 // METHOD NAME : Pathname::_assign 00129 // METHOD TYPE : void 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 // check for prefix 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 // rel or abs path 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 // METHOD NAME : Pathname::dirname 00188 // METHOD TYPE : Pathname 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 // METHOD NAME : Pathname::basename 00214 // METHOD TYPE : string 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 // METHOD NAME : Pathname::asUrl 00234 // METHOD TYPE : Url 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 // METHOD NAME : Pathname::extension 00258 // METHOD TYPE : string 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 // METHOD NAME : Pathname::assertprefix 00275 // METHOD TYPE : Pathname 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 // METHOD NAME : Pathname::cat 00289 // METHOD TYPE : Pathname 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 // METHOD NAME : Pathname::Extend 00307 // METHOD TYPE : Pathname 00308 // 00309 Pathname Pathname::extend( const Pathname & l, const string & r ) 00310 { 00311 return l.asString() + r; 00312 } 00313 00315 } // namespace filesystem 00318 } // namespace zypp