Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

CdbPathName.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbPathName.cc,v 1.7 2005/08/23 18:54:58 gapon Exp $
00003 
00004 /// The implementation of the CdbPathName class.
00005 /**
00006   * @see CdbPathName
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbBase/CdbPathName.hh"
00012 #include "CdbBase/CdbPathNameItr.hh"
00013 
00014 #include <string.h>     // strstr()
00015 #include <assert.h>
00016 
00017 #include <iostream>
00018 using std::endl;
00019 
00020 const char*
00021 CdbPathName::separator( )
00022 {
00023     return "/";
00024 }
00025 
00026 std::string
00027 CdbPathName::separatorTerminated( const std::string& theName )
00028 {
00029     assert( !theName.empty( ));
00030     assert( theName.length( ) != 0 );
00031 
00032   // The following test is done just in case if the current model of
00033   // of the separator's concept would change and it will be a multi-character
00034   // string.
00035 
00036     assert( strlen( separator( )) == 1 );
00037 
00038   // If the last character in the input string is not the separator
00039   // then we're adding the one by the string's end.
00040 
00041     if( theName[theName.length( )-1] == separator( )[0] ) return theName;
00042     return theName + separator( );
00043 }
00044 
00045 CdbPathName::CdbPathName( const char* theStr ) :
00046     _isValid    (false),
00047     _isAbsolute (false),
00048     _isRoot     (false),
00049     _isComposite(false)
00050 {
00051     _isValid = translateStringIntoTokens( theStr );
00052 
00053     recalculateDescriptorFlags( );
00054 }
00055 
00056 CdbPathName::CdbPathName( const std::string& theStr ) :
00057     _isValid    (false),
00058     _isAbsolute (false),
00059     _isRoot     (false),
00060     _isComposite(false)
00061 {
00062     _isValid  = translateStringIntoTokens(( theStr.empty( ) ? 0 : theStr.c_str( )));
00063 
00064     recalculateDescriptorFlags( );
00065 }
00066 
00067 CdbPathName::CdbPathName( const std::vector< std::string >& theTokens ) :
00068     _isValid    (false),
00069     _isAbsolute (false),
00070     _isRoot     (false),
00071     _isComposite(false),
00072     _tokens     (theTokens) // must be set before to proceed with the rest
00073 {
00074     _isValid = rebuildFullPath( );
00075 
00076     recalculateDescriptorFlags( );
00077 }
00078 
00079 CdbPathName::CdbPathName( const CdbPathName& thePath ) :
00080     _isValid    (thePath._isValid),
00081     _isAbsolute (thePath._isAbsolute),
00082     _isRoot     (thePath._isRoot),
00083     _isComposite(thePath._isComposite),
00084     _name       (thePath._name),
00085     _tokens     (thePath._tokens)
00086 { }
00087 
00088 CdbPathName::~CdbPathName( )
00089 { }
00090 
00091 CdbPathName&
00092 CdbPathName::operator=( const CdbPathName& thePath )
00093 {
00094     if( this != &thePath ) {
00095         _isValid     = thePath._isValid;
00096         _isAbsolute  = thePath._isAbsolute;
00097         _isRoot      = thePath._isRoot;
00098         _isComposite = thePath._isComposite;
00099         _name        = thePath._name;
00100         _tokens      = thePath._tokens;
00101     }
00102     return *this;
00103 }
00104 
00105 bool
00106 CdbPathName::isValid( ) const
00107 {
00108     return _isValid;
00109 }
00110 
00111 bool
00112 CdbPathName::isRoot( ) const
00113 {
00114     return _isRoot;
00115 }
00116 
00117 bool
00118 CdbPathName::isAbsolute( ) const
00119 {
00120     return _isAbsolute;
00121 }
00122 
00123 bool
00124 CdbPathName::isComposite( ) const
00125 {
00126     return _isComposite;
00127 }
00128 
00129 CdbPathName
00130 CdbPathName::first( ) const
00131 {
00132     if( _isValid ) return CdbPathName( _tokens[0] );
00133     return CdbPathName( );
00134 }
00135 
00136 CdbPathName
00137 CdbPathName::afterFirst( ) const
00138 {
00139     if( _isValid && ( _tokens.size( ) > 1 )) {
00140 
00141         CdbPathName result( _tokens[1] );
00142 
00143         for( unsigned int i = 2; i < _tokens.size( ); i++ )
00144             result = result + _tokens[i];
00145 
00146         return result;
00147     }
00148     return CdbPathName( );
00149 }
00150 
00151 CdbPathName
00152 CdbPathName::last( ) const
00153 {
00154     if( _isValid ) return CdbPathName( _tokens[_tokens.size( ) - 1] );
00155     return CdbPathName( );
00156 }
00157 
00158 CdbPathName
00159 CdbPathName::beforeLast( ) const
00160 {
00161     if( _isValid && ( _tokens.size( ) > 1 )) {
00162 
00163         CdbPathName result( _tokens[0] );
00164 
00165         for( size_t i = 1; i < _tokens.size( ) - 1; i++ )
00166             result = result + _tokens[i];
00167 
00168         return result;
00169     }
00170     return CdbPathName( );
00171 }
00172 
00173 std::string
00174 CdbPathName::toString( ) const
00175 {
00176     return _name;
00177 }
00178 
00179 CdbPathName
00180 CdbPathName::operator+( const CdbPathName& thePath ) const
00181 {
00182   // Make sure the input path is valid
00183 
00184     if( thePath.isValid( )) {
00185 
00186         if( _isValid ) {
00187 
00188           // Concatenate the input path to the current one if the current
00189           // one is valid.
00190           //
00191           // NOTE: We only allow a relative path to be added
00192 
00193             if( ! thePath.isAbsolute( )) {
00194 
00195                 std::vector< std::string > tokens( _tokens );
00196                 tokens.insert( tokens.end( ),
00197                                thePath._tokens.begin( ),
00198                                thePath._tokens.end( ));
00199 
00200                 return CdbPathName( tokens );
00201             }
00202 
00203         } else {
00204 
00205           // Replace the current (invalid) path with the specified one.
00206           //
00207           // This scenariou can be used when a temporary path object gets
00208           // created during manipulations with the path.
00209           //
00210           // NOTE: Unlike the previous scenario (of the valid current path)
00211           //       the other path can be both absolute and relative one.
00212 
00213             return CdbPathName( thePath );
00214         }
00215     }
00216 
00217   // Return a non-valid path otherwise
00218 
00219     return CdbPathName( );
00220 }
00221 
00222 CdbPathName
00223 CdbPathName::operator+( const char* theStr ) const
00224 {
00225     return operator+( CdbPathName( theStr ));
00226 }
00227 
00228 CdbPathName
00229 CdbPathName::operator+( const std::string& theStr ) const
00230 {
00231     return operator+( CdbPathName( theStr ));
00232 }
00233 
00234 CdbIItr<CdbPathName>*
00235 CdbPathName::iterator( ) const
00236 {
00237     return new CdbPathNameItr( *this );
00238 }
00239 
00240 void
00241 CdbPathName::dump( std::ostream&      theStream,
00242                    const std::string& thePrefix ) const
00243 {
00244     theStream << thePrefix << "_isValid     = " << ( _isValid     ? "Yes" : "No" ) << endl
00245               << thePrefix << "_isAbsolute  = " << ( _isAbsolute  ? "Yes" : "No" ) << endl
00246               << thePrefix << "_isRoot      = " << ( _isRoot      ? "Yes" : "No" ) << endl
00247               << thePrefix << "_isComposite = " << ( _isComposite ? "Yes" : "No" ) << endl
00248               << thePrefix << "_name        = \"" << ( _name.empty() ? "" : _name ) << "\"" << endl
00249               << thePrefix << "_tokens      = ";
00250 
00251     for( std::vector< std::string >::const_iterator itr = _tokens.begin( );
00252                                                     itr < _tokens.end( );
00253                                                   ++itr ) {
00254         if( itr == _tokens.begin( )) {
00255             theStream << "\"" << (*itr) << "\"" << endl;
00256         } else {
00257             theStream << thePrefix << "               \"" << (*itr) << "\"" << endl;
00258         }
00259     }
00260     if( _tokens.empty( )) theStream << endl;
00261 }
00262 
00263 bool
00264 CdbPathName::translateStringIntoTokens( const char* theStr )
00265 {
00266     if( 0 == theStr ) return false;
00267 
00268   // Break the specified string down to tokens and populate the object's
00269   // list of tokens.
00270 
00271     const char* begin   = theStr;
00272     const char* end     = theStr + strlen( theStr );
00273     char*       current = const_cast<char*>( theStr );
00274 
00275     std::vector< std::string > vectorOfTokens;
00276 
00277     while( current < end ) {
00278 
00279         char* next = strstr( current, separator( ));
00280         if( 0 == next ) {
00281 
00282           // Treat the rest of the input string as the last element
00283 
00284             vectorOfTokens.push_back( std::string( current, end - current ));
00285             current = const_cast<char*>( end );
00286 
00287         } else {
00288 
00289           // A separator is found. Now we are going to see how to interpret it.
00290           // This depends on a position of the found separator in the string.
00291 
00292             if( current == next ) {
00293 
00294               // Separator at the current position
00295 
00296                 if( begin == next ) {
00297 
00298                   // The ROOT DIR found - remember it.
00299 
00300                     vectorOfTokens.push_back( std::string( separator( ), strlen( separator( ))));
00301 
00302                 } else {
00303 
00304                   // A regular separator found - ignore it
00305                   //
00306                   // NOTE: We treat repeating separators as a single one.
00307                   //       The trailing separator is also ignored unless
00308                   //       it's the ROOT DIR.
00309 
00310                     ;
00311                 }
00312 
00313             } else {
00314 
00315               // Another element is found - store it
00316 
00317                 vectorOfTokens.push_back( std::string( current, next - current ));
00318                 current = next;
00319             }
00320 
00321           // Skip the separator
00322 
00323             current += strlen( separator( ));
00324         }
00325     }
00326     _tokens = vectorOfTokens;
00327 
00328   // A final step - try rebuild the full path name.
00329 
00330     return rebuildFullPath( );
00331 }
00332 
00333 bool
00334 CdbPathName::rebuildFullPath( )
00335 {
00336   // The operation will make a sense if a valid list of tokens is already loaded.
00337 
00338     unsigned int nTokens = _tokens.size( );
00339 
00340     if( 0 == nTokens ) return false;
00341 
00342   // Rebuild the path
00343 
00344     std::string result = "";
00345 
00346     for( unsigned int i = 0; i < nTokens; ++i ) {
00347 
00348       // Prepend a separator before any token except:
00349       //
00350       //   (1) the very first token for any path value to avoid mis-interpreting
00351       //       the current path as the ROOT one.
00352       //
00353       //   (2) the second token if the current path is an absolute one. In this case
00354       //       the path already begins with the separator, which is also the ROOT path.
00355 
00356         if( 0 == i ) {
00357 
00358             ;   // (1)
00359 
00360         } else if(( 1 == i ) && ( _tokens[0] == separator( ))) {
00361 
00362             ;   // (2)
00363 
00364         } else {
00365 
00366             result += separator( );
00367         }
00368         result += _tokens[i];
00369     }
00370 
00371   // Update the internal state
00372 
00373     _name = result;
00374 
00375     return true;
00376 }
00377 
00378 void
00379 CdbPathName::recalculateDescriptorFlags( )
00380 {
00381   // The object must be loaded and be in a valid state
00382 
00383     if( !_isValid ) return;
00384     if( 0 == _tokens.size( )) return;
00385 
00386   // Proceed
00387 
00388     _isAbsolute  = _isValid && ( _tokens[0] == separator( ));
00389     _isRoot      = _isValid && _isAbsolute && ( 1 == _tokens.size( ));
00390     _isComposite = _isValid && ( _tokens.size( ) > 1 );
00391 }
00392 
00393 /////////////////
00394 // End Of File //
00395 /////////////////

Generated on Mon Dec 5 18:22:08 2005 for CDB by doxygen1.3-rc3