#include "config.h" #include #include #include "asserts.h" #include "types.h" #include "error.h" #include "estring.h" #include "table.h" //---------------------------------------------------------------------------- const table_cell_base::size_type table_cell_base::npos = estring::npos; table_cell_base::table_cell_base() { x = npos; y = npos; repeat = false; } table_cell_base::table_cell_base(const table_cell_base& a_class) { assign(a_class); } table_cell_base::~table_cell_base() { } void table_cell_base::assign(const table_cell_base& a_class) { } table_cell_base::size_type table_cell_base::height(void) const { return(0); } table_cell_base::size_type table_cell_base::width(void) const { return(0); } void table_cell_base::write( std::ostream& a_out, size_type a_line, size_type a_width ) const { } table_cell_base& table_cell_base::operator=(const table_cell_base& a_class) { assign(a_class); return(*this); } bool operator==(const table_cell_base& a_1, const table_cell_base& a_2) { bool value; value = (&a_1 == &a_2); return(value); } //---------------------------------------------------------------------------- table_cell_estring::table_cell_estring() { } table_cell_estring::table_cell_estring(const table_cell_estring& a_class) { assign(a_class); } table_cell_estring::table_cell_estring(const estring& a_class) { assign(a_class); } table_cell_estring::~table_cell_estring() { } void table_cell_estring::assign(const table_cell_estring& a_class) { assign(a_class.m_value); x = a_class.x; y = a_class.y; repeat = a_class.repeat; } void table_cell_estring::assign(const estring& a_class) { m_value = a_class; } table_cell_estring::size_type table_cell_estring::height(void) const { return(1); } table_cell_estring::size_type table_cell_estring::width(void) const { size_type value; value = m_value.size(); return(value); } void table_cell_estring::write( std::ostream& a_out, size_type a_line, size_type a_width ) const { estring str; if (repeat) { a_line = 0; } if (a_line == 0) { str = m_value; str.width(a_width); a_out << str.fmt_str(); a_out.flush(); } else { str = ""; str.width(a_width); a_out << str.fmt_str(); a_out.flush(); } } table_cell_estring& table_cell_estring::operator=(const table_cell_estring& a_class) { assign(a_class); return(*this); } table_cell_estring& table_cell_estring::operator=(const estring& a_class) { assign(a_class); return(*this); } //---------------------------------------------------------------------------- table_cell_table::table_cell_table() { m_value = new table; if (m_value == 0) throw(err_nomem); } table_cell_table::table_cell_table(const table_cell_table& a_class) { m_value = 0; assign(a_class); } table_cell_table::table_cell_table(const table& a_class) { m_value = 0; assign(a_class); } table_cell_table::~table_cell_table() { if (m_value != 0) delete(m_value); } void table_cell_table::assign(const table_cell_table& a_class) { ASSERT(a_class.m_value != 0); assign(*a_class.m_value); x = a_class.x; y = a_class.y; repeat = a_class.repeat; } void table_cell_table::assign(const table& a_class) { if (m_value != 0) { delete(m_value); } m_value = new table(a_class); } table_cell_table::size_type table_cell_table::height(void) const { size_type value; value = m_value->height(); return(value); } table_cell_table::size_type table_cell_table::width(void) const { size_type value; value = m_value->width(); return(value); } void table_cell_table::write( std::ostream& a_out, size_type a_line, size_type a_width ) const { if (repeat) { a_line %= m_value->height(); } if (a_line < m_value->height()) { m_value->write(a_out, a_line, a_width); } else { estring str; str = ""; str.width(a_width); a_out << str.fmt_str(); a_out.flush(); } } table_cell_table& table_cell_table::operator=(const table_cell_table& a_class) { assign(a_class); return(*this); } table_cell_table& table_cell_table::operator=(const table& a_class) { assign(a_class); return(*this); } //---------------------------------------------------------------------------- table::table() { mf_init(); } table::table(const table::size_type a_ncols, const table::size_type a_nrows) { size_type cx, cy; mf_init(); for (cy = 0; cy != a_nrows; ++cy) { table_row_type new_row; for (cx = 0; cx != a_ncols; ++cx) { new_row.push_back(static_cast(0)); } TRY_nomem(m_table.push_back(new_row)); } } table::table(const table& a_class) { mf_init(); assign(a_class); } table::~table() { } void table::resize(const size_type a_x, const size_type a_y) { size_type cy; while (m_table.size() > a_y) mf_remove_row(m_table.size()-1); for (cy = 0; cy != m_table.size(); ++cy) { while (m_table[cy].size() > a_x) mf_remove_elt(m_table[cy].size()-1,cy); } while (m_table.size() < a_y) { table_row_type new_row; TRY_nomem(m_table.push_back(new_row)); } for (cy = 0; cy != m_table.size(); ++cy) { while (m_table[cy].size() < a_x) TRY_nomem(m_table[cy].push_back(static_cast(0))); } } void table::insert_row(const table::size_type a_y) { size_type num_cols; table_row_type new_row; table_type::iterator ti; while (a_y > m_table.size()) insert_row(m_table.size()); num_cols = ncols(); while (new_row.size() < num_cols) TRY_nomem(new_row.push_back(static_cast(0))); ti = m_table.begin(); ti += a_y; TRY_nomem(m_table.insert(ti,new_row)); } void table::insert_col(const table::size_type a_x) { table_type::iterator cy; table_row_type::iterator cx; for (cy = m_table.begin(); cy != m_table.end(); ++cy) { while (a_x > cy->size()) { TRY_nomem(cy->push_back(static_cast(0))); } cx = cy->begin(); cx += a_x; TRY_nomem(cy->insert(cx,static_cast(0))); } } void table::assign(const table& a_class) { std::list::const_iterator ctce; std::list::const_iterator ctct; m_table.clear(); m_list_estring.clear(); m_list_table.clear(); resize(a_class.ncols(),a_class.nrows()); for ( ctce = a_class.m_list_estring.begin(); ctce != a_class.m_list_estring.end(); ++ctce ) { mf_add_elt(*ctce); } for ( ctct = a_class.m_list_table.begin(); ctct != a_class.m_list_table.end(); ++ctct ) { mf_add_elt(*ctct); } } void table::assign( const size_type a_x, const size_type a_y, const estring& a_class ) { estring es; table_cell_estring new_cell(a_class); if (a_y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_y); throw(INTERNAL_ERROR(0,es)); } if (a_x >= m_table[a_y].size()) { es = "Row index out of bounds: "; es += estring(a_x); throw(INTERNAL_ERROR(0,es)); } if (m_table[a_y][a_x] != 0) mf_remove_elt(a_x,a_y); new_cell.x = a_x; new_cell.y = a_y; new_cell.repeat = m_repeat; m_repeat = false; mf_add_elt(new_cell); } void table::assign( const size_type a_x, const size_type a_y, const table& a_class ) { estring es; table_cell_table new_cell(a_class); if (a_y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_y); throw(INTERNAL_ERROR(0,es)); } if (a_x >= m_table[a_y].size()) { es = "Row index out of bounds: "; es += estring(a_x); throw(INTERNAL_ERROR(0,es)); } if (m_table[a_y][a_x] != 0) mf_remove_elt(a_x,a_y); new_cell.x = a_x; new_cell.y = a_y; new_cell.repeat = m_repeat; m_repeat = false; mf_add_elt(new_cell); } table::size_type table::col_width(const table::size_type a_x) const { estring es; table_type::const_iterator cy; size_type width = 0; if (m_table.size() == 0) { return(0); } for (cy = m_table.begin(); cy != m_table.end(); cy++) { if (a_x >= cy->size()) { es = "Column index out of bounds: "; es += estring(a_x); throw(INTERNAL_ERROR(0,es)); } if ((*cy)[a_x] != 0) width = std::max(width,(*cy)[a_x]->width()); } return(width); } table::size_type table::row_width(void) const { size_type cx; size_type width = 0; if (m_table.size() == 0) { return(0); } for (cx = 0; cx != m_table.begin()->size(); ++cx) { width += col_width(cx); } return(width); } table::size_type table::col_height(void) const { size_type y; size_type height = 0; for (y = 0; y != m_table.size(); ++y) { height += row_height(y); } return(height); } table::size_type table::row_height(const table::size_type a_y) const { estring es; table_row_type::const_iterator cx; size_type height = 0; if (m_table.size() == 0) { return(0); } if (a_y >= m_table.size()) { es = "Row index out of bounds: "; es += estring(a_y); throw(INTERNAL_ERROR(0,es)); } for (cx = m_table[a_y].begin(); cx != m_table[a_y].end(); ++cx) { if (*cx != 0) height = std::max(height, (*cx)->height()); } return(height); } table::size_type table::height(void) const { table_type::const_iterator cy; table_row_type::const_iterator cx; size_type height = 0; for (cy = m_table.begin(); cy != m_table.end(); ++cy) { size_type row_height = 0; for (cx = cy->begin(); cx != cy->end(); ++cx) { if (*cx != 0) row_height = std::max(row_height, (*cx)->height()); } height += row_height; } return(height); } table::size_type table::width(void) const { table_type::const_iterator cy; size_type x, max_x = 0; size_type width = 0; for (cy = m_table.begin(); cy != m_table.end(); ++cy) { max_x = std::max(max_x, cy->size()); } for (x = 0; x < max_x; ++x) { size_type col_width = 0; for (cy = m_table.begin(); cy != m_table.end(); ++cy) { if ((x < cy->size()) && ((*cy)[x] != 0)) { col_width = std::max(col_width, (*cy)[x]->width()); } } width += col_width; } return(width); } const table::size_type table::ncols(void) const { table_type::const_iterator cy; size_type cols = 0; for (cy = m_table.begin(); cy != m_table.end(); ++cy) { cols = std::max(cols,cy->size()); } return(cols); } const table::size_type table::nrows(void) const { size_type value; value = m_table.size(); return(value); } void table::write( std::ostream& a_out, size_type a_line, size_type a_width ) const { size_type row = 0; size_type height; size_type col = 0; size_type width; if (m_table.size() == 0) return; while ((m_table.size() > row) && (a_line >= (height = row_height(row)))) { a_line -= height; ++row; } for (col = 0; col != m_table[row].size(); ++col) { width = std::min(col_width(col), a_width); if (m_table[row][col] != 0) m_table[row][col]->write(a_out,a_line,width); else { estring estr; estr = ""; estr.width(width); a_out << estr.fmt_str(); a_out.flush(); } a_width -= width; } if (a_width > 0) { estring estr; estr = ""; estr.width(a_width); a_out << estr.fmt_str(); a_out.flush(); } } table& table::operator=(const table& a_class) { assign(a_class); return(*this); } table::size_type table::cursor_x(void) const { return(m_cursor_x); } table::size_type table::cursor_y(void) const { return(m_cursor_y); } void table::set_cursor(table::size_type a_x, table::size_type a_y) { estring es; if (a_y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_y); throw(ERROR(0,es)); } if (a_x >= m_table[a_y].size()) { es = "Row index out of bounds: "; es += estring(a_x); throw(ERROR(0,es)); } m_cursor_x = a_x; m_cursor_y = a_y; } bool table::eot(void) const { if ((m_cursor_x == ncols()-1) && (m_cursor_y == nrows()-1)) { return(true); } return(false); } void table::repeat(const bool a_bool) { m_repeat = a_bool; } void table::mf_init(void) { m_cursor_x = 0; m_cursor_y = 0; m_repeat = false; } void table::mf_add_elt(const table_cell_estring& a_class) { estring es; if (a_class.y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_class.y); throw(INTERNAL_ERROR(0,es)); } if (a_class.x >= m_table[a_class.y].size()) { es = "Row index out of bounds: "; es += estring(a_class.x); throw(INTERNAL_ERROR(0,es)); } TRY_nomem(m_list_estring.push_back(a_class)); m_table[a_class.y][a_class.x] = &(*m_list_estring.rbegin()); } void table::mf_add_elt(const table_cell_table& a_class) { estring es; if (a_class.y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_class.y); throw(INTERNAL_ERROR(0,es)); } if (a_class.x >= m_table[a_class.y].size()) { es = "Row index out of bounds: "; es += estring(a_class.x); throw(INTERNAL_ERROR(0,es)); } TRY_nomem(m_list_table.push_back(a_class)); m_table[a_class.y][a_class.x] = &(*m_list_table.rbegin()); } void table::mf_remove_elt(const table_cell_estring& a_class) { estring es; if (a_class.y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_class.y); throw(INTERNAL_ERROR(0,es)); } if (a_class.x >= m_table[a_class.y].size()) { es = "Row index out of bounds: "; es += estring(a_class.x); throw(INTERNAL_ERROR(0,es)); } m_table[a_class.y][a_class.x] = static_cast(0); m_list_estring.erase( find(m_list_estring.begin(), m_list_estring.end(), a_class) ); } void table::mf_remove_elt(const table_cell_table& a_class) { estring es; if (a_class.y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_class.y); throw(INTERNAL_ERROR(0,es)); } if (a_class.x >= m_table[a_class.y].size()) { es = "Row index out of bounds: "; es += estring(a_class.x); throw(INTERNAL_ERROR(0,es)); } m_table[a_class.y][a_class.x] = static_cast(0); m_list_table.erase( find(m_list_table.begin(), m_list_table.end(), a_class) ); } void table::mf_remove_elt( table::size_type a_x, table::size_type a_y ) { estring es; std::list::const_iterator ctce; std::list::const_iterator ctct; if (a_y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_y); throw(INTERNAL_ERROR(0,es)); } if (a_x >= m_table[a_y].size()) { es = "Row index out of bounds: "; es += estring(a_x); throw(INTERNAL_ERROR(0,es)); } if (m_table[a_y][a_x] != 0) { for (ctce = m_list_estring.begin(); ctce != m_list_estring.end(); ++ctce) { if (*ctce == *m_table[a_y][a_x]) { mf_remove_elt(*ctce); return; } } for (ctct = m_list_table.begin(); ctct != m_list_table.end(); ++ctct) { if (*ctct == *m_table[a_y][a_x]) { mf_remove_elt(*ctct); return; } } // This should never happen ASSERT(0); } } void table::mf_remove_row(table::size_type a_y) { size_type cx; table_type::iterator ti; estring es; if (a_y >= m_table.size()) { es = "Column index out of bounds: "; es += estring(a_y); throw(INTERNAL_ERROR(0,es)); } for (cx = 0; cx < m_table[a_y].size(); ++cx) { mf_remove_elt(cx,a_y); } ti = m_table.begin(); ti += a_y; m_table.erase(ti); } //---------------------------------------------------------------------------- std::ostream& operator<<(std::ostream& a_out, table& a_class) { table::size_type width, height, cy; height = a_class.col_height(); width = a_class.row_width(); for (cy = 0; cy != height; ++cy) { a_class.write(a_out, cy, width); a_out << std::endl; a_out.flush(); } return(a_out); } //---------------------------------------------------------------------------- table& table_write(table& a_table, const estring& a_estr) { if ((a_table.ncols() == 0) && (a_table.nrows() == 0)) { a_table.insert_row(0); a_table.insert_col(0); } a_table.assign(a_table.cursor_x(), a_table.cursor_y(), a_estr); if (a_table.cursor_x() == a_table.ncols()-1) a_table.insert_col(a_table.ncols()); table_skip(a_table); return(a_table); } table& table_write(table& a_table, const table& a_subtable) { if ((a_table.ncols() == 0) && (a_table.nrows() == 0)) { a_table.insert_row(0); a_table.insert_col(0); } a_table.assign(a_table.cursor_x(), a_table.cursor_y(), a_subtable); if (a_table.cursor_x() == a_table.ncols()-1) a_table.insert_col(a_table.ncols()); table_skip(a_table); return(a_table); } table& table_endl(table& a_table) { if (a_table.cursor_y() == a_table.nrows()-1) a_table.insert_row(a_table.nrows()); a_table.set_cursor(0,a_table.cursor_y()+1); return(a_table); } table& table_rewind(table& a_table) { a_table.set_cursor(0,0); return(a_table); } table& table_skip(table& a_table) { if (a_table.cursor_x() == a_table.ncols()-1) { if (a_table.cursor_y() != a_table.nrows()-1) { a_table.set_cursor(0,a_table.cursor_y()+1); } } else { a_table.set_cursor(a_table.cursor_x()+1,a_table.cursor_y()); } return(a_table); } table& table_repeat(table& a_table) { a_table.repeat(true); return(a_table); } table& operator<<(table& a_table, const estring& a_estr) { table_write(a_table, a_estr); return(a_table); } table& operator<<(table& a_table, const table& a_subtable) { table_write(a_table, a_subtable); return(a_table); } table& operator<<(table& a_table, table& (*a_arg)(table&)) { a_arg(a_table); return(a_table); } //----------------------------------------------------------------------------