Pathname.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002  |                          ____ _   __ __ ___                          |
00003  |                         |__  / \ / / . \ . \                         |
00004  |                           / / \ V /|  _/  _/                         |
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       //        CLASS NAME : DirStack
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 == "." ) { // '.' or '/' only for bot
00082             if ( bot )
00083               return;
00084           } else if ( n == ".." && top ) {
00085             if ( top->name == "" )          // "/.."        ==> "/"
00086               return;
00087 
00088             if ( top->name != "." && top->name != ".." ) {      // "somedir/.." ==> ""
00089               Pop();
00090               return;
00091             }
00092             // "../.." "./.." stays
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     } // namespace
00124 
00126     //
00127     //  METHOD NAME : Pathname::_assign
00128     //  METHOD TYPE : void
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       // check for prefix
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       // rel or abs path
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     //  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 
00244     //
00245     //  METHOD NAME : Pathname::extension
00246     //  METHOD TYPE : string
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     //  METHOD NAME : Pathname::cat
00263     //  METHOD TYPE : Pathname
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     //  METHOD NAME : Pathname::Extend
00281     //  METHOD TYPE : Pathname
00282     //
00283     Pathname Pathname::extend( const Pathname & l, const string & r )
00284     {
00285       return l.asString() + r;
00286     }
00287 
00289   } // namespace filesystem
00292 } // namespace zypp

Generated on Tue Sep 25 19:23:05 2007 for libzypp by  doxygen 1.5.3