#ifndef NEWBANKS_HEADER_H #define NEWBANKS_HEADER_H /* ************************************************************** ** Some templates for bank access ** ************************************************************** This files reside in /afs/desy.de/user/b/blist/h1/c++ Comments, questions, suggestions, BUGS to Benno List blist@mail.desy.de General remarks: o All banks are assumed to be located on the main BOS common BCS o Workbanks are not implemented o After garbage collection, all banks must be reopened Three types are provided: o Bank: Generic bank, no special structure, base type of the other bank types o StrBank ("Structured Bank"): Bank with a structure defined by a class "row" o Table: Bank with Miniheader and row structure given by a class "row" Type Bank --------- A Bank is opened with Bank bank ("BANK", no); // open bank "BANK", no. This defines a bank "bank", and opens it with nlink ("BANK", no). The argument "no" can be left out, it is then assumed to be the default, 0. If the bank is not present in the BOS common, the object "name" exists, but the bank is not open. If the bank is not open, only the following methods can be applied: int i = bank.is_open(); // 1 if bank is open, 0 otherwise int i = bank.length(); // Returns bank length; 0 if bank is not open. If the bank is indeed open, the following methods can be applied: char *name = bank.name(); // returns pointer to bank name (not 0-terminated!) int no = bank.number(); // returns bank number int i = bank.i(n); // returns n-th integer value of bank. // This access function is range-checked. float r = bank.r(n); // returns n-th float value of bank. // This access function is range-checked. After garbage collection, a bank can be reconnected with bank.reopen ("BANK", no); Name and number must be given a second time because they are not stored. Banks can be created (by means of a call to nbank) by Bank bank ("BANK", no, l); // create bank "BANK", no with with length "l" bank.create ("BANK", no, l); // create bank "BANK", no with with length "l" Type StrBank ----------------- After defining a class (or structure) row, e.g.: class examplerow { public: int a; float b; float getab () const {return a*b;} }; one can define a strcutured bank StrBank example ("EXAM", 0); and access it the following way: examplerow r = *example; // copy contents of bank EXAM to r; int a = example.a; // Get value of a float b = example.b; // Get value of b float ab = example.getab(); // Access function defined in examplerow Type Table --------------- After defining a class (or structure) row, like in the example above, one can define a Table with the row structure given by "row": Table example ("EXAM", 0); and access it the following way: examplerow r = example[n]; // copy contents of n-th row of table // EXAM to r; int a = example[n].a; // Get value of a of n-th row float b = example[n].b; // Get value of b of n-th row float ab = example[n].getab(); // Access function defined in examplerow Type TablePointer ---------------------- For pointers to bank rows a type TablePointer can be used. For this type to be usable, a global definition of the bank name and number is necessary: char TablePointer::name [5] = "EXAM"; int TablePointer::no = 0; Now pointers can be defined which point to a row of bank EXAM: TablePointer examp = n; // Pointer to row n; The contents of this row can be accessed in two ways: o Using the pointer as array index: Table example ("EXAM", 0); examplerow r = example[examp]; // copy contents of n-th row of table // EXAM to r; int a = example [examp].a; // Get value of a of n-th row o Using the pointer like a real pointer: examplerow r = *examp; // copy contents of n-th row of table // EXAM to r; int a = examp->a; // Get value of a of n-th row The usual application of TablePointer is within the definition of another bank: class anotherrow: { public: int c; TablePointer l_example; }; Now one can access the bank EXAM from bank ANOT: Table another ("ANOT", 0); int c = another[n].c; // value c of n-th row int l = another[n].l_example; // value of link (rownumber // in EXAM bank) of n-th row int a = example [another[n].l_example].a; // use link as index to float b = another[n].l_example->b; // EXAM bank. Fast, but // it cannot be checked // if link really points to // EXAM bank row r1 = example [another[n].l_example]; // use link as pointer to row r2 = *another[n].l_example; // row of EXAM bank. Slower, // because "nlink" must be // called, but more // reliable, because access // to correct bank is // guaranteed. float ab = r1.getab(); */ #include "4vectors.h" #include "h1util.h" #include "bos.h" #include #include #include extern bcstype& bcs; class BankError { public: virtual void printmessage () const { cout << "BankError\n"; } BankError () { cout << "BankError instantiated.\n"; } // ~BankError () { // cout << "BankError out of scope.\n"; // } }; class StrBankLengthError: public BankError { public: char name [4]; int no; inline StrBankLengthError (char *c, int n) { strncpy (name, c, 4); no = n; cerr << "StrBankLengthError occured for bank "; cerr.write (name, 4); cerr << " " << no << "\n"; } virtual void printmessage () const { cout << "StrBankLengthError, bank "; cout.write (name, 4); cout << " " << no << "\n"; } }; class TableStructureError: public BankError { public: char name [4]; int no; int columns; int rows; int length; inline TableStructureError (char *c, int n, int co, int r, int l) { strncpy (name, c, 4); no = n; columns = co; rows = r; length = l; cerr << "TableStructureError occured for bank "; cerr.write (name, 4); cerr << " " << no << "\n"; cerr << "columns=" << columns << ", rows=" << rows << ", length=" << length << "\n"; } virtual void printmessage () const { cout << "TableStructureError, for bank "; cout.write (name, 4); cout << " " << no << "\n"; cout << "columns=" << columns << ", rows=" << rows << ", length=" << length << "\n"; } }; class TableWidthError: public BankError { public: char name [4]; int no; int columns; int rowsize; inline TableWidthError (char *c, int n, int co, int s) { strncpy (name, c, 4); no = n; columns = co; rowsize = s; cerr << "TableWidthError occured for bank "; cerr.write (name, 4); cerr << " " << no << "\n"; cerr << "columns=" << columns << ", rowsize=" << rowsize << "\n"; } virtual void printmessage () const { cout << "TableWidthError, for bank "; cout.write (name, 4); cout << " " << no << "\n"; cout << "columns=" << columns << ", rowsize=" << rowsize << "\n"; } }; class BankNotOpen: public BankError { public: inline BankNotOpen () { cerr << "BankNotOpen\n"; } virtual void printmessage () const { cout << "BankNotOpen\n"; } }; class BankIndexWrong: public BankError { public: char name [4]; int no; int index; inline BankIndexWrong (char *c, int n, int i) { strncpy (name, c, 4); no = n; index = i; cerr << "BankIndexWrong, bank "; cerr.write (name, 4); cerr << " " << no << ", index=" << index << "\n"; } void printmessage () const { cout << "BankIndexWrong, bank "; cout.write (name, 4); cout << " " << no << ", index=" << index << "\n"; } }; class Bank { protected: int base; public: inline Bank (char name [4], int no=0) { // cout << "Bank "; cout.write (name, 4); cout << " no. " << no << " has been opened.\n"; base = nlink (name, no); } inline int create (char name [4], int no, int Length) { // cout << "Bank "; cout.write (name, 4); cout << " no. " << no << " is being created.\n"; base = nbank (name, no, Length); return base != 0; } inline Bank (char name [4], int no, int Length) { // cout << "Bank "; cout.write (name, 4); cout << " no. " << no << " is being created.\n"; base = nbank (name, no, Length); } inline void reopen (char name [4], int no=0) { // cout << "Bank "; cout.write (name, 4); cout << " no. " << no << " has been reopened.\n"; base = nlink (name, no); } inline ~Bank () { // cout << "Bank has gone out of scope.\n"; } inline int length() const {return base ? bcs.iw [base-1] : 0;} inline int is_open() const {return base > 0;} inline char *name() const {return base > 0 ? (char*)bcs.iw [base-4] : 0;} inline int number() const {return base > 0 ? bcs.iw [base-3] : -1;} inline int i (int n) const { if (base) { if (n > 0 && n <= length()) { return bcs.iw [base-1+n]; } else { throw BankIndexWrong (name(), number(), n); cout << "Exception BankIndexWrong not thrown:\nBankIndexWrong, bank "; cout.write (name(), 4); cout << " " << number() << ", index=" << n << "\n"; } } else { throw BankNotOpen(); cout << "Exception BankNotOpen not thrown!\n"; } } inline float r (int n) const { if (base) { if (n > 0 && n <= length()) { return bcs.rw [base-1+n]; } else { throw BankIndexWrong (name(), number(), n); cout << "Exception BankIndexWrong not thrown:\nBankIndexWrong, bank "; cout.write (name(), 4); cout << " " << number() << ", index=" << n << "\n"; } } else { throw BankNotOpen(); cout << "Exception BankNotOpen not thrown!\n"; } } friend Bank CreateBank (char[4], int, int) ; friend class TablePointer; }; template class StrBank: public Bank { public: inline StrBank (char name [4], int no=0): Bank (name, no) { cout << "StrBank " << name << " no. " << no << " has been opened.\n"; // Check that bank is at least as long as its structure demands if (base && length() < sizeof(row) / sizeof (int)) { throw StrBankLengthError(name, no); cout << "Exception StrBankLengthError not thrown:\nStrBankLengthError occured for bank "; cout.write (name, 4); cout << " " << no << "\n"; } } inline ~StrBank () { // cout << "StrBank has gone out of scope.\n"; } row *operator -> () const {return base ? (row*)(bcs.iw+base) : 0;} row &operator * () const { if (base) return *(row*)(bcs.iw+base); else { throw BankNotOpen(); cout << "Exception BankNotOpen not thrown!\n"; } } }; template class TablePointer { protected: static char name [5]; static int no; public: int rownumber; public: TablePointer (int i=0) {rownumber = i;} inline void SetBank (char n [5], int i=0) { strncpy (name, n, 5); no = i; } int rowno() const {return rownumber;} operator int () const {return rownumber;} row &operator *() const; row *operator -> () const; }; template row &TablePointer::operator *() const { if (rownumber >= 1) { Table T (name, no); return T [rownumber]; } else { throw BankIndexWrong (name, no, rownumber); cout << "Exception BankIndexWrong not thrown:\nbankIndexWrong, bank "; cout.write (name, 4); cout << " " << no << ", index=" << rownumber << "\n"; } } template row *TablePointer::operator -> () const { if (rownumber >= 1) { Table T (name, no); if (T.is_open()) { return &T [rownumber]; } else { throw BankIndexWrong (name, no, rownumber); cout << "Exception BankIndexWrong not thrown:\nBankIndexWrong, bank "; cout.write (name, 4); cout << " " << no << ", index=" << rownumber << "\n"; return 0; } } else { throw BankIndexWrong (name, no, rownumber); cout << "Exception BankIndexWrong not thrown:\nBankIndexWrong, bank "; cout.write (name, 4); cout << " " << no << ", index=" << rownumber << "\n"; return 0; } } template class Table: public Bank { protected: inline int rows_() const {return bcs.iw [base+1];} inline int columns_() const {return bcs.iw [base];} public: inline Table (char name [4], int no=0): Bank (name, no) { // cout << "Table "; cout.write (name, 4); cout << " no. " << no << " has been opened.\n"; // Check consistency of miniheader int c = columns(); if (base && length() != rows()*c + 2) { throw TableStructureError (name, no, c, rows(), length()); cout << "Exception TableStructureError not thrown:\nTableStructureError, bank "; cout.write (name, 4); cout << " " << no << "\n columns=" << c << ", rows=" << rows() << ", length=" << length() << "\n"; } // Check number of columns if (base && c < sizeof (row)/sizeof(int)) { throw TableWidthError (name, no, c, sizeof(row)/sizeof(int)); cout << "Exception TableWidthError not thrown:\nTableWidthError, bank "; cout.write (name, 4); cout << " " << no << "\n columns=" << c << ", rowsize=" << sizeof(row)/sizeof(int) << "\n"; } } inline int create (char name [4], int no, int Rows); inline Table (char name [4], int no, int Rows): Bank (name, no) { // cout << "Table "; cout.write (name, 4); cout << " no. " << no << " is being created.\n"; create (name, no, Rows); } inline ~Table () { // cout << "Table has gone out of scope.\n"; } inline int rows() const {return base ? rows_() : 0;} inline int columns() const {return base ? columns_() : 0;} row &operator [] (int i) const; }; template inline int Table::create (char name [4], int no, int Rows) { int Columns = sizeof (row) / sizeof (int); base = nbank (name, no, 2+Rows*Columns); if (base) { bcs.iw [base] = Columns; bcs.iw [base+1] = Rows; row r; for (int i = 1; i <= Rows; i++) *((row *)&bcs.iw [base+2+(i-1)*Rows]) = r; } return base != 0; } template row &Table::operator [] (int i) const { if (base) { if (i >= 1 && i <= rows()) { return *(row *)(bcs.iw+base+2+(i-1)*columns_()); } else { throw BankIndexWrong (name(), number(), i); cout << "Exception BankIndexWrong not thrown:\nBankIndexWrong, bank "; cout.write (name(), 4); cout << " " << number() << ", index=" << i << "\n"; } } else { throw BankNotOpen(); cout << "Exception BankNotOpen not thrown!\n"; } } #endif