asciistreamwriter.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 1999-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: Mon Jun  7 13:05:57 1999
00010 // commit: $Id: asciistreamwriter.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/io/asciistreamwriter.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_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     // Escape any special characters
00077     for (size_t pos = 0; pos < text.length(); /* ++ done in loop body */ )
00078       {
00079         switch (text[pos])
00080           {
00081           case '\\': // i.e., a single backslash
00082             text.replace(pos, 1, "\\\\"); // i.e., two backslashes
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   // asw_writer member definitions
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     // need the const_cast here because:
00305     // (1) soft_ref constructor will optionally call Detail::insert_item()
00306     // (2) insert_item() will put the object in the nub::objectdb
00307     // (3) objects in the nub::objectdb are non-const since they can be
00308     //     retrieved and modified
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     // Objects are written in the following format:
00333     //
00334     // { ?<version id>? <attribute count>
00335     // ...attributes...
00336     // }
00337     //
00338 
00339     // Open the object's braces...
00340     m_buf << "{ ";
00341 
00342     //   ...write <version id> if it is nonzero...
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     //   ...write the <attribute count>...
00348     m_buf << io::attrib_count(*obj) << '\n';
00349 
00350     //   ...write the object's <attributes>...
00351     obj->write_to(*this);
00352 
00353     mark_as_written(obj);
00354 
00355     //   ...and finally, close the object's braces.
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

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.