parens_serializer.hpp

Go to the documentation of this file.
00001 #ifndef parens_SERIALIZER_H_INCLUDED
00002 #define parens_SERIALIZER_H_INCLUDED 1
00003 
00004 ////////////////////////////////////////////////////////////////////////
00005 // data_node_serializers.hpp: some file parsers for the s11n framework
00006 //
00007 // License: Public Domain
00008 // Author: stephan@s11n.net
00009 ////////////////////////////////////////////////////////////////////////
00010 
00011 #include <s11n.net/s11n/io/data_node_format.hpp> // base interfaces
00012 #include <s11n.net/s11n/traits.hpp> // node_traits
00013 
00014 #define MAGIC_COOKIE_PARENS "(s11n::parens)"
00015 #define INDENT(LEVEL,ECHO) indent = ""; for( size_t i = 0; i < depth + LEVEL; i++ ) { indent += '\t'; if(ECHO) dest << '\t'; }
00016 
00017 namespace s11n {
00018     namespace io {
00019 
00020                 namespace sharing {
00021                         /**
00022                            Sharing context used by parens_serializer.
00023                         */
00024                         struct parens_sharing_context {};
00025                 }
00026 
00027 
00028                 /**
00029                    The entity translations map used by parens_serializer.
00030                  */
00031                 entity_translation_map & parens_serializer_translations();
00032 
00033                 /**
00034                    De/serializes objects from/to a lisp-like grammar.
00035                 */
00036                 template <typename NodeType>
00037                 class parens_serializer : public tree_builder_lexer<NodeType,sharing::parens_sharing_context>
00038                 {
00039                 public:
00040                         typedef NodeType node_type;
00041 
00042                         typedef parens_serializer<node_type> this_type; // convenience typedef
00043                         typedef tree_builder_lexer<node_type,sharing::parens_sharing_context> parent_type; // convenience typedef
00044 
00045                         parens_serializer() : parent_type( "parens_data_nodeFlexLexer" ),
00046                                               m_depth(0)
00047                         {
00048                                 this->magic_cookie( MAGIC_COOKIE_PARENS );
00049                         }
00050 
00051                         virtual ~parens_serializer() {}
00052 
00053                         typedef entity_translation_map translation_map;
00054 
00055                         /**
00056                            Reimplemented to return this type's entity
00057                            translation map.
00058                          */
00059                         virtual const translation_map & entity_translations() const
00060                         {
00061                                 return parens_serializer_translations();
00062                         }
00063 
00064                         /**
00065                            Writes src out to dest.
00066                         */
00067                         virtual bool serialize( const node_type & src, std::ostream & dest )
00068             {
00069                 try
00070                 {
00071                     return this->serialize_impl( src, dest );
00072                 }
00073                 catch(...)
00074                 {
00075                     this->m_depth = 0;
00076                     throw;
00077                 }
00078                 return false; // can't get this far.
00079             }
00080 
00081 
00082         private:
00083                         /**
00084                            Writes src out to dest.
00085                         */
00086                         bool serialize_impl( const node_type & src, std::ostream & dest )
00087                         {
00088                                 typedef ::s11n::node_traits<node_type> NT;
00089                                 size_t depth = this->m_depth++;
00090                                 if( 0 == depth )
00091                                 {
00092                                         dest << this->magic_cookie()
00093 //                                              << "\n(* serializer info: "
00094 //                                              << "\n\t" << PARENS_VERSION
00095 //                                              << "\n\tBuilt " << __TIME__ << " on " __DATE__
00096 //                                              << "\n*)"
00097                                              << "\n";
00098                                 }
00099 
00100                                 std::string indent;
00101                                 std::string implclass = NT::class_name(src);
00102 
00103                                 // i know this quote check is fairly expensive, but 2 bytes per
00104                                 // object adds up. Consider: 10k objects would take up
00105                                 // 20k bytes just in classname quotes!
00106                                 std::string quote =
00107                                         (std::string::npos != implclass.find('<'))
00108                                         ? "\""
00109                                         : "";
00110                                 dest << NT::name(src) << "=" << this->m_open
00111                                      << quote << implclass << quote;
00112 
00113                                 typename NT::property_map_type::const_iterator beg = NT::properties(src).begin(),
00114                                         end = NT::properties(src).end();
00115                                 if( end != beg )
00116                                 {
00117                                         //INDENT(1,0);
00118                                         std::for_each(beg, end,
00119                                                       key_value_serializer<node_type>(
00120                                                               &(this->entity_translations()),
00121                                                               dest,
00122                                                               /* indent + */ ' ' + this->m_open ,
00123                                                               " ",
00124                                                               this->m_close )
00125                                                       );
00126                                 }
00127                                 typename NT::child_list_type::const_iterator chbeg = NT::children(src).begin(),
00128                                         chend = NT::children(src).end();
00129                                 if( chend != chbeg )
00130                                 { // got children?
00131                                         dest << '\n';
00132                                         INDENT(1,0);
00133                     for( ; chend != chbeg; ++chbeg )
00134                     {
00135                         dest << indent;
00136                         this->serialize_impl( *(*chbeg), dest );
00137                     }
00138                                         INDENT(0,1);
00139                                 }
00140 
00141                                 dest << this->m_close << '\n';
00142 
00143                                 if( 0 == depth )
00144                                 {
00145                                         dest.flush(); // << std::endl; // else client may be forced to manually flush().
00146                                 }
00147                                 --this->m_depth;
00148                                 return true;
00149                         }
00150 
00151 
00152 
00153                 private:
00154                         size_t m_depth;
00155                         static const std::string m_open;
00156                         static const std::string m_close;
00157                 };
00158                 template <typename NodeType>
00159                 const std::string parens_serializer<NodeType>::m_open = "(";
00160                 template <typename NodeType>
00161                 const std::string parens_serializer<NodeType>::m_close = ")";
00162 
00163     } // namespace io
00164 } // namespace s11n
00165 
00166 #undef PARENS_VERSION
00167 #undef INDENT
00168 
00169 #endif // parens_SERIALIZER_H_INCLUDED

Generated on Wed Jun 4 21:44:19 2008 for libs11n by  doxygen 1.5.3