// ---------------------------------------------------------------------- // // TupleNameTag -- implementation of the name tag parsing. // // This simple structure is used to parse a column name for a ntuple // that can be of the form "[block_name::]column_name" // or "[block_name::]column_name(1 , ...)" if withIndices is true // The block name is an alpha numerical string whithout any white space. // The column name is as defined by HBook. // isValid is set to false the name tag parsed was not correctly formed. // // The following method are defined in this file: // TupleNameTag() // TupleNameTag(const string& tag) // init(const string& tag) // bool isValid() // bool isValidBlockName(const string& name) // bool isValidColumnName(const string& name) // string block() // string column() #include "HepTuple/TupleNameTag.h" #include #include USING( std::string ) ZM_BEGIN_NAMESPACE( zmht ) /* namespace zmht { */ const string TupleNameTag::NameTagDelimiter("::"); const string TupleNameTag::IndicesStart("("); const string TupleNameTag::IndicesDelimiter(","); const string TupleNameTag::IndicesStop(")"); /* Gnu misnames the erase function :( */ // But egcs got it right :) #if defined(__GNUC__) && (__GNUC__ < 3) && (__GNUC_MINOR__ < 90) #define erase remove #endif // empty constructor to be called by sub-class TupleNameTag::TupleNameTag() : _block(""), _column(""), _indices(""), _indicesArray(0), _indicesSize(0), _allowIndices(false) { } // Public constructor. Run init to actually set _block and _column // to their proper value. // Using an init function allow for sub-class to use the same // initialization sequence with virtual functions!!! /* TupleNameTag::TupleNameTag(const string& tag, bool withIndices) : _block(""), _column(""), _indices(""), _indicesArray(0), _indicesSize(0), _allowIndices(false) { init(tag,withIndices); } */ // Copy Constructor TupleNameTag::TupleNameTag(const TupleNameTag& tag) : _block(tag._block), _column(tag._column), _indices(tag._indices), _indicesArray(NULL), _indicesSize(tag._indicesSize), _allowIndices(tag._allowIndices) { if ( _indicesSize > 0 ) { _indicesArray = new int[_indicesSize]; for( int i=0; i<_indicesSize; i++) { _indicesArray[i] = tag._indicesArray[i]; } } } TupleNameTag::~TupleNameTag() { if ( _indicesArray != NULL ) { delete _indicesArray; } } // function that actually set the block and column // name to there proper values. // ALL sub-class need to call this function in their // constructor. This is to be able to use correctly // the two following virtual function. void TupleNameTag::init( string tag, bool withIndices, TupleNameTag& object ) { object._allowIndices = withIndices; // We assume that _block, _column, _indices, _indicesArray // have been initialized to "","","" and 0. int xpos = tag.find(NameTagDelimiter); if ( xpos != -1 ) { object._block = tag.substr(0,xpos); if ( ! isValidBlockName(object._block) ) { object._block.erase(); object._column.erase(); return; } tag = tag.substr(xpos+NameTagDelimiter.length()); } else { object._block.erase(); } int ppos = tag.find(IndicesStart); if ( ppos != -1 ) { if ( !object._allowIndices ) { object._block.erase(); object._column.erase(); object._indices.erase(); return; } if ( ! setIndices(tag.substr(ppos), object) ) { object._block.erase(); object._column.erase(); object._indices.erase(); return; } tag = tag.substr(0,ppos); } else { object._indices.erase(); } if ( isValidColumnName(tag) ) { object._column = tag; } else { object._column.erase(); } } bool TupleNameTag::isValid() const { return ( _column.length() != 0 ); } const string& TupleNameTag::block() const { return _block; } const string& TupleNameTag::column() const { return _column; } string TupleNameTag::tag() const { if ( _block.empty() ) { return _column; } else { return _block + NameTagDelimiter + _column; } } // check if name contain a white space. bool TupleNameTag::isValidBlockName( const string& name) const { for (std::string::size_type i = 0; i < name.length(); i++) { if (isspace(name[i])) { return false; } char c = name[i]; if (! (isalnum(c) || (c == '_') || (c == '#')) ) { return false; } } return true; } // check if name contain a white space. bool TupleNameTag::isValidColumnName( const string& name) const { for (std::string::size_type i = 0; i < name.length(); i++) { if (isspace(name[i])) { return false; } char c = name[i]; if (! ( isalnum(c) || (c == '_') || (c == '#') ) ) { return false; } } return true; } // for atoi #include bool TupleNameTag::setIndices(const string& index, TupleNameTag& object) { int openPar = -1; string arrayList; openPar = index.find(IndicesStart); if ( openPar == -1 || openPar != 0 ) { return false; } else { arrayList = index.substr(openPar+1); } int allocatedSize = 3; if ( object._indicesArray != NULL ) { allocatedSize = object._indicesSize; } else { object._indicesArray = new int[allocatedSize]; } object._indicesSize = 0; int j = 0; for (std::string::size_type i = 0; i < arrayList.length(); i++) { std::string::size_type begin = i; if ( !( isdigit(arrayList[i])) ) { return false; } while ( isdigit(arrayList[i]) && i < arrayList.length() ) { i++; }; if ( j+1 > allocatedSize ) { allocatedSize *= 2; int *temp = new int[allocatedSize]; for ( int k = 0; k < j ; k++ ) temp[j] = object._indicesArray[j]; delete object._indicesArray; _indicesArray = temp; } object._indicesArray[j] = atoi(arrayList.substr(begin,i-begin).c_str()); j++; if ( ! arrayList[i] == *(IndicesDelimiter.data()) ) { if ( ! arrayList[i] == *(IndicesStop.data()) && (i+1==arrayList.length()) ) { return false; } } } object._indicesSize = j; object._indices = arrayList.substr(0,arrayList.length()-1); return true; } string TupleNameTag::indices() const { return _indices; } ZM_END_NAMESPACE( zmht ) /* } // namespace zmht */