// ---------------------------------------------------------------------- // // Block.cc - implementation of the accessors, constructors and destructor of // the block class. // // Typical creations of Block look like: // Block* b = new Block(blockName); // b->addColumn(existingColumnPointer); // // The following methods can be found in this file: // string format() : return the chform coresponding to the current list of // column // bool addColumn(Column* newCol) : add a existing column to the block // Block(string name) : construct an empty Block. // string AttribsToChForm(HepAList listOfColumns) // string AttribsToChform(const int nc, const ColumnAttribs* CAs) // both return the chform string representing the // list of ColumnAttribs. The first one is used to // implement Block::format(); // bool lockNoNewColumn() // return if the block and any of its column is locke. // // History: // ??-???-1997 Unknown author Initial creation // 22-Aug-1997 Walter Brown Fixed terminal commas in generated // ChForm strings that had been "removed" by overwriting them with // null bytes rather than by truncating the string: now no excess // commas are generated at all // 30-Sep-1997 Philippe Canal Replace CLHEP lists by standard library // container. Add sort capability on Columns // 21-Feb-2000 Walter Brown Improved C++ standard compliance #include "HepTuple/Block.h" #include "HepTuple/Column.h" #include "HepTuple/HepTrace.h" #include "ZMutility/algorithm" USING( namespace std ) ZM_BEGIN_NAMESPACE( zmht ) /* namespace zmht { */ // *********************************************************************** // // // Constructor and destructor // // *********************************************************************** // Block::Block(HepNtuple *owner, const string& name, Column *col, bool isCaseSensitive) : _columns(), _hepTuple(owner), _isCaseSensitive(isCaseSensitive), _lockNoNewColumn(false), _captured(false), _booked(false), _capturedArray(0), _prePadding(0) { _formatUptodate = false; _name = name; addColumn(col); } Block::Block(HepNtuple *owner, const string& name, bool isCaseSensitive) : _columns(), _hepTuple(owner), _isCaseSensitive(isCaseSensitive), _lockNoNewColumn(false), _captured(false), _booked(false), _capturedArray(0), _prePadding(0) { _formatUptodate = false; _name = name; } // The destructor is empty. Block::~Block() { _capturedArray = (char*)_capturedArray - _prePadding; delete _capturedArray; } Block* Block::duplicate(HepNtuple *newOwner) const { Block *bk = new Block(newOwner,_name,_isCaseSensitive); for ( columnsVec::const_iterator iterateCol(_columnsList.begin()); iterateCol != _columnsList.end(); iterateCol++ ) { bk->addColumn( (*iterateCol)->duplicate(bk) ); } bk->_lockNoNewColumn = _lockNoNewColumn; return bk; } string Block::format() const { if (!_formatUptodate) { _format = AttribsToChform(_columnsList); _formatUptodate = true; } return _format; } // ************************************** // // // // bool Block::addColumn(Column* newCol) // // // // add the column to the block // // // // ************************************** // bool Block::addColumn(Column* newCol) { if ( isLockedNewColumn() ) { ZMthrow(ZMxHepLockedItem( string("Attempt to add column to the locked Block ") +name())); return false; } if ( _isCaseSensitive ) { _columns[newCol->name()] = newCol; } else { string UpperName(newCol->name()); for (string::size_type i=0; i < UpperName.size(); i++) { UpperName[i] = toupper( UpperName[i] ); } _columns[UpperName] = newCol; } _columnsList.push_back(newCol); if ( newCol->getIndex() != "" ) { Column* index = findColumn(newCol->getIndex()); if ( index == NULL ) { ZMthrow(ZMxHepImproperUse(string("No index is present in block ") +name() +string(" for column ")+ newCol->name() )); return false; } index->isIndex(true); } _formatUptodate = false; return true; } // **************************** // // // // int Block::nColumns() const // // // // **************************** // int Block::nColumns() const { return (_columns.size()); } // ******************************************************************* // // // // string Block::AttribsToChform( // // // // generate the HBOOK chForm (a character string) from an // // array of ColumnAttribs // // also, delete[] should be used when the string is no longer needed! // // (maxmium size for the string is 2000 chars as defined by // // CHF_STRING_MAX) // // // // ******************************************************************* // string Block::AttribsToChform( STL_VECTOR(Column*) listOfColumns ) const { // This is a simple converter from vector to array of ColumnAttribs string chf; int size = listOfColumns.size(); for (int i = 0; i < size; i++ ) { if ( i > 0 ) chf += ','; chf += listOfColumns[i]->attributes().format(); //this column is done! }; return chf; } string Block::AttribsToChform( STL_DEQUE(Column*) listOfColumns ) const { // This is a simple converter from vector to array of ColumnAttribs string chf; for (STL_DEQUE(Column*)::const_iterator i(listOfColumns.begin()); ! (i == listOfColumns.end() ); i++ ) { if ( ! (i == listOfColumns.begin()) ) chf += ','; chf += (*i)->attributes().format(); //this column is done! }; return chf; } string Block::AttribsToChform( STL_VECTOR(ColumnAttribs*) listOfColumns ) const { // This is a simple converter from HepAList to array of ColumnAttribs string chf; int size = listOfColumns.size(); for (int i = 0; i < size; i++ ) { if ( i > 0 ) chf += ','; chf += listOfColumns[i]->format(); //this column is done! }; return chf; } string Block::AttribsToChform(const int nc, const ColumnAttribs* CAs) const { string chf_string(""); for (int k=0; k < nc; k++) { if ( k > 0 ) { chf_string += ','; }; chf_string += CAs[k].format(); //this column is done! } // end of big for loop // End of the ColumnAttribs array return(chf_string); } // AttribsToChform() // *************************** // // // // bool isLockedNewColumn() // // // // *************************** // bool Block::isLockedNewColumn() const { bool result = _lockNoNewColumn; for ( columnsVec::const_iterator iterateCol(_columnsList.begin()); iterateCol != _columnsList.end(); iterateCol++ ) { result |= (*iterateCol)->hasBeenStored(); } return result; } // ****************************************** // // // // Column* Block::findColumn(string colName) // // // // ****************************************** // Column* Block::findColumn(const string& arg) const { string colName = arg; if ( _columns.empty() ) return NULL; if ( ! _isCaseSensitive ) { for (string::size_type i=0; i < colName.size(); i++) { colName[i] = toupper( colName[i] ); } } columnsMap::const_iterator it = _columns.find(colName); return it == _columns.end() ? (Column*)NULL : (*it).second; // return (*(_columns.find(colName))).second; } // ********************************************************** // // // // // // capture() : capture all columns through DesignatedValues. // // // // // // ********************************************************** // bool Block::capture() { if ( _captured ) { ZMthrow(ZMxHepAlreadyDone (string("Attempt to capture a block multiple times for one row ") +name()) ); return false; } _captured = true; bool result = true; for ( columnsVec::iterator iterateCol = _columnsList.begin(); iterateCol != _columnsList.end(); iterateCol++ ) { Column *c = (*iterateCol); if ( ! c->isCaptured() ) { result |= c->captureDesignatedValues(); }; } return result; } // **************************** // // // // bool Block::isCaptured() // // // // Return true if the block or // // ALL columns is already been // // captured // // // // **************************** // bool Block::isCaptured() const { bool result = true; for ( columnsVec::const_iterator iterateCol (_columnsList.begin()); iterateCol != _columnsList.end(); iterateCol++ ) { result &= (*iterateCol)->isCaptured(); } return _captured || result; } // ***************************** // // // // bool Block::allowNewColumn() // // // // ***************************** // bool Block::allowNewColumn() { if ( _booked ) { ZMthrow(ZMxHepLockedItem( string("attempt to unlock block ") +name()+ " after it has been booked")); return _lockNoNewColumn; } bool old = _lockNoNewColumn; _lockNoNewColumn = false; if (_capturedArray!=NULL) { delete _capturedArray; } return old; } void Block::clear() { _captured = false; for ( columnsVec::iterator iterateCol = _columnsList.begin(); iterateCol != _columnsList.end(); iterateCol++ ) { (*iterateCol)->clear(); } } // ***************************************************** // // // // void* Block::dataArray(size_type prePadding) // // // // Returns the arrays where read() copy // // the data of all the columns // // // // ***************************************************** // void* Block::dataArray(string::size_type prePadding) { // the prePadding is usefull for HBook. // It allows to insure the correct alignement of the data on // (hopefully) all platform. lockNewColumn(); // create the space to copy the captured data. if ( _capturedArray == NULL) { string::size_type totalSize = capturedDataSize(); _capturedArray = new char[totalSize+prePadding]; _prePadding = prePadding; _capturedArray = (char*)_capturedArray + prePadding; } return _capturedArray; } // *************************** // // // // bool Block::read() // // // // *************************** // bool Block::read() { if (_capturedArray == NULL ) { ZMthrow(ZMxHepPremature("Cannot read before a call to dataArray")); return false; } // fill the data void * current = _capturedArray; for ( columnsVec::iterator iterateCol = _columnsList.begin(); iterateCol != _columnsList.end(); iterateCol++ ) { // set value of column current = (*iterateCol)->copyFromMem(current); // transfer it to destination. (*iterateCol)->read(); } return true; } // *************************** // // // // bool Block::load() // // // // *************************** // bool Block::load() { if (_capturedArray == NULL ) { ZMthrow(ZMxHepPremature("Cannot read before a call to dataArray")); return false; } // fill the data void * current = _capturedArray; for ( columnsVec::iterator iterateCol = _columnsList.begin(); iterateCol != _columnsList.end(); iterateCol++ ) { // set value of column current = (*iterateCol)->copyFromMem(current); } return true; } // ******************************************************** // // // // void* Block::capturedData(size_type prePadding) // // // // Return the address of the array where // // the storing function will look for the // // data for each column // // // // ******************************************************** // void* Block::capturedData(string::size_type prePadding) { // the prePadding is usefull for HBook. // It allows to insure the correct alignement of the data on // (hopefully) all platform. lockNewColumn(); // create the space to copy the captured data. if ( _capturedArray == NULL) { string::size_type totalSize = capturedDataSize(); _capturedArray = new char[totalSize+prePadding]; _prePadding = prePadding; _capturedArray = (char*)_capturedArray + prePadding; } // fill the data void * current = _capturedArray; for ( columnsVec::iterator iterateCol = _columnsList.begin(); iterateCol != _columnsList.end(); iterateCol++ ) { current = (*iterateCol)->copyToMem(current); } return _capturedArray; } string::size_type Block::capturedDataSize() const { string::size_type totalSize = 0; for ( columnsVec::const_iterator iterateCol (_columnsList.begin()); iterateCol != _columnsList.end(); iterateCol++ ) { totalSize += (*iterateCol)->sizeofElem(); }; return totalSize; } // *************************************** // // // // bool Block::hasSomeDestination() const // // // // *************************************** // // return true if at least one of the column has a destination set. bool Block::hasSomeDestination() const { for ( columnsVec::const_iterator iterateCol (_columnsList.begin()); iterateCol != _columnsList.end(); iterateCol++ ) { if ( (*iterateCol)->hasDestination() ) { return true; } }; return false; } // **************************************** // // // // void Block::sortColumn(ColumnLess* cmp) // // // // **************************************** // class wrapper : binary_function { public: ColumnLess* _cmp; wrapper(ColumnLess *cmp) : _cmp(cmp) {}; bool operator()(Column* x, Column* y) const { return _cmp->operator()(x,y); } }; void Block::sortColumn(ColumnLess* cmp) { // We use this extra class instead of having sortColumn being // a templated member function (which would be better). // It helps us keeping the sort(_columnsList.begin(),_columnsList.end(),wrapper(cmp)); _formatUptodate = false; } ZM_END_NAMESPACE( zmht ) /* } // namespace zmht */