00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_IO_IOLEGACY_CC_UTC20050626084021_DEFINED
00035 #define GROOVX_IO_IOLEGACY_CC_UTC20050626084021_DEFINED
00036
00037 #include "io/iolegacy.h"
00038
00039 #include "nub/objmgr.h"
00040 #include "nub/ref.h"
00041
00042 #include "rutz/error.h"
00043 #include "rutz/fstring.h"
00044 #include "rutz/sfmt.h"
00045 #include "rutz/value.h"
00046
00047 #include <cctype>
00048 #include <cstring>
00049 #include <iostream>
00050
00051 #include "rutz/trace.h"
00052 #include "rutz/debug.h"
00053 GVX_DBG_REGISTER
00054
00055 using rutz::fstring;
00056
00057 using nub::ref;
00058 using nub::soft_ref;
00059
00061
00062
00063
00065
00066 class io::legacy_reader::impl
00067 {
00068 impl(const impl&);
00069 impl& operator=(const impl&);
00070
00071 public:
00072
00073 io::legacy_reader* m_owner;
00074 std::istream& m_stream;
00075 int m_legacy_version_id;
00076
00077 impl(io::legacy_reader* owner, std::istream& is) :
00078 m_owner(owner),
00079 m_stream(is),
00080 m_legacy_version_id(0)
00081 {}
00082
00083 void throw_if_error(const char* type, const rutz::file_pos& pos)
00084 {
00085 if (m_stream.fail())
00086 {
00087 dbg_print(3, "throw_if_error for"); dbg_eval_nl(3, type);
00088 throw rutz::error(type, pos);
00089 }
00090 }
00091
00092 void throw_if_error(const fstring& type, const rutz::file_pos& pos)
00093 {
00094 throw_if_error(type.c_str(), pos);
00095 }
00096
00097 void read_typename(const fstring& correct_name)
00098 {
00099 GVX_TRACE("io::legacy_reader::impl::read_typename(fstring)");
00100
00101 fstring name;
00102 m_stream >> name;
00103
00104 if (! name.equals(correct_name))
00105 {
00106
00107
00108 throw rutz::error(rutz::sfmt("couldn't read typename for %s",
00109 correct_name.c_str()), SRC_POS);
00110 }
00111 }
00112
00113
00114 void read_typename(const fstring& correct_name, const fstring& alt_name)
00115 {
00116 GVX_TRACE("io::legacy_reader::impl::read_typename(fstring, fstring)");
00117
00118 fstring name;
00119 m_stream >> name;
00120
00121 if ( !name.equals(correct_name) && !name.equals(alt_name) )
00122 {
00123
00124
00125 throw rutz::error(rutz::sfmt("couldn't read typename for %s",
00126 correct_name.c_str()), SRC_POS);
00127 }
00128 }
00129
00130 int get_legacy_version_id()
00131 {
00132 GVX_TRACE("io::legacy_reader::impl::get_legacy_version_id");
00133 while ( isspace(m_stream.peek()) )
00134 { m_stream.get(); }
00135
00136 int version = -1;
00137
00138 if (m_stream.peek() == '@')
00139 {
00140 int c = m_stream.get();
00141 GVX_ASSERT(c == '@');
00142
00143 m_stream >> version;
00144 dbg_eval_nl(3, version);
00145 throw_if_error("version id", SRC_POS);
00146 }
00147 else
00148 {
00149 throw rutz::error("missing legacy version id", SRC_POS);
00150 }
00151
00152 return version;
00153 }
00154
00155 void grab_left_brace()
00156 {
00157 char brace;
00158 m_stream >> brace;
00159 if (brace != '{')
00160 {
00161 dbg_print_nl(3, "grab_left_brace failed");
00162 throw rutz::error("missing left-brace", SRC_POS);
00163 }
00164 }
00165
00166 void grab_right_brace()
00167 {
00168 char brace;
00169 m_stream >> brace;
00170 if (brace != '}')
00171 {
00172 dbg_print_nl(3, "grab_right_brace failed");
00173 throw rutz::error("missing right-brace", SRC_POS);
00174 }
00175 }
00176
00177 void inflate_object(const fstring& name, ref<io::serializable> obj)
00178 {
00179 GVX_TRACE("io::legacy_reader::impl::inflate_object");
00180
00181 dbg_eval_nl(3, name);
00182
00183 m_legacy_version_id = get_legacy_version_id();
00184 if (m_legacy_version_id != -1)
00185 {
00186 grab_left_brace();
00187 obj->read_from(*m_owner);
00188 grab_right_brace();
00189 }
00190
00191 throw_if_error(name, SRC_POS);
00192 }
00193 };
00194
00196
00197
00198
00200
00201 io::legacy_reader::legacy_reader(std::istream& is) :
00202 rep(new impl(this, is))
00203 {
00204 GVX_TRACE("io::legacy_reader::legacy_reader");
00205 }
00206
00207 io::legacy_reader::~legacy_reader() throw()
00208 {
00209 GVX_TRACE("io::legacy_reader::~legacy_reader");
00210 delete rep;
00211 }
00212
00213 io::version_id io::legacy_reader::input_version_id()
00214 {
00215 GVX_TRACE("io::legacy_reader::input_version_id");
00216 dbg_eval_nl(3, rep->m_legacy_version_id);
00217 return rep->m_legacy_version_id;
00218 }
00219
00220 char io::legacy_reader::read_char(const fstring& name)
00221 {
00222 GVX_TRACE("io::legacy_reader::read_char");
00223 dbg_eval(3, name);
00224 char val;
00225 rep->m_stream >> val; dbg_eval_nl(3, val);
00226 rep->throw_if_error(name, SRC_POS);
00227 return val;
00228 }
00229
00230 int io::legacy_reader::read_int(const fstring& name)
00231 {
00232 GVX_TRACE("io::legacy_reader::read_int");
00233 dbg_eval(3, name);
00234 int val;
00235 rep->m_stream >> val; dbg_eval_nl(3, val);
00236 rep->throw_if_error(name, SRC_POS);
00237 return val;
00238 }
00239
00240 bool io::legacy_reader::read_bool(const fstring& name)
00241 {
00242 GVX_TRACE("io::legacy_reader::read_bool");
00243 dbg_eval(3, name);
00244 int val;
00245 rep->m_stream >> val; dbg_eval_nl(3, val);
00246 rep->throw_if_error(name, SRC_POS);
00247 return bool(val);
00248 }
00249
00250 double io::legacy_reader::read_double(const fstring& name)
00251 {
00252 GVX_TRACE("io::legacy_reader::read_double");
00253 dbg_eval(3, name);
00254 double val;
00255 rep->m_stream >> val; dbg_eval_nl(3, val);
00256 rep->throw_if_error(name, SRC_POS);
00257 return val;
00258 }
00259
00260 fstring io::legacy_reader::read_string_impl(const fstring& name)
00261 {
00262 GVX_TRACE("io::legacy_reader::read_string_impl");
00263 dbg_eval_nl(3, name);
00264
00265 int numchars = 0;
00266 rep->m_stream >> numchars;
00267
00268 rep->throw_if_error(name, SRC_POS);
00269
00270 if (numchars < 0)
00271 {
00272 throw rutz::error("legacy_reader::read_string_impl "
00273 "saw negative character count", SRC_POS);
00274 }
00275
00276 int c = rep->m_stream.get();
00277 if (c != ' ')
00278 {
00279 throw rutz::error("legacy_reader::read_string_impl "
00280 "did not have whitespace after character count", SRC_POS);
00281 }
00282
00283 fstring new_string;
00284 new_string.readsome(rep->m_stream, static_cast<unsigned int>(numchars));
00285
00286 rep->throw_if_error(name, SRC_POS);
00287
00288 dbg_eval_nl(3, new_string);
00289
00290 return new_string;
00291 }
00292
00293 void io::legacy_reader::read_value_obj(const fstring& name, rutz::value& v)
00294 {
00295 GVX_TRACE("io::legacy_reader::read_value_obj");
00296 dbg_eval_nl(3, name);
00297 v.scan_from(rep->m_stream);
00298 rep->throw_if_error(name, SRC_POS);
00299 }
00300
00301 ref<io::serializable>
00302 io::legacy_reader::read_object(const fstring& name)
00303 {
00304 GVX_TRACE("io::legacy_reader::read_object");
00305 return ref<io::serializable>(read_weak_object(name));
00306 }
00307
00308 soft_ref<io::serializable>
00309 io::legacy_reader::read_weak_object(const fstring& name)
00310 {
00311 GVX_TRACE("io::legacy_reader::read_weak_object");
00312 dbg_eval(3, name);
00313 fstring type;
00314 rep->m_stream >> type; dbg_eval(3, type);
00315
00316 if (type == "NULL")
00317 {
00318 return soft_ref<io::serializable>();
00319 }
00320
00321 ref<io::serializable> obj(nub::obj_mgr::new_typed_obj<io::serializable>(type));
00322 dbg_eval_nl(3, obj->obj_typename());
00323
00324 rep->inflate_object(name, obj);
00325
00326 return obj;
00327 }
00328
00329 void io::legacy_reader::read_owned_object(const fstring& name,
00330 ref<io::serializable> obj)
00331 {
00332 GVX_TRACE("io::legacy_reader::read_owned_object");
00333
00334 rep->read_typename(obj->obj_typename());
00335 rep->inflate_object(name, obj);
00336 }
00337
00338 void io::legacy_reader::read_base_class(const fstring& base_class_name,
00339 ref<io::serializable> base_part)
00340 {
00341 GVX_TRACE("io::legacy_reader::read_base_class");
00342
00343
00344
00345
00346 rep->read_typename(base_part->obj_typename(), base_class_name);
00347 rep->inflate_object(base_class_name, base_part);
00348 }
00349
00350 ref<io::serializable> io::legacy_reader::read_root(io::serializable* given_root)
00351 {
00352 GVX_TRACE("io::legacy_reader::read_root");
00353 if (given_root == 0)
00354 {
00355 return read_object("root_object");
00356 }
00357
00358 dbg_eval_nl(3, given_root->obj_typename());
00359
00360 ref<io::serializable> root(given_root);
00361 read_owned_object("root_object", root);
00362
00363 return root;
00364 }
00365
00367
00368
00369
00371
00372 class io::legacy_writer::impl
00373 {
00374 private:
00375 impl(const impl&);
00376 impl& operator=(const impl&);
00377
00378 public:
00379 impl(io::legacy_writer* owner, std::ostream& os, bool write_bases) :
00380 m_owner(owner),
00381 m_stream(os),
00382 m_write_bases(write_bases),
00383 m_field_sep(' '),
00384 m_indent_level(0),
00385 m_needs_newline(false),
00386 m_needs_whitespace(false),
00387 m_is_beginning(true),
00388 m_do_pretty_print(true)
00389 {}
00390
00391 void throw_if_error(const char* type, const rutz::file_pos& pos)
00392 {
00393 if (m_stream.fail())
00394 {
00395 dbg_print(3, "throw_if_error for"); dbg_eval_nl(3, type);
00396 throw rutz::error(type, pos);
00397 }
00398 }
00399
00400 io::legacy_writer* m_owner;
00401 private:
00402 std::ostream& m_stream;
00403 public:
00404 const bool m_write_bases;
00405 const char m_field_sep;
00406 int m_indent_level;
00407 bool m_needs_newline;
00408 bool m_needs_whitespace;
00409 bool m_is_beginning;
00410 bool m_do_pretty_print;
00411
00412 std::ostream& stream()
00413 {
00414 flush_whitespace();
00415 m_is_beginning = false;
00416 return m_stream;
00417 }
00418
00419 void flush_whitespace()
00420 {
00421 update_newline();
00422 update_whitespace();
00423 }
00424
00425 private:
00426 class Indenter
00427 {
00428 private:
00429 impl* m_owner;
00430
00431 Indenter(const Indenter&);
00432 Indenter& operator=(const Indenter&);
00433
00434 public:
00435 Indenter(impl* impl) : m_owner(impl) { ++(m_owner->m_indent_level); }
00436 ~Indenter() { --(m_owner->m_indent_level); }
00437 };
00438
00439 void do_newline_and_tabs()
00440 {
00441 m_stream << '\n';
00442 for (int i = 0; i < m_indent_level; ++i)
00443 m_stream << '\t';
00444 }
00445
00446 void do_whitespace()
00447 {
00448 if (m_do_pretty_print)
00449 do_newline_and_tabs();
00450 else
00451 m_stream << ' ';
00452 }
00453
00454 void update_newline()
00455 {
00456 if (m_needs_newline)
00457 {
00458 do_newline_and_tabs();
00459 no_newline_needed();
00460 no_whitespace_needed();
00461 }
00462 }
00463
00464 void update_whitespace()
00465 {
00466 if (m_needs_whitespace)
00467 {
00468 do_whitespace();
00469 no_whitespace_needed();
00470 }
00471 }
00472
00473 public:
00474 void use_pretty_print(bool yes) { m_do_pretty_print = yes; }
00475
00476 void request_newline() { if (!m_is_beginning) m_needs_newline = true; }
00477 void request_whitespace() { if (!m_is_beginning) m_needs_whitespace = true; }
00478 void no_newline_needed() { m_needs_newline = false; }
00479 void no_whitespace_needed() { m_needs_whitespace = false; }
00480
00481 void flatten_object(const char* obj_name,
00482 soft_ref<const io::serializable> obj,
00483 bool stub_out = false)
00484 {
00485 if (m_indent_level > 0)
00486 request_whitespace();
00487 else
00488 request_newline();
00489
00490 if ( !(obj.is_valid()) )
00491 {
00492 stream() << "NULL" << m_field_sep;
00493 throw_if_error(obj_name, SRC_POS);
00494 return;
00495 }
00496
00497 GVX_ASSERT(obj.is_valid());
00498
00499 stream() << obj->obj_typename() << m_field_sep;
00500 throw_if_error(obj->obj_typename().c_str(), SRC_POS);
00501
00502 stream() << '@';
00503
00504 if (stub_out)
00505 {
00506 stream() << "-1 ";
00507 }
00508 else
00509 {
00510 stream() << obj->class_version_id() << " {";
00511 {
00512 Indenter indent(this);
00513 request_whitespace();
00514 obj->write_to(*m_owner);
00515 }
00516 request_whitespace();
00517 stream() << "}";
00518 }
00519
00520 if (m_indent_level > 0)
00521 request_whitespace();
00522 else
00523 request_newline();
00524
00525 throw_if_error(obj_name, SRC_POS);
00526 }
00527 };
00528
00530
00531
00532
00534
00535
00536 io::legacy_writer::legacy_writer(std::ostream& os, bool write_bases) :
00537 rep(new impl(this, os, write_bases))
00538 {
00539 GVX_TRACE("io::legacy_writer::legacy_writer");
00540 }
00541
00542 io::legacy_writer::~legacy_writer() throw()
00543 {
00544 GVX_TRACE("io::legacy_writer::~legacy_writer");
00545 rep->flush_whitespace();
00546 delete rep;
00547 }
00548
00549 void io::legacy_writer::use_pretty_print(bool yes)
00550 {
00551 GVX_TRACE("io::legacy_writer::use_pretty_print");
00552 rep->use_pretty_print(yes);
00553 }
00554
00555 void io::legacy_writer::write_char(const char* name, char val)
00556 {
00557 GVX_TRACE("io::legacy_writer::write_char");
00558 rep->stream() << val << rep->m_field_sep;
00559 rep->throw_if_error(name, SRC_POS);
00560 }
00561
00562 void io::legacy_writer::write_int(const char* name, int val)
00563 {
00564 GVX_TRACE("io::legacy_writer::write_int");
00565 rep->stream() << val << rep->m_field_sep;
00566 rep->throw_if_error(name, SRC_POS);
00567 }
00568
00569 void io::legacy_writer::write_bool(const char* name, bool val)
00570 {
00571 GVX_TRACE("io::legacy_writer::write_bool");
00572 rep->stream() << val << rep->m_field_sep;
00573 rep->throw_if_error(name, SRC_POS);
00574 }
00575
00576 void io::legacy_writer::write_double(const char* name, double val)
00577 {
00578 GVX_TRACE("io::legacy_writer::write_double");
00579 rep->stream() << val << rep->m_field_sep;
00580 rep->throw_if_error(name, SRC_POS);
00581 }
00582
00583 void io::legacy_writer::write_cstring(const char* name, const char* val)
00584 {
00585 GVX_TRACE("io::legacy_writer::write_cstring");
00586
00587 rep->stream() << strlen(val) << " " << val << rep->m_field_sep;
00588
00589 rep->throw_if_error(name, SRC_POS);
00590 }
00591
00592 void io::legacy_writer::write_value_obj(const char* name,
00593 const rutz::value& v)
00594 {
00595 GVX_TRACE("io::legacy_writer::write_value_obj");
00596 v.print_to(rep->stream());
00597 rep->stream() << rep->m_field_sep;
00598 rep->throw_if_error(name, SRC_POS);
00599 }
00600
00601 void io::legacy_writer::write_byte_array(const char* name,
00602 const unsigned char* data,
00603 unsigned int length)
00604 {
00605 GVX_TRACE("io::legacy_writer::write_byte_array");
00606 default_write_byte_array(name, data, length);
00607 }
00608
00609 void io::legacy_writer::write_object(const char* name,
00610 soft_ref<const io::serializable> obj)
00611 {
00612 GVX_TRACE("io::legacy_writer::write_object");
00613
00614 rep->flatten_object(name, obj);
00615 }
00616
00617 void io::legacy_writer::write_owned_object(const char* name,
00618 ref<const io::serializable> obj)
00619 {
00620 GVX_TRACE("io::legacy_writer::write_owned_object");
00621
00622 rep->flatten_object(name, obj);
00623 }
00624
00625 void io::legacy_writer::write_base_class(const char* base_class_name,
00626 ref<const io::serializable> base_part)
00627 {
00628 GVX_TRACE("io::legacy_writer::write_base_class");
00629 if (rep->m_write_bases)
00630 {
00631 rep->flatten_object(base_class_name, base_part);
00632 }
00633 else
00634 {
00635 rep->flatten_object(base_class_name, base_part, true);
00636 }
00637 }
00638
00639 void io::legacy_writer::write_root(const io::serializable* root)
00640 {
00641 GVX_TRACE("io::legacy_writer::write_root");
00642
00643 rep->flatten_object
00644 ("root_object", soft_ref<io::serializable>(const_cast<io::serializable*>(root),
00645 nub::STRONG,
00646 nub::PRIVATE));
00647 }
00648
00649 static const char __attribute__((used)) vcid_groovx_io_iolegacy_cc_utc20050626084021[] = "$Id: iolegacy.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00650 #endif // !GROOVX_IO_IOLEGACY_CC_UTC20050626084021_DEFINED