xmlwriter.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 2003-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Thu Jun 19 18:26:48 2003
00010 // commit: $Id: xmlwriter.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/io/xmlwriter.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
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 // xml_writer member definitions
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   // special case for empty string:
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   // Escape any special characters
00308   for ( ; *p != '\0'; ++p)
00309     {
00310       switch (*p)
00311         {
00312         case '<':  m_buf.write("&lt;",   4); break;
00313         case '>':  m_buf.write("&gt;",   4); break;
00314         case '&':  m_buf.write("&amp;",  5); break;
00315         case '"':  m_buf.write("&quot;", 6); break;
00316         case '\'': m_buf.write("&apos;", 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

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:39 2008 by Doxygen version 1.5.5.