funxml_serializer.hpp

Go to the documentation of this file.
00001 #ifndef funxml_SERIALIZER_H_INCLUDED
00002 #define funxml_SERIALIZER_H_INCLUDED 1
00003 
00004 ////////////////////////////////////////////////////////////////////////
00005 // funxml_serializer.hpp: an XML dialect for the s11n framework
00006 //
00007 // License: Public Domain
00008 // Author: stephan@s11n.net
00009 ////////////////////////////////////////////////////////////////////////
00010 
00011 
00012 #include <s11n.net/s11n/io/strtool.hpp> // translate_entities()
00013 
00014 #include <s11n.net/s11n/traits.hpp> // node_traits
00015 #include <s11n.net/s11n/s11n_debuggering_macros.hpp> // COUT/CERR
00016 #include <s11n.net/s11n/io/data_node_format.hpp>
00017 
00018 
00019 #define MAGIC_COOKIE_FUNXML "<!DOCTYPE SerialTree>"
00020 
00021 namespace s11n {
00022     namespace io {
00023                 namespace sharing {
00024                         /**
00025                            Sharing context used by funxml_serializer.
00026                          */
00027                         struct funxml_sharing_context {};
00028 
00029                 }
00030                 /** convenience typedef */
00031                 typedef std::map<std::string,std::string> entity_translation_map;
00032 
00033 
00034                 /**
00035                    The entity translations map used by funxml_serializer.
00036                  */
00037                 entity_translation_map & funxml_serializer_translations();
00038 
00039 
00040 
00041                 /**
00042                    De/serializes objects from/to a simple XML grammar,
00043                    with all properties and children stored as subnodes.
00044                 */
00045                 template <typename NodeType>
00046                 class funxml_serializer : public tree_builder_lexer<NodeType,sharing::funxml_sharing_context>
00047                 {
00048                 public:
00049                         typedef NodeType node_type;
00050 
00051                         typedef funxml_serializer<node_type> this_type; // convenience typedef
00052                         typedef tree_builder_lexer<node_type,sharing::funxml_sharing_context> parent_type; // convenience typedef
00053 
00054                         funxml_serializer() : parent_type( "funxml_data_nodeFlexLexer" ), m_depth(0)
00055                         {
00056                                 this->magic_cookie( MAGIC_COOKIE_FUNXML );
00057                         }
00058 
00059                         virtual ~funxml_serializer() {}
00060 
00061                         /**
00062                            Reimplemented to return this type's entity
00063                            translation map.
00064                          */
00065                         virtual const entity_translation_map & entity_translations() const
00066                         {
00067                                 return funxml_serializer_translations();
00068                         }
00069 
00070 
00071                         /**
00072                            Overridden to parse src using this object's grammar rules.
00073                         */
00074                         virtual node_type * deserialize( std::istream & src )
00075                         {
00076                                 return deserialize_lex_forwarder<node_type,sharing::funxml_sharing_context>( "funxml_data_nodeFlexLexer", src );
00077                                 //CERR << "deserialize() returning " << std::hex << ret << "\n";
00078                         }
00079 
00080                         virtual node_type * deserialize( const std::string & src )
00081                         { // Forwarding this avoids an odd compiler error sometimes,
00082                           // where the compiler doesn't see that this function
00083                           // exists which called from client code. ???
00084                                 return this->parent_type::deserialize( src );
00085                         }
00086 
00087 
00088                         /**
00089                            Writes src out to dest.
00090                         */
00091                         virtual bool serialize( const node_type & src, std::ostream & dest )
00092             {
00093                 try
00094                 {
00095                     return this->serialize_impl( src, dest );
00096                 }
00097                 catch(...)
00098                 {
00099                     this->m_depth = 0;
00100                     throw;
00101                 }
00102                 return false; // can't get this far.
00103             }
00104 
00105 
00106         private:
00107                         /**
00108                            Writes src out to dest.
00109                         */
00110                         bool serialize_impl( const node_type & src, std::ostream & dest )
00111                         {
00112 
00113                                 typedef ::s11n::node_traits<node_type> NT;
00114 // INDENT() is a helper macro for some serializers.
00115 #define INDENT(LEVEL,ECHO) indent = ""; for( size_t i = 0; i < depth + LEVEL; i++ ) { indent += '\t'; if(ECHO) dest << '\t'; }
00116                                 size_t depth = this->m_depth++;
00117                                 if ( 0 == depth )
00118                                 {
00119                                         dest << this->magic_cookie() << '\n';
00120                                 }
00121 
00122 
00123                                 std::string nname = NT::name(src);
00124                                 std::string impl = NT::class_name(src);
00125                                 strtool::translate_entities( impl, this->entity_translations(), false ); // handle class templates
00126 
00127                                 std::string indent;
00128 
00129 
00130                                 dest << "<" << nname << " class=\"" << impl << "\">\n";
00131                                 typename NT::property_map_type::const_iterator pit = NT::properties(src).begin(),
00132                                         pet = NT::properties(src).end();
00133 
00134 
00135                                 std::string propval;
00136                                 std::string key;
00137 
00138                                 INDENT(1,0);
00139                                 for ( ; pet != pit; ++pit )
00140                                 {
00141                                         key = ( *pit ).first;
00142                                         propval = ( *pit ).second;
00143                                         strtool::translate_entities( propval, this->entity_translations(), false );
00144                                         dest << indent;
00145                                         dest << "<" << key << ">";
00146                                         dest << propval;
00147                                         dest << "</" << key << ">\n";
00148                                 }
00149                                 INDENT(1,0);
00150 
00151                 typedef typename NT::child_list_type CLT;
00152                 typedef typename CLT::const_iterator CLIT;
00153                 CLIT cit = NT::children(src).begin();
00154                 CLIT cet = NT::children(src).end();
00155                 for( ; cet != cit; ++cit )
00156                 {
00157                     dest << indent;
00158                     this->serialize_impl( *(*cit), dest );
00159                 }
00160 
00161                                 INDENT(0,1);
00162                                 dest << "</" << nname << ">\n";
00163                                 if( 0 == depth )
00164                                 {
00165                                         dest.flush();
00166                                         // if we don't do this then the client is possibly forced to flush() the stream :/
00167                                 }
00168                                 --this->m_depth;
00169                                 return true;
00170 #undef INDENT
00171                         }
00172 
00173                 private:
00174                         size_t m_depth;
00175                 };
00176 
00177     } // namespace io
00178 } // namespace s11n
00179 
00180 #endif // funxml_SERIALIZER_H_INCLUDED

Generated on Sun Apr 27 11:48:19 2008 for libs11n-1.2.6 by  doxygen 1.5.3