// Open for input, using explicit open mode. RDB irdb( "input.rdb", ios::in ); // Open for input, using default open mode. RDB irdb( "input.rdb" ); // Open for input, using a pointer to an istream. RDB irdb( &cin ); // Open for output. The explicit open mode is required, otherwise // it will default to open for input. RDB ordb( "output.rdb", ios::out ); // Create the object with no file or stream specified. RDB ordb; // Specify the stream via the RDB::open(ostream) method. ordb.open( &cout ); // Or, specify the file via the RDB::open(string,ios::openmode) method. ordb.open( "output.rdb", ios::out );
irdb.open( &cin ); for ( size_t idx = 0; idx < irdb.nColumns( ); idx++ ) { cout << idx << ": " << irdb.getColumn( idx )->getName( ) << endl; } // This could take awhile... cout << "There are " << irdb.nRows( ) << " rows" << endl;
To access an existing comment or column the user may reference the comment or column by index. Comments/Columns are indexed beginning at 0. If the user is requesting an index beyond the range of comments/columns contained in the RDB object, an RDBErrNotFound object is thrown or RDB::_errno is set. If the user is adding a comment/column and specifies an index beyond the range contained in the RDB object, the comment/column is added to the end of the list.
It is important to note that comments are returned as references to the underlying object while columns are returned as pointers to the underlying object. This is to allow columns of different datatypes to be stored in the same RDB object container.
// Foreach column... for ( size_t idx = 0; idx < irdb.nColumns( ); idx++ ) { // Print the name and definition. cout << irdb.getColumn( idx )->getName( ) << " | " << irdb.getColumn( idx )->getDef( ) << endl; // Note the use of the '->', pointer dereference, operator. } // Set the error handling behavior to throw exceptions. irdb.setThrow( true ); try { // Ask for on comment beyond what we have. irdb.getComment( irdb.nComments( ) ); // NOTE: the use of the '.', dot, operator. } catch ( RDBErr& rdberr ) { // Catch the exception that will be thrown. cerr << "This will fail because comment indices start at 0." << endl; } // Here we check how many comments there are and then add one to // the end. size_t ncomments_before = irdb.nComments( ); irdb.setComment( "Add one comment to the end..." ); if ( ncomments_before != irdb.nComments( ) ) { cout << "Now there's one more comment..." << endl; }
It is also possible to access an existing comment/column or add a new comment/column by specifying the comment keyword/column name. Once, again if the comment/column is being added and no matching keyword/name is found, a new comment/column is added to the end of the list. If the comment/column is being returned and not matching keyword/name is found, an RDBErrNotFound object is thrown or RDB::_errno is set.
RDBColumn* col = irdb.getColumn( "x_err" );
Comments and columns are stored in RDBComment and RDBColumn objects respectively. The RDB object provides access to the RDBComment and RDBColumn objects it contains. For access to the constituent parts of either a comment or a column, the user may use the respective class interfaces.
// To access a column name, first get the column then ask it for // its name... irdb.getColumn( 3 )->getName( ); // To reset a comment header variable, first get the comment then // set its value... irdb.getComment( "foo" ).setValue( "Not bar" );
It is important to note that if the RDB object was opened with a stream, rather than a filename, the stream must the ability to seek. Rewinding an RDB object opened with cin or cout will fail.
double sum; int cnt; string group; irdb.getColumn( "break" )->setGroup( true ); while ( irdb.read( ) ) { if ( irdb.newGroup( ) ) { if ( irdb.getColumn( "_NR" )->getDataLong( ) ) { // Write out old group's stats... cout << "Avg for group " << group << " == " << sum / cnt << endl; } // Reset accumulators... sum = 0.0; cnt = 0; group = irdb.getColumn( "break" )->getDataString( ); } // Accumulate statistics on other columns... sum += irdb.getColumn( "data" )->getDataDouble( ); cnt++; }
If the filename constructor is used with a filename specified, then the default is to open the file for reading. The user may explicitly set the open mode for output though.
The copy constructor does a shallow copy of the object provided as an argument. The new object is linked to the argument. Modification to the first objects RDBColumns will show up in the second objects RDBColumns.
Each method allows the user to either specify the comment index, thereby replacing the existing RDBComment, or to leave out the index, thereby appending a new RDBComment to the end of the header.
RDBComment comment( "#: comment_variable = comment value" ); rdb.setComment( comment );
Here we overwrite the second comment with a new one.
rdb.setComment( comment, 2 );
Each method has two signatures. The first signature allows the user to specify which comment to act upon by its index in the header. The second signature allows the user to specify which comment to act upon via keyword. It should be noted that if the comment does not explicityly contain a keyword = value construct no keyword is stored for the comment.
Each signature throws an exception if a comment matching either the index or keyword is not found. For functions specifying the index, an IndexOutOfRangeException is thrown. For the functions specifying the keyword, a KeyNotFoundException is thrown.
Each method allows the user to either specify either the column index or the column name. The user may provide an entire RDBColumn object, as is the case with the RDB::setColumn() methods. If the index is out of range or the name is not the name of an existing column, the RDBColumn object is added to the RDB. Otherwise, the RDBColumn object replaces the existing object.
Each in turn throws an exception if the column is not found. In the case of columns specified by index, an IndexOutOfRangeException is thrown. In the cass of columns specified by name, a KeyNotFoundException is thrown. The methods which provide a column definition can also throw BadHeaderException if the definition is not of the proper form.
Each method allows the user to either specify either the column index or the column name.
Each in turn throws an exception if the column is not found. In the case of columns specified by index, an IndexOutOfRangeException is thrown. In the cass of columns specified by name, a KeyNotFoundException is thrown.
RDB irdb(&cin); RDB ordb(&cout); // This part takes a pointer to the column from input and gives it // to the output. Now they point at the same RDBColumn... for ( int i = 0; i < input.nColumns( ); i++ ) ordb.setColumn( irdb.getColumn( i ) ); ordb.writeHeader( ); // Because the two tables share pointers to the same RDBColumns, a // call to read sets the values of the data in the output as well // as the input. So now, a call to write will write the values // from the read. while ( irdb.read( ) ) ordb.write( );