Pathname.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002  |                          ____ _   __ __ ___                          |
00003  |                         |__  / \ / / . \ . \                         |
00004  |                           / / \ V /|  _/  _/                         |
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       //        CLASS NAME : DirStack
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 == "." ) { // '.' or '/' only for bot
00079             if ( bot )
00080               return;
00081           } else if ( n == ".." && top ) {
00082             if ( top->name == "" )          // "/.."        ==> "/"
00083               return;
00084 
00085             if ( top->name != "." && top->name != ".." ) {      // "somedir/.." ==> ""
00086               Pop();
00087               return;
00088             }
00089             // "../.." "./.." stays
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     } // namespace
00121 
00123     //
00124     //  METHOD NAME : Pathname::_assign
00125     //  METHOD TYPE : void
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       // check for prefix
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       // rel or abs path
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     //  METHOD NAME : Pathname::dirname
00185     //  METHOD TYPE : Pathname
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     //  METHOD NAME : Pathname::basename
00211     //  METHOD TYPE : string
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     //  METHOD NAME : Pathname::cat
00231     //  METHOD TYPE : Pathname
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     //  METHOD NAME : Pathname::Extend
00249     //  METHOD TYPE : Pathname
00250     //
00251     Pathname Pathname::extend( const Pathname & l, const string & r )
00252     {
00253       return l.asString() + r;
00254     }
00255 
00257   } // namespace filesystem
00260 } // namespace zypp

Generated on Thu Jul 6 00:07:22 2006 for zypp by  doxygen 1.4.6