wesnoth_serializer.hpp

Go to the documentation of this file.
00001 #ifndef wesnoth_SERIALIZER_H_INCLUDED
00002 #define wesnoth_SERIALIZER_H_INCLUDED 1
00003 
00004 ////////////////////////////////////////////////////////////////////////
00005 // License: Public Domain
00006 // Author: stephan@s11n.net
00007 ////////////////////////////////////////////////////////////////////////
00008 
00009 #include <s11n.net/s11n/io/data_node_format.hpp>
00010 #include <s11n.net/s11n/traits.hpp> // node_traits
00011 #include <s11n.net/s11n/io/strtool.hpp> // translate_entities()
00012 #define MAGIC_COOKIE_WESNOTH "#s11n::io::wesnoth_serializer"
00013 
00014 #define INDENT(LEVEL,ECHO) indent = ""; for( size_t i = 0; i < depth + LEVEL; i++ ) { indent += '\t'; if(ECHO) dest << '\t'; }
00015 
00016 namespace s11n { namespace io {
00017         namespace sharing {
00018                 /**
00019                    Sharing context used by wesnoth_serializer.
00020                 */
00021                 struct wesnoth_sharing_context {};
00022 
00023         }
00024 
00025         /** convenience typedef */
00026         typedef std::map<std::string,std::string> entity_translation_map;
00027 
00028         /**
00029            The entity translations map used by wesnoth_serializer.
00030         */
00031         entity_translation_map & wesnoth_serializer_translations();
00032 
00033         /**
00034            De/serializes objects from/to this class' config-file-like grammar.
00035        It gets its name, and most of its grammar, from the Open Source
00036        strategy/adventure game "The Battle for Wesnoth" (www.wesnoth.org).
00037         */
00038         template <typename NodeType>
00039         class wesnoth_serializer : public tree_builder_lexer<NodeType,sharing::wesnoth_sharing_context>
00040         {
00041         public:
00042                 typedef NodeType node_type;
00043 
00044                 typedef wesnoth_serializer<node_type> this_type; // convenience typedef
00045                 typedef tree_builder_lexer<node_type,sharing::wesnoth_sharing_context> parent_type; // convenience typedef
00046 
00047                 wesnoth_serializer() : parent_type( "wesnoth_data_nodeFlexLexer" ), m_depth(0)
00048                 {
00049                         this->magic_cookie( MAGIC_COOKIE_WESNOTH );
00050                 }
00051 
00052                 virtual ~wesnoth_serializer() {}
00053 
00054                 /**
00055                    Reimplemented to return this type's entity
00056                    translation map.
00057                 */
00058                 virtual const entity_translation_map & entity_translations() const
00059                 {
00060                         return wesnoth_serializer_translations();
00061                 }
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     private:
00082                 /**
00083                    Writes src out to dest.
00084                 */
00085                 bool serialize_impl( const node_type & src, std::ostream & dest )
00086                 {
00087                         typedef ::s11n::node_traits<node_type> NT;
00088                         size_t depth = this->m_depth++;
00089                         if ( 0 == depth )
00090                         {
00091                                 dest << this->magic_cookie() << '\n';
00092                         }
00093                         const static char open = '[';
00094                         const static char close = ']';
00095 
00096                         std::string nname = NT::name(src);
00097                         std::string impl = NT::class_name(src);
00098                         dest << open << nname << "=" << impl << close <<"\n";
00099 
00100                         std::string indent;
00101                         std::string propval;
00102                         std::string key;
00103 
00104                         INDENT(0,0);
00105                         typedef typename NT::property_map_type::const_iterator PCIT;
00106                         PCIT pit = NT::properties(src).begin();
00107             PCIT pet = NT::properties(src).end();
00108                         std::string val;
00109                         const static std::string nonquoted = "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
00110                         for( ; pet != pit; ++pit )
00111                         {
00112                                 dest << indent << (*pit).first << "=";
00113                 val = (*pit).second;
00114                                 ::s11n::io::strtool::translate_entities( val, this->entity_translations(), false );
00115                                 if( std::string::npos != val.find_first_not_of( nonquoted ) )
00116                                 {
00117                                         dest << "\"" << val << "\"";
00118                                 }
00119                                 else
00120                                 {
00121                                         dest << val;
00122                                 }
00123                                 dest << "\n";
00124                         }
00125             typedef typename NT::child_list_type CLT;
00126             typedef typename CLT::const_iterator CLIT;
00127             CLIT cit = NT::children(src).begin();
00128             CLIT cet = NT::children(src).end();
00129                         if( cet != cit )
00130                         {
00131                                 INDENT(1,0);
00132                 for( ; cet != cit; ++cit )
00133                 {
00134                     dest << indent;
00135                     this->serialize_impl( *(*cit), dest );
00136                 }
00137                         }
00138                         INDENT(0,1);
00139                         dest << open << "/"<< nname << close <<"\n";
00140                         if( 0 == depth )
00141                         {
00142                                 dest.flush();
00143                                 // if we don't do this then the client is possibly forced to flush() the stream :/
00144                         }
00145                         --this->m_depth;
00146                         return true;
00147                 }
00148 
00149         private:
00150                 size_t m_depth;
00151         };
00152 
00153 
00154 
00155 
00156 
00157 } } // namespace s11n::io
00158 
00159 #undef INDENT
00160 #endif // wesnoth_SERIALIZER_H_INCLUDED

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