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