1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
#ifndef mbl_table_h
#define mbl_table_h
//:
// \file
// \author Kevin de Souza
// \date 05-Aug-2004
// \brief Container for tabulated data suitable for reading/writing to delimited text files
#include <vcl_map.h>
#include <vcl_iosfwd.h>
#include <vcl_vector.h>
#include <vcl_string.h>
//: Container for tabulated data suitable for reading/writing to delimited text files.
//
// Table comprises a number of columns of double-precision data.
// Each column is headed by a text string (which may contain whitespace but not end-of-line).
// Column headers must be unique.
// Columns are separated by a delimiter character (e.g. "\t").
// The delimiter character must not occur in any of the entries!
// The delimiter character is optional at the end of a row.
// Each row must be terminated by an end-of-line (including the last row).
// Each column of data is stored as a vector of doubles and associated with the column header string.
class mbl_table
{
public:
//: Constructor
// \param delim The delimiter character.
mbl_table(const char delim='\t');
//: Constructor
// \param delim The delimiter character.
// \param headers The column headers (in order).
mbl_table(const char delim,
const vcl_vector<vcl_string>& headers);
//: Return the number of columns
unsigned num_cols() const;
//: Return the number of rows
unsigned num_rows() const;
//: Get the column of data corresponding to a particular heading.
// \param header String identifying the desired column.
// \return true if there is a column with the specified heading.
// \retval column A vector containing the values of the requested column.
bool get_column(const vcl_string& header,
vcl_vector<double>& column) const;
//: Returns true if column exists
bool column_exists(const vcl_string& header) const;
//: Get a specified row of data.
// \param r Index of the desired row.
// \return true if there is a row with the specified index.
// \retval row A vector containing the values of the requested row.
bool get_row(const unsigned& r,
vcl_vector<double>& row) const;
//: Get the list of column headers (in column order).
// \retval headers The list of column headers.
void get_column_headers(vcl_vector<vcl_string>& headers) const;
//: Append a column of data with its own heading.
// \param header String identifying the column.
// \param column A vector containing the values of the column.
// \return true If the column was added.
// \note The new column must be the same length as existing columns.
bool append_column(const vcl_string& header,
const vcl_vector<double>& column);
//: Append an empty column with its own heading.
// \param header String identifying the column.
// \param val Default value to initialize all elements of the new column.
// \return true If the column was added.
// \note The new column will be the same length as existing columns.
bool append_column(const vcl_string& header,
const double val=0);
//: Append a row of data.
// \return true if the row was added.
// \param row A vector containing the values of the new row.
// \note The new row must be the same length as existing rows.
bool append_row(const vcl_vector<double>& row);
//: Append an empty row.
// \return true If the row was added.
// \param val Default value to initialize all elements of the new row.
// \note The new row will be the same length as existing rows.
bool append_row(const double val=0);
//: Set the value of an existing element.
// \param header The string identifying the column to be modified.
// \param r The row index of the element to be modified.
// \param value The new value to use for the modified element.
// \return False if the column does not exist or the row index is not valid.
// \note This function is intended only for existing elements.
bool set_element(const vcl_string& header,
const unsigned r,
const double value);
//: Get the value of an existing element.
// \param header The string identifying the column of interest.
// \param r The row index of the element of interest.
// \return The value of the requested element (undefined if the element
// does not exist).
// \retval success If provided, will be used to indicate whether the
// specified element existed.
// \note This function is intended only for existing elements.
// \note It is recommended that you provide and check the parameter success.
double get_element(const vcl_string& header,
const unsigned r,
bool* success=0) const;
//: Load this table's data from specified text stream.
// Any existing data is lost.
// \return true if table was read successfully from the stream.
bool read(vcl_istream& is);
//: Save this table's data to specified text stream.
void write(vcl_ostream& os) const;
//: Create a new table of subset of columns defined by headers
// \retval new_table a subtable
// \param headers subset of column headers
// \return true if all columns in headers existed in "this" and were copied
bool subtable(mbl_table &new_table, const vcl_vector<vcl_string> &headers) const;
//: Is another table identical to this one?
// \note The normal behaviour of this function is to return false as soon
// as a discrepancy is found. However, if verbosity>=2 this function will
// compare all corresponding elements (providing that the table dimensions match).
bool operator==(const mbl_table& rhs) const;
//: Is another table different from this one?
// \sa operator==()
bool operator!=(const mbl_table& rhs) const;
//: Set the tolerance used to determine whether table entries are equal.
// \param tol The tolerance should be a small positive number, eg 1e-19.
// \param frac Whether the tolerance is applied as a fractional difference.
static void set_tolerance(const double& tol,
const bool& fract=false);
//: Set the level of verbosity used for error output.
// \param v The verbosity should be a small integer, eg -3 to 3.
// Larger values cause more detailed output.
// Default level is 0.
// \note Currently only levels 1 and 2 are defined: level 1 provides some
// feedback for equality testing; level 2 also causes the equality operator
// to check all corresponding elements of a table.
static void set_verbosity(const int& v);
protected:
//: Read a series of characters from the stream until a delimiter character or eol.
// \param is The input stream.
// \return true if a non-empty string was successfully read.
// \retval str The string which was read.
// \retval eol Whether the stream is at end-of-line after reading the string.
// \retval eof Whether the stream is at end-of-file after reading the string.
bool read_delimited_string(vcl_istream& is,
vcl_string& str,
bool& eol,
bool& eof);
//: The character delimiting each column.
char delimiter_;
//: The column headers (in order)
vcl_vector<vcl_string> column_headers_;
//: Map a column header string to column index
vcl_map<vcl_string, unsigned> header_to_column_index_;
//: The table data, arranged as column vectors of double data.
vcl_vector<vcl_vector<double> > columns_;
};
#endif // mbl_table_h
|