//===========================================================================// // Purpose : Template version for a regular expression list iterator class. // This class handles applying a name string, possibly defined // using regular expression constructs, to a match list template // object, returning 0 or more indices to list elements with // matching name strings. // // Inline methods include: // - TCT_RegExpIter, ~TCT_RegExpIter // - HasRegExp // - IsValid // // Public methods include: // - Init // - Next // //===========================================================================// #ifndef TCT_REGEXP_ITER_H #define TCT_REGEXP_ITER_H #include #include #include using namespace std; #include "RegExp.h" #include "TIO_PrintHandler.h" #include "TC_Typedefs.h" // Define a default invalid index value #define TCT_REGEXP_INDEX_INVALID SIZE_MAX //===========================================================================// // Purpose : Class declaration // Author : Jeff Rudolph //---------------------------------------------------------------------------// // Version history // 05/01/12 jeffr : Original //===========================================================================// template< class T > class TCT_RegExpIter_c { public: TCT_RegExpIter_c( void ); TCT_RegExpIter_c( const char* pszRegExp, const T& matchList ); TCT_RegExpIter_c( const string& srRegExp, const T& matchList ); ~TCT_RegExpIter_c( void ); bool Init( const char* pszRegExp, const T& matchList ); bool Init( const string& srRegExp, const T& matchList ); size_t Next( void ); bool HasRegExp( void ) const; bool IsValid( void ) const; private: RegExp* pregExp_; // Ptr to object for RE pattern matching string* psrRegExp_; // Ptr to simple RE pattern string T* pmatchList_; // Ptr to a match list for pattern matching size_t matchIndex_; // Current index to match list for matching size_t nextIndex_; // Next index to match list for matching bool isValid_; // true => object has been initialized; }; //===========================================================================// // Purpose : Class inline definition(s) // Author : Jeff Rudolph //---------------------------------------------------------------------------// // Version history // 05/01/12 jeffr : Original //===========================================================================// template< class T > inline TCT_RegExpIter_c< T >::TCT_RegExpIter_c( void ) : pregExp_( 0 ), psrRegExp_( 0 ), pmatchList_( 0 ), matchIndex_( TCT_REGEXP_INDEX_INVALID ), nextIndex_( 0 ), isValid_( false ) { } //===========================================================================// template< class T > inline TCT_RegExpIter_c< T >::TCT_RegExpIter_c( const char* pszRegExp, const T& matchList ) : pregExp_( 0 ), psrRegExp_( 0 ), pmatchList_( 0 ), matchIndex_( TCT_REGEXP_INDEX_INVALID ), nextIndex_( 0 ), isValid_( false ) { this->Init( pszRegExp, matchList ); } //===========================================================================// template< class T > inline TCT_RegExpIter_c< T >::TCT_RegExpIter_c( const string& srRegExp, const T& matchList ) : pregExp_( 0 ), psrRegExp_( 0 ), pmatchList_( 0 ), matchIndex_( TCT_REGEXP_INDEX_INVALID ), nextIndex_( 0 ), isValid_( false ) { this->Init( srRegExp, matchList ); } //===========================================================================// template< class T > inline TCT_RegExpIter_c< T >::~TCT_RegExpIter_c( void ) { delete this->pregExp_; delete this->psrRegExp_; } //===========================================================================// template< class T > inline bool TCT_RegExpIter_c< T >::HasRegExp( void ) const { return( this->pregExp_ ? true : false ); } //===========================================================================// template< class T > inline bool TCT_RegExpIter_c< T >::IsValid( void ) const { return( this->isValid_ ); } //===========================================================================// // Method : Init // Purpose : Initialize this object for regular expression pattern // matching based on the given regular expression string // and given match list used for pattern matching. // Author : Jeff Rudolph //---------------------------------------------------------------------------// // Version history // 05/01/12 jeffr : Original //===========================================================================// template< class T > bool TCT_RegExpIter_c< T >::Init( const char* pszRegExp, const T& matchList ) { string srRegExp( pszRegExp ? pszRegExp : "" ); return( this->Init( srRegExp, matchList )); } //===========================================================================// template< class T > bool TCT_RegExpIter_c< T >::Init( const string& srRegExp, const T& matchList ) { bool ok = true; // Reset object state (object may have been used by a previous pattern) delete this->pregExp_; this->pregExp_ = 0; delete this->psrRegExp_; this->psrRegExp_ = 0; this->pmatchList_ = const_cast< T* >( &matchList ); this->matchIndex_ = TCT_REGEXP_INDEX_INVALID; this->nextIndex_ = 0; // Make regular expression object or simple string, whichever is needed string srRegExp_( srRegExp ); const char* pszSpecialChars = "^.?[]+*$"; if ( srRegExp_.find_first_of( pszSpecialChars ) != string::npos ) { size_t escape = srRegExp_.find( '\\' ); while (( escape != string::npos ) && ( escape < srRegExp_.length( ) - 1 )) { srRegExp_.replace( escape, 2, "" ); escape = srRegExp_.find( '\\' ); } } if ( srRegExp_.find_first_of( pszSpecialChars ) != string::npos ) { // Regular expression string may require 'pattern-matching' this->pregExp_ = new TC_NOTHROW RegExp( srRegExp.data( )); TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( ); ok = printHandler.IsValidNew( this->pregExp_, sizeof( RegExp ), "TCT_RegExpIter_c< T >::Init" ); if ( ok ) { if ( !this->pregExp_->IsValidRE( ) ) { printHandler.Error( "Invalid regular expression '%s', pattern is illegal!\n", TIO_SR_STR( srRegExp )); ok = printHandler.IsWithinMaxErrorCount( ); delete this->pregExp_; this->pregExp_ = 0; } } } else { // Simple string does not have to be 'pattern-matched' this->psrRegExp_ = new TC_NOTHROW string( srRegExp ); TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( ); ok = printHandler.IsValidNew( this->psrRegExp_, sizeof( string ), "TCT_RegExpIter_c< T >::Init" ); } this->isValid_ = ok; return( ok ); } //===========================================================================// // Method : Next // Purpose : Apply the current regular expression to the current // match list, returning an index to the next element in // the current match list with a matching string // Author : Jeff Rudolph //---------------------------------------------------------------------------// // Version history // 05/01/12 jeffr : Original //===========================================================================// template< class T > size_t TCT_RegExpIter_c< T >::Next( void ) { if ( this->pregExp_ ) { // Using 'complex' pattern matching (ie. with special characters) this->matchIndex_ = TCT_REGEXP_INDEX_INVALID; while (( this->matchIndex_ == TCT_REGEXP_INDEX_INVALID ) && ( this->nextIndex_ <= this->pmatchList_->GetLength( ) - 1 )) { // Get next string, then apply the current regular expression size_t nextIndex = this->nextIndex_; const char* pszNextString = this->pmatchList_->FindName( nextIndex ); string srNextString( pszNextString ? pszNextString : "" ); size_t matchStart = 0; size_t matchLength = 0; bool match = this->pregExp_->Index( srNextString.data( ), &matchStart, &matchLength ); if ( match && ( srNextString.length( ) == matchLength )) { this->matchIndex_ = this->nextIndex_; } ++this->nextIndex_; } if ( this->matchIndex_ == TCT_REGEXP_INDEX_INVALID ) { delete this->psrRegExp_; this->psrRegExp_ = 0; } } else if ( this->psrRegExp_ ) { // Using 'simple' pattern matching (ie. no special characters) const string& srRegExp = *this->psrRegExp_; this->matchIndex_ = this->pmatchList_->FindIndex( srRegExp ); delete this->psrRegExp_; this->psrRegExp_ = 0; } else { this->matchIndex_ = TCT_REGEXP_INDEX_INVALID; } return( this->matchIndex_ ); } #endif