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_ASCIISTREAMWRITER_CC_UTC20050626084021_DEFINED
00035 #define GROOVX_IO_ASCIISTREAMWRITER_CC_UTC20050626084021_DEFINED
00036
00037 #include "io/asciistreamwriter.h"
00038
00039 #include "io/attribcount.h"
00040 #include "io/io.h"
00041 #include "io/writeidmap.h"
00042 #include "io/writer.h"
00043
00044 #include "nub/ref.h"
00045
00046 #include "rutz/arrays.h"
00047 #include "rutz/fstring.h"
00048 #include "rutz/gzstreambuf.h"
00049 #include "rutz/value.h"
00050
00051 #include <ostream>
00052 #include <string>
00053 #include <set>
00054 #include <vector>
00055
00056 #include "rutz/trace.h"
00057 #include "rutz/debug.h"
00058 GVX_DBG_REGISTER
00059
00060 using rutz::fstring;
00061 using rutz::shared_ptr;
00062
00063 using nub::ref;
00064 using nub::soft_ref;
00065
00066 using std::vector;
00067 using std::set;
00068
00069 namespace
00070 {
00071 const char* ATTRIB_ENDER = "^\n";
00072
00073 void add_escapes(std::string& text)
00074 {
00075 GVX_TRACE("<asciistreamwriter.cc>::add_escapes");
00076
00077 for (size_t pos = 0; pos < text.length(); )
00078 {
00079 switch (text[pos])
00080 {
00081 case '\\':
00082 text.replace(pos, 1, "\\\\");
00083 pos += 2;
00084 break;
00085 case '^':
00086 text.replace(pos, 1, "\\c");
00087 pos += 2;
00088 break;
00089 case '{':
00090 text.replace(pos, 1, "\\{");
00091 pos += 2;
00092 break;
00093 case '}':
00094 text.replace(pos, 1, "\\}");
00095 pos += 2;
00096 break;
00097 default:
00098 ++pos;
00099 break;
00100 }
00101 }
00102 }
00103
00104 class asw_writer : public io::writer
00105 {
00106 public:
00107 asw_writer(std::ostream& os);
00108
00109 asw_writer(const char* filename);
00110
00111 virtual ~asw_writer() throw();
00112
00113 virtual void write_char(const char* name, char val);
00114 virtual void write_int(const char* name, int val);
00115 virtual void write_bool(const char* name, bool val);
00116 virtual void write_double(const char* name, double val);
00117 virtual void write_value_obj(const char* name, const rutz::value& v);
00118
00119 virtual void write_byte_array(const char* name,
00120 const unsigned char* data,
00121 unsigned int length)
00122 { default_write_byte_array(name, data, length); }
00123
00124 virtual void write_object(const char* name,
00125 nub::soft_ref<const io::serializable> obj);
00126
00127 virtual void write_owned_object(const char* name,
00128 nub::ref<const io::serializable> obj);
00129
00130 virtual void write_base_class(const char* base_class_name,
00131 nub::ref<const io::serializable> base_part);
00132
00133 virtual void write_root(const io::serializable* root);
00134
00135 protected:
00136 virtual void write_cstring(const char* name, const char* val);
00137
00138 private:
00139 shared_ptr<std::ostream> m_owned_stream;
00140 std::ostream& m_buf;
00141 mutable vector<soft_ref<const io::serializable> > m_pending_objs;
00142 set<soft_ref<const io::serializable> > m_written_objs;
00143 io::write_id_map m_id_map;
00144
00145 void add_pending_object(soft_ref<const io::serializable> obj)
00146 {
00147 if ( !already_written(obj) )
00148 {
00149 m_pending_objs.push_back(obj);
00150 }
00151 }
00152
00153 bool already_written(soft_ref<const io::serializable> obj) const
00154 {
00155 return ( m_written_objs.find(obj) !=
00156 m_written_objs.end() );
00157 }
00158
00159 void mark_as_written(soft_ref<const io::serializable> obj)
00160 {
00161 m_written_objs.insert(obj);
00162 }
00163
00164 void flatten_object(soft_ref<const io::serializable> obj);
00165
00166 template <class T>
00167 void write_basic_type(const char* name, T val,
00168 const char* string_typename)
00169 {
00170 m_buf << string_typename << " "
00171 << name << " := "
00172 << val << ATTRIB_ENDER;
00173 }
00174
00175 void write_string_type(const char* name, const char* val)
00176 {
00177 std::string escaped_val(val);
00178 int val_length = escaped_val.length();
00179 add_escapes(escaped_val);
00180
00181 m_buf << "cstring "
00182 << name << " := "
00183 << val_length << " " << escaped_val.c_str() << ATTRIB_ENDER;
00184 }
00185 };
00186
00188
00189
00190
00192
00193 asw_writer::asw_writer(std::ostream& os) :
00194 m_owned_stream(),
00195 m_buf(os),
00196 m_pending_objs(),
00197 m_written_objs()
00198 {
00199 GVX_TRACE("asw_writer::asw_writer");
00200 }
00201
00202 asw_writer::asw_writer(const char* filename) :
00203 m_owned_stream(rutz::ogzopen(filename)),
00204 m_buf(*m_owned_stream),
00205 m_pending_objs(),
00206 m_written_objs()
00207 {
00208 GVX_TRACE("asw_writer::asw_writer(const char*)");
00209 }
00210
00211 asw_writer::~asw_writer () throw()
00212 {
00213 GVX_TRACE("asw_writer::~asw_writer");
00214 }
00215
00216 void asw_writer::write_char(const char* name, char val)
00217 {
00218 GVX_TRACE("asw_writer::write_char");
00219 write_basic_type(name, val, "char");
00220 }
00221
00222 void asw_writer::write_int(const char* name, int val)
00223 {
00224 GVX_TRACE("asw_writer::write_int");
00225 write_basic_type(name, val, "int");
00226 }
00227
00228 void asw_writer::write_bool(const char* name, bool val)
00229 {
00230 GVX_TRACE("asw_writer::write_bool");
00231 write_basic_type(name, val, "bool");
00232 }
00233
00234 void asw_writer::write_double(const char* name, double val)
00235 {
00236 GVX_TRACE("asw_writer::write_double");
00237 write_basic_type(name, val, "double");
00238 }
00239
00240 void asw_writer::write_cstring(const char* name, const char* val)
00241 {
00242 GVX_TRACE("asw_writer::write_cstring");
00243 write_string_type(name, val);
00244 }
00245
00246 void asw_writer::write_value_obj(const char* name,
00247 const rutz::value& v)
00248 {
00249 GVX_TRACE("asw_writer::write_value_obj");
00250
00251 write_basic_type<const rutz::value&>(name, v, v.value_typename().c_str());
00252 }
00253
00254 void asw_writer::write_object(const char* name,
00255 soft_ref<const io::serializable> obj)
00256 {
00257 GVX_TRACE("asw_writer::write_object");
00258
00259 fstring type = "NULL";
00260 nub::uid id = 0;
00261
00262 if (obj.is_valid())
00263 {
00264 GVX_ASSERT(dynamic_cast<const io::serializable*>(obj.get()) != 0);
00265
00266 type = obj->obj_typename();
00267 id = m_id_map.get(obj->id());
00268
00269 add_pending_object(obj);
00270 }
00271
00272 m_buf << type << " "
00273 << name << " := "
00274 << id << ATTRIB_ENDER;
00275 }
00276
00277 void asw_writer::write_owned_object(const char* name,
00278 ref<const io::serializable> obj)
00279 {
00280 GVX_TRACE("asw_writer::write_owned_object");
00281
00282 fstring type = obj->obj_typename().c_str();
00283
00284 m_buf << type.c_str() << ' ' << name << " := ";
00285
00286 flatten_object(obj);
00287
00288 m_buf << ATTRIB_ENDER;
00289 }
00290
00291 void asw_writer::write_base_class(const char* base_class_name,
00292 ref<const io::serializable> base_part)
00293 {
00294 GVX_TRACE("asw_writer::write_base_class");
00295 write_owned_object(base_class_name, base_part);
00296 }
00297
00298 void asw_writer::write_root(const io::serializable* root)
00299 {
00300 GVX_TRACE("asw_writer::write_root");
00301 m_pending_objs.clear();
00302 m_written_objs.clear();
00303
00304
00305
00306
00307
00308
00309 m_pending_objs.push_back
00310 (soft_ref<io::serializable>(const_cast<io::serializable*>(root)));
00311
00312 while ( !m_pending_objs.empty() )
00313 {
00314 soft_ref<const io::serializable> obj = m_pending_objs.back();
00315 m_pending_objs.pop_back();
00316
00317 if ( !already_written(obj) )
00318 {
00319 m_buf << obj->obj_typename().c_str() << ' '
00320 << m_id_map.get(obj->id()) << " := ";
00321 flatten_object(obj);
00322 }
00323 }
00324
00325 m_buf.flush();
00326 }
00327
00328 void asw_writer::flatten_object(soft_ref<const io::serializable> obj)
00329 {
00330 GVX_TRACE("asw_writer::flatten_object");
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 m_buf << "{ ";
00341
00342
00343 io::version_id serial_ver_id = obj->class_version_id();;
00344 if ( serial_ver_id > 0 )
00345 m_buf << 'v' << serial_ver_id << ' ';
00346
00347
00348 m_buf << io::attrib_count(*obj) << '\n';
00349
00350
00351 obj->write_to(*this);
00352
00353 mark_as_written(obj);
00354
00355
00356 m_buf << '}' << '\n';
00357 }
00358 }
00359
00360 shared_ptr<io::writer> io::make_asw_writer(std::ostream& os)
00361 {
00362 return rutz::make_shared(new asw_writer(os));
00363 }
00364
00365 shared_ptr<io::writer> io::make_asw_writer(const char* filename)
00366 {
00367 return rutz::make_shared(new asw_writer(filename));
00368 }
00369
00370 static const char __attribute__((used)) vcid_groovx_io_asciistreamwriter_cc_utc20050626084021[] = "$Id: asciistreamwriter.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00371 #endif // !GROOVX_IO_ASCIISTREAMWRITER_CC_UTC20050626084021_DEFINED