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 
00016 using std::string;
00017 
00019 namespace zypp
00020 { 
00021 
00022   namespace filesystem
00023   { 
00024 
00026     namespace
00027     { 
00028 
00030       //
00031       //        CLASS NAME : DirStack
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 == "." ) { // '.' or '/' only for bot
00081             if ( bot )
00082               return;
00083           } else if ( n == ".." && top ) {
00084             if ( top->name == "" )          // "/.."        ==> "/"
00085               return;
00086 
00087             if ( top->name != "." && top->name != ".." ) {      // "somedir/.." ==> ""
00088               Pop();
00089               return;
00090             }
00091             // "../.." "./.." stays
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     } // namespace
00123 
00125     //
00126     //  METHOD NAME : Pathname::_assign
00127     //  METHOD TYPE : void
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       // check for prefix
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       // rel or abs path
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     //  METHOD NAME : Pathname::dirname
00187     //  METHOD TYPE : Pathname
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     //  METHOD NAME : Pathname::basename
00213     //  METHOD TYPE : string
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     //  METHOD NAME : Pathname::extension
00233     //  METHOD TYPE : string
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     //  METHOD NAME : Pathname::cat
00250     //  METHOD TYPE : Pathname
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     //  METHOD NAME : Pathname::Extend
00268     //  METHOD TYPE : Pathname
00269     //
00270     Pathname Pathname::extend( const Pathname & l, const string & r )
00271     {
00272       return l.asString() + r;
00273     }
00274 
00276   } // namespace filesystem
00279 } // namespace zypp

Generated on Thu Apr 24 02:24:50 2008 for zypp by  doxygen 1.4.6