00001 #include "config.h"
00002
00003 #include <iostream>
00004 #include <algorithm>
00005
00006 #include "asserts.h"
00007 #include "types.h"
00008 #include "error.h"
00009 #include "estring.h"
00010 #include "table.h"
00011
00012
00013
00014 const table_cell_base::size_type table_cell_base::npos = estring::npos;
00015
00016 table_cell_base::table_cell_base()
00017 {
00018 x = npos;
00019 y = npos;
00020 repeat = false;
00021 }
00022
00023 table_cell_base::table_cell_base(const table_cell_base& a_class)
00024 {
00025 assign(a_class);
00026 }
00027
00028 table_cell_base::~table_cell_base()
00029 {
00030 }
00031
00032 void table_cell_base::assign(const table_cell_base& a_class)
00033 {
00034 }
00035
00036 table_cell_base::size_type table_cell_base::height(void) const
00037 {
00038 return(0);
00039 }
00040
00041 table_cell_base::size_type table_cell_base::width(void) const
00042 {
00043 return(0);
00044 }
00045
00046 void table_cell_base::write(
00047 std::ostream& a_out,
00048 size_type a_line,
00049 size_type a_width
00050 ) const
00051 {
00052 }
00053
00054 table_cell_base& table_cell_base::operator=(const table_cell_base& a_class)
00055 {
00056 assign(a_class);
00057
00058 return(*this);
00059 }
00060
00061 bool operator==(const table_cell_base& a_1, const table_cell_base& a_2)
00062 {
00063 bool value;
00064
00065 value = (&a_1 == &a_2);
00066
00067 return(value);
00068 }
00069
00070
00071
00072 table_cell_estring::table_cell_estring()
00073 {
00074 }
00075
00076 table_cell_estring::table_cell_estring(const table_cell_estring& a_class)
00077 {
00078 assign(a_class);
00079 }
00080
00081 table_cell_estring::table_cell_estring(const estring& a_class)
00082 {
00083 assign(a_class);
00084 }
00085
00086 table_cell_estring::~table_cell_estring()
00087 {
00088 }
00089
00090 void table_cell_estring::assign(const table_cell_estring& a_class)
00091 {
00092 assign(a_class.m_value);
00093 x = a_class.x;
00094 y = a_class.y;
00095 repeat = a_class.repeat;
00096 }
00097
00098 void table_cell_estring::assign(const estring& a_class)
00099 {
00100 m_value = a_class;
00101 }
00102
00103 table_cell_estring::size_type table_cell_estring::height(void) const
00104 {
00105 return(1);
00106 }
00107
00108 table_cell_estring::size_type table_cell_estring::width(void) const
00109 {
00110 size_type value;
00111
00112 value = m_value.size();
00113
00114 return(value);
00115 }
00116
00117 void table_cell_estring::write(
00118 std::ostream& a_out,
00119 size_type a_line,
00120 size_type a_width
00121 ) const
00122 {
00123 estring str;
00124
00125 if (repeat) {
00126 a_line = 0;
00127 }
00128 if (a_line == 0) {
00129 str = m_value;
00130 str.width(a_width);
00131 a_out << str.fmt_str();
00132 a_out.flush();
00133 }
00134 else {
00135 str = "";
00136 str.width(a_width);
00137 a_out << str.fmt_str();
00138 a_out.flush();
00139 }
00140 }
00141
00142 table_cell_estring&
00143 table_cell_estring::operator=(const table_cell_estring& a_class)
00144 {
00145 assign(a_class);
00146
00147 return(*this);
00148 }
00149
00150 table_cell_estring&
00151 table_cell_estring::operator=(const estring& a_class)
00152 {
00153 assign(a_class);
00154
00155 return(*this);
00156 }
00157
00158
00159
00160 table_cell_table::table_cell_table()
00161 {
00162 m_value = new table;
00163 if (m_value == 0)
00164 throw(err_nomem);
00165 }
00166
00167 table_cell_table::table_cell_table(const table_cell_table& a_class)
00168 {
00169 m_value = 0;
00170 assign(a_class);
00171 }
00172
00173 table_cell_table::table_cell_table(const table& a_class)
00174 {
00175 m_value = 0;
00176 assign(a_class);
00177 }
00178
00179 table_cell_table::~table_cell_table()
00180 {
00181 if (m_value != 0)
00182 delete(m_value);
00183 }
00184
00185 void table_cell_table::assign(const table_cell_table& a_class)
00186 {
00187 ASSERT(a_class.m_value != 0);
00188 assign(*a_class.m_value);
00189 x = a_class.x;
00190 y = a_class.y;
00191 repeat = a_class.repeat;
00192 }
00193
00194 void table_cell_table::assign(const table& a_class)
00195 {
00196 if (m_value != 0) {
00197 delete(m_value);
00198 }
00199 m_value = new table(a_class);
00200 }
00201
00202 table_cell_table::size_type table_cell_table::height(void) const
00203 {
00204 size_type value;
00205
00206 value = m_value->height();
00207
00208 return(value);
00209 }
00210
00211 table_cell_table::size_type table_cell_table::width(void) const
00212 {
00213 size_type value;
00214
00215 value = m_value->width();
00216
00217 return(value);
00218 }
00219
00220 void table_cell_table::write(
00221 std::ostream& a_out,
00222 size_type a_line,
00223 size_type a_width
00224 ) const
00225 {
00226 if (repeat) {
00227 a_line %= m_value->height();
00228 }
00229 if (a_line < m_value->height()) {
00230 m_value->write(a_out, a_line, a_width);
00231 }
00232 else {
00233 estring str;
00234
00235 str = "";
00236 str.width(a_width);
00237 a_out << str.fmt_str();
00238 a_out.flush();
00239 }
00240 }
00241
00242 table_cell_table&
00243 table_cell_table::operator=(const table_cell_table& a_class)
00244 {
00245 assign(a_class);
00246
00247 return(*this);
00248 }
00249
00250 table_cell_table&
00251 table_cell_table::operator=(const table& a_class)
00252 {
00253 assign(a_class);
00254
00255 return(*this);
00256 }
00257
00258
00259
00260 table::table()
00261 {
00262 mf_init();
00263 }
00264
00265 table::table(const table::size_type a_ncols, const table::size_type a_nrows)
00266 {
00267 size_type cx, cy;
00268
00269 mf_init();
00270 for (cy = 0; cy != a_nrows; ++cy) {
00271 table_row_type new_row;
00272
00273 for (cx = 0; cx != a_ncols; ++cx) {
00274 new_row.push_back(static_cast<table_cell_base *>(0));
00275 }
00276
00277 TRY_nomem(m_table.push_back(new_row));
00278 }
00279 }
00280
00281 table::table(const table& a_class)
00282 {
00283 mf_init();
00284 assign(a_class);
00285 }
00286
00287 table::~table()
00288 {
00289 }
00290
00291 void table::resize(const size_type a_x, const size_type a_y)
00292 {
00293 size_type cy;
00294
00295 while (m_table.size() > a_y)
00296 mf_remove_row(m_table.size()-1);
00297
00298 for (cy = 0; cy != m_table.size(); ++cy) {
00299 while (m_table[cy].size() > a_x)
00300 mf_remove_elt(m_table[cy].size()-1,cy);
00301 }
00302
00303 while (m_table.size() < a_y) {
00304 table_row_type new_row;
00305
00306 TRY_nomem(m_table.push_back(new_row));
00307 }
00308
00309 for (cy = 0; cy != m_table.size(); ++cy) {
00310 while (m_table[cy].size() < a_x)
00311 TRY_nomem(m_table[cy].push_back(static_cast<table_cell_base *>(0)));
00312 }
00313 }
00314
00315 void table::insert_row(const table::size_type a_y)
00316 {
00317 size_type num_cols;
00318 table_row_type new_row;
00319 table_type::iterator ti;
00320
00321 while (a_y > m_table.size())
00322 insert_row(m_table.size());
00323
00324 num_cols = ncols();
00325 while (new_row.size() < num_cols)
00326 TRY_nomem(new_row.push_back(static_cast<table_cell_base *>(0)));
00327 ti = m_table.begin();
00328 ti += a_y;
00329 TRY_nomem(m_table.insert(ti,new_row));
00330 }
00331
00332 void table::insert_col(const table::size_type a_x)
00333 {
00334 table_type::iterator cy;
00335 table_row_type::iterator cx;
00336
00337 for (cy = m_table.begin(); cy != m_table.end(); ++cy) {
00338 while (a_x > cy->size()) {
00339 TRY_nomem(cy->push_back(static_cast<table_cell_base *>(0)));
00340 }
00341 cx = cy->begin();
00342 cx += a_x;
00343 TRY_nomem(cy->insert(cx,static_cast<table_cell_base *>(0)));
00344 }
00345 }
00346
00347 void table::assign(const table& a_class)
00348 {
00349 std::list<table_cell_estring>::const_iterator ctce;
00350 std::list<table_cell_table>::const_iterator ctct;
00351
00352 m_table.clear();
00353 m_list_estring.clear();
00354 m_list_table.clear();
00355
00356 resize(a_class.ncols(),a_class.nrows());
00357
00358 for (
00359 ctce = a_class.m_list_estring.begin();
00360 ctce != a_class.m_list_estring.end();
00361 ++ctce
00362 ) {
00363 mf_add_elt(*ctce);
00364 }
00365 for (
00366 ctct = a_class.m_list_table.begin();
00367 ctct != a_class.m_list_table.end();
00368 ++ctct
00369 ) {
00370 mf_add_elt(*ctct);
00371 }
00372 }
00373
00374 void table::assign(
00375 const size_type a_x,
00376 const size_type a_y,
00377 const estring& a_class
00378 )
00379 {
00380 estring es;
00381 table_cell_estring new_cell(a_class);
00382
00383 if (a_y >= m_table.size()) {
00384 es = "Column index out of bounds: ";
00385 es += estring(a_y);
00386 throw(INTERNAL_ERROR(0,es));
00387 }
00388 if (a_x >= m_table[a_y].size()) {
00389 es = "Row index out of bounds: ";
00390 es += estring(a_x);
00391 throw(INTERNAL_ERROR(0,es));
00392 }
00393 if (m_table[a_y][a_x] != 0)
00394 mf_remove_elt(a_x,a_y);
00395 new_cell.x = a_x;
00396 new_cell.y = a_y;
00397 new_cell.repeat = m_repeat;
00398 m_repeat = false;
00399 mf_add_elt(new_cell);
00400 }
00401
00402 void table::assign(
00403 const size_type a_x,
00404 const size_type a_y,
00405 const table& a_class
00406 )
00407 {
00408 estring es;
00409 table_cell_table new_cell(a_class);
00410
00411 if (a_y >= m_table.size()) {
00412 es = "Column index out of bounds: ";
00413 es += estring(a_y);
00414 throw(INTERNAL_ERROR(0,es));
00415 }
00416 if (a_x >= m_table[a_y].size()) {
00417 es = "Row index out of bounds: ";
00418 es += estring(a_x);
00419 throw(INTERNAL_ERROR(0,es));
00420 }
00421 if (m_table[a_y][a_x] != 0)
00422 mf_remove_elt(a_x,a_y);
00423
00424 new_cell.x = a_x;
00425 new_cell.y = a_y;
00426 new_cell.repeat = m_repeat;
00427 m_repeat = false;
00428 mf_add_elt(new_cell);
00429 }
00430
00431 table::size_type table::col_width(const table::size_type a_x) const
00432 {
00433 estring es;
00434 table_type::const_iterator cy;
00435 size_type width = 0;
00436
00437 if (m_table.size() == 0) {
00438 return(0);
00439 }
00440
00441 for (cy = m_table.begin(); cy != m_table.end(); cy++) {
00442 if (a_x >= cy->size()) {
00443 es = "Column index out of bounds: ";
00444 es += estring(a_x);
00445 throw(INTERNAL_ERROR(0,es));
00446 }
00447 if ((*cy)[a_x] != 0)
00448 width = std::max(width,(*cy)[a_x]->width());
00449 }
00450
00451 return(width);
00452 }
00453
00454 table::size_type table::row_width(void) const
00455 {
00456 size_type cx;
00457 size_type width = 0;
00458
00459 if (m_table.size() == 0) {
00460 return(0);
00461 }
00462
00463 for (cx = 0; cx != m_table.begin()->size(); ++cx) {
00464 width += col_width(cx);
00465 }
00466
00467 return(width);
00468 }
00469
00470 table::size_type table::col_height(void) const
00471 {
00472 size_type y;
00473 size_type height = 0;
00474
00475 for (y = 0; y != m_table.size(); ++y) {
00476 height += row_height(y);
00477 }
00478
00479 return(height);
00480 }
00481
00482 table::size_type table::row_height(const table::size_type a_y) const
00483 {
00484 estring es;
00485 table_row_type::const_iterator cx;
00486 size_type height = 0;
00487
00488 if (m_table.size() == 0) {
00489 return(0);
00490 }
00491 if (a_y >= m_table.size()) {
00492 es = "Row index out of bounds: ";
00493 es += estring(a_y);
00494 throw(INTERNAL_ERROR(0,es));
00495 }
00496 for (cx = m_table[a_y].begin(); cx != m_table[a_y].end(); ++cx) {
00497 if (*cx != 0)
00498 height = std::max(height, (*cx)->height());
00499 }
00500
00501 return(height);
00502 }
00503
00504 table::size_type table::height(void) const
00505 {
00506 table_type::const_iterator cy;
00507 table_row_type::const_iterator cx;
00508 size_type height = 0;
00509
00510 for (cy = m_table.begin(); cy != m_table.end(); ++cy) {
00511 size_type row_height = 0;
00512
00513 for (cx = cy->begin(); cx != cy->end(); ++cx) {
00514 if (*cx != 0)
00515 row_height = std::max(row_height, (*cx)->height());
00516 }
00517
00518 height += row_height;
00519 }
00520
00521 return(height);
00522 }
00523
00524 table::size_type table::width(void) const
00525 {
00526 table_type::const_iterator cy;
00527 size_type x, max_x = 0;
00528 size_type width = 0;
00529
00530 for (cy = m_table.begin(); cy != m_table.end(); ++cy) {
00531 max_x = std::max(max_x, cy->size());
00532 }
00533
00534 for (x = 0; x < max_x; ++x) {
00535 size_type col_width = 0;
00536
00537 for (cy = m_table.begin(); cy != m_table.end(); ++cy) {
00538 if ((x < cy->size()) && ((*cy)[x] != 0)) {
00539 col_width = std::max(col_width, (*cy)[x]->width());
00540 }
00541 }
00542
00543 width += col_width;
00544 }
00545
00546 return(width);
00547 }
00548
00549 const table::size_type table::ncols(void) const
00550 {
00551 table_type::const_iterator cy;
00552 size_type cols = 0;
00553
00554 for (cy = m_table.begin(); cy != m_table.end(); ++cy) {
00555 cols = std::max(cols,cy->size());
00556 }
00557
00558 return(cols);
00559 }
00560
00561 const table::size_type table::nrows(void) const
00562 {
00563 size_type value;
00564
00565 value = m_table.size();
00566
00567 return(value);
00568 }
00569
00570 void table::write(
00571 std::ostream& a_out,
00572 size_type a_line,
00573 size_type a_width
00574 ) const
00575 {
00576 size_type row = 0;
00577 size_type height;
00578 size_type col = 0;
00579 size_type width;
00580
00581 if (m_table.size() == 0)
00582 return;
00583
00584 while ((m_table.size() > row) && (a_line >= (height = row_height(row))))
00585 {
00586 a_line -= height;
00587 ++row;
00588 }
00589 for (col = 0; col != m_table[row].size(); ++col) {
00590 width = std::min(col_width(col), a_width);
00591 if (m_table[row][col] != 0)
00592 m_table[row][col]->write(a_out,a_line,width);
00593 else {
00594 estring estr;
00595
00596 estr = "";
00597 estr.width(width);
00598 a_out << estr.fmt_str();
00599 a_out.flush();
00600 }
00601 a_width -= width;
00602 }
00603
00604 if (a_width > 0) {
00605 estring estr;
00606
00607 estr = "";
00608 estr.width(a_width);
00609 a_out << estr.fmt_str();
00610 a_out.flush();
00611 }
00612 }
00613
00614 table& table::operator=(const table& a_class)
00615 {
00616 assign(a_class);
00617
00618 return(*this);
00619 }
00620
00621 table::size_type table::cursor_x(void) const
00622 {
00623 return(m_cursor_x);
00624 }
00625
00626 table::size_type table::cursor_y(void) const
00627 {
00628 return(m_cursor_y);
00629 }
00630
00631 void table::set_cursor(table::size_type a_x, table::size_type a_y)
00632 {
00633 estring es;
00634
00635 if (a_y >= m_table.size()) {
00636 es = "Column index out of bounds: ";
00637 es += estring(a_y);
00638 throw(ERROR(0,es));
00639 }
00640 if (a_x >= m_table[a_y].size()) {
00641 es = "Row index out of bounds: ";
00642 es += estring(a_x);
00643 throw(ERROR(0,es));
00644 }
00645
00646 m_cursor_x = a_x;
00647 m_cursor_y = a_y;
00648 }
00649
00650 bool table::eot(void) const
00651 {
00652 if ((m_cursor_x == ncols()-1) && (m_cursor_y == nrows()-1)) {
00653 return(true);
00654 }
00655
00656 return(false);
00657 }
00658
00659 void table::repeat(const bool a_bool)
00660 {
00661 m_repeat = a_bool;
00662 }
00663
00664 void table::mf_init(void)
00665 {
00666 m_cursor_x = 0;
00667 m_cursor_y = 0;
00668 m_repeat = false;
00669 }
00670
00671 void table::mf_add_elt(const table_cell_estring& a_class)
00672 {
00673 estring es;
00674
00675 if (a_class.y >= m_table.size()) {
00676 es = "Column index out of bounds: ";
00677 es += estring(a_class.y);
00678 throw(INTERNAL_ERROR(0,es));
00679 }
00680 if (a_class.x >= m_table[a_class.y].size()) {
00681 es = "Row index out of bounds: ";
00682 es += estring(a_class.x);
00683 throw(INTERNAL_ERROR(0,es));
00684 }
00685 TRY_nomem(m_list_estring.push_back(a_class));
00686 m_table[a_class.y][a_class.x] = &(*m_list_estring.rbegin());
00687 }
00688
00689 void table::mf_add_elt(const table_cell_table& a_class)
00690 {
00691 estring es;
00692
00693 if (a_class.y >= m_table.size()) {
00694 es = "Column index out of bounds: ";
00695 es += estring(a_class.y);
00696 throw(INTERNAL_ERROR(0,es));
00697 }
00698 if (a_class.x >= m_table[a_class.y].size()) {
00699 es = "Row index out of bounds: ";
00700 es += estring(a_class.x);
00701 throw(INTERNAL_ERROR(0,es));
00702 }
00703 TRY_nomem(m_list_table.push_back(a_class));
00704 m_table[a_class.y][a_class.x] = &(*m_list_table.rbegin());
00705 }
00706
00707 void table::mf_remove_elt(const table_cell_estring& a_class)
00708 {
00709 estring es;
00710
00711 if (a_class.y >= m_table.size()) {
00712 es = "Column index out of bounds: ";
00713 es += estring(a_class.y);
00714 throw(INTERNAL_ERROR(0,es));
00715 }
00716 if (a_class.x >= m_table[a_class.y].size()) {
00717 es = "Row index out of bounds: ";
00718 es += estring(a_class.x);
00719 throw(INTERNAL_ERROR(0,es));
00720 }
00721 m_table[a_class.y][a_class.x] = static_cast<table_cell_base *>(0);
00722 m_list_estring.erase(
00723 find(m_list_estring.begin(), m_list_estring.end(), a_class)
00724 );
00725 }
00726
00727 void table::mf_remove_elt(const table_cell_table& a_class)
00728 {
00729 estring es;
00730
00731 if (a_class.y >= m_table.size()) {
00732 es = "Column index out of bounds: ";
00733 es += estring(a_class.y);
00734 throw(INTERNAL_ERROR(0,es));
00735 }
00736 if (a_class.x >= m_table[a_class.y].size()) {
00737 es = "Row index out of bounds: ";
00738 es += estring(a_class.x);
00739 throw(INTERNAL_ERROR(0,es));
00740 }
00741 m_table[a_class.y][a_class.x] = static_cast<table_cell_base *>(0);
00742 m_list_table.erase(
00743 find(m_list_table.begin(), m_list_table.end(), a_class)
00744 );
00745 }
00746
00747 void table::mf_remove_elt(
00748 table::size_type a_x,
00749 table::size_type a_y
00750 )
00751 {
00752 estring es;
00753 std::list<table_cell_estring>::const_iterator ctce;
00754 std::list<table_cell_table>::const_iterator ctct;
00755
00756 if (a_y >= m_table.size()) {
00757 es = "Column index out of bounds: ";
00758 es += estring(a_y);
00759 throw(INTERNAL_ERROR(0,es));
00760 }
00761 if (a_x >= m_table[a_y].size()) {
00762 es = "Row index out of bounds: ";
00763 es += estring(a_x);
00764 throw(INTERNAL_ERROR(0,es));
00765 }
00766 if (m_table[a_y][a_x] != 0) {
00767 for (ctce = m_list_estring.begin(); ctce != m_list_estring.end(); ++ctce)
00768 {
00769 if (*ctce == *m_table[a_y][a_x]) {
00770 mf_remove_elt(*ctce);
00771 return;
00772 }
00773 }
00774 for (ctct = m_list_table.begin(); ctct != m_list_table.end(); ++ctct) {
00775 if (*ctct == *m_table[a_y][a_x]) {
00776 mf_remove_elt(*ctct);
00777 return;
00778 }
00779 }
00780
00781 ASSERT(0);
00782 }
00783 }
00784
00785 void table::mf_remove_row(table::size_type a_y)
00786 {
00787 size_type cx;
00788 table_type::iterator ti;
00789
00790 estring es;
00791
00792 if (a_y >= m_table.size()) {
00793 es = "Column index out of bounds: ";
00794 es += estring(a_y);
00795 throw(INTERNAL_ERROR(0,es));
00796 }
00797 for (cx = 0; cx < m_table[a_y].size(); ++cx) {
00798 mf_remove_elt(cx,a_y);
00799 }
00800 ti = m_table.begin();
00801 ti += a_y;
00802 m_table.erase(ti);
00803 }
00804
00805
00806
00807 std::ostream& operator<<(std::ostream& a_out, table& a_class)
00808 {
00809 table::size_type width, height, cy;
00810
00811 height = a_class.col_height();
00812 width = a_class.row_width();
00813
00814 for (cy = 0; cy != height; ++cy) {
00815 a_class.write(a_out, cy, width);
00816 a_out << std::endl;
00817 a_out.flush();
00818 }
00819
00820 return(a_out);
00821 }
00822
00823
00824
00825 table& table_write(table& a_table, const estring& a_estr)
00826 {
00827 if ((a_table.ncols() == 0) && (a_table.nrows() == 0)) {
00828 a_table.insert_row(0);
00829 a_table.insert_col(0);
00830 }
00831 a_table.assign(a_table.cursor_x(), a_table.cursor_y(), a_estr);
00832 if (a_table.cursor_x() == a_table.ncols()-1)
00833 a_table.insert_col(a_table.ncols());
00834 table_skip(a_table);
00835
00836 return(a_table);
00837 }
00838
00839 table& table_write(table& a_table, const table& a_subtable)
00840 {
00841 if ((a_table.ncols() == 0) && (a_table.nrows() == 0)) {
00842 a_table.insert_row(0);
00843 a_table.insert_col(0);
00844 }
00845 a_table.assign(a_table.cursor_x(), a_table.cursor_y(), a_subtable);
00846 if (a_table.cursor_x() == a_table.ncols()-1)
00847 a_table.insert_col(a_table.ncols());
00848 table_skip(a_table);
00849
00850 return(a_table);
00851 }
00852
00853 table& table_endl(table& a_table)
00854 {
00855 if (a_table.cursor_y() == a_table.nrows()-1)
00856 a_table.insert_row(a_table.nrows());
00857 a_table.set_cursor(0,a_table.cursor_y()+1);
00858
00859 return(a_table);
00860 }
00861
00862 table& table_rewind(table& a_table)
00863 {
00864 a_table.set_cursor(0,0);
00865
00866 return(a_table);
00867 }
00868
00869 table& table_skip(table& a_table)
00870 {
00871 if (a_table.cursor_x() == a_table.ncols()-1) {
00872 if (a_table.cursor_y() != a_table.nrows()-1) {
00873 a_table.set_cursor(0,a_table.cursor_y()+1);
00874 }
00875 }
00876 else {
00877 a_table.set_cursor(a_table.cursor_x()+1,a_table.cursor_y());
00878 }
00879
00880 return(a_table);
00881 }
00882
00883 table& table_repeat(table& a_table)
00884 {
00885 a_table.repeat(true);
00886
00887 return(a_table);
00888 }
00889
00890 table& operator<<(table& a_table, const estring& a_estr)
00891 {
00892 table_write(a_table, a_estr);
00893
00894 return(a_table);
00895 }
00896
00897 table& operator<<(table& a_table, const table& a_subtable)
00898 {
00899 table_write(a_table, a_subtable);
00900
00901 return(a_table);
00902 }
00903
00904 table& operator<<(table& a_table, table& (*a_arg)(table&))
00905 {
00906 a_arg(a_table);
00907
00908 return(a_table);
00909 }
00910
00911
00912