compact_serializer.hpp

Go to the documentation of this file.
00001 #ifndef compact_SERIALIZER_H_INCLUDED
00002 #define compact_SERIALIZER_H_INCLUDED 1
00003 
00004 ////////////////////////////////////////////////////////////////////////
00005 // compact_serializer.hpp: a binary-like serializer 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_COMPACT "51191011"
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 compact_serializer.
00023                         */
00024                         struct compact_sharing_context {};
00025                 }
00026 
00027                 /**
00028                    De/serializes objects from/to a compact binary-like grammar.
00029                 */
00030                 template <typename NodeType>
00031                 class compact_serializer : public tree_builder_lexer<NodeType,sharing::compact_sharing_context>
00032                 {
00033                 public:
00034                         typedef NodeType node_type;
00035 
00036                         typedef compact_serializer<node_type> this_type; // convenience typedef
00037                         typedef tree_builder_lexer<node_type,sharing::compact_sharing_context> parent_type; // convenience typedef
00038 
00039                         compact_serializer() : parent_type( "compact_data_nodeFlexLexer" ),
00040                                               m_depth(0)
00041                         {
00042                                 this->magic_cookie( MAGIC_COOKIE_COMPACT );
00043                         }
00044 
00045                         virtual ~compact_serializer() {}
00046 
00047                         typedef entity_translation_map translation_map;
00048 
00049 //                         /**
00050 //             Tries to read a new node from src. The caller owns the returned
00051 //             pointer, which may be null.
00052 //                         */
00053 //                         virtual node_type * deserialize( std::istream & is )
00054 //                         {
00055 //                                 return 0;
00056 //                         }
00057 
00058 
00059                         /**
00060                            Writes src out to dest.
00061                         */
00062                         virtual bool serialize( const node_type & src, std::ostream & dest )
00063             {
00064                 try
00065                 {
00066                     return this->serialize_impl( src, dest );
00067                 }
00068                 catch(...)
00069                 {
00070                     this->m_depth = 0;
00071                     throw;
00072                 }
00073                 return false; // can't get this far.
00074             }
00075 
00076 
00077         private:
00078             bool serialize_impl( const node_type & src, std::ostream & dest )
00079                         {
00080                                 typedef ::s11n::node_traits<node_type> node_traits;
00081 
00082                                 static const int ctrlwidth = 2;
00083                                 static const int size2b = 2;
00084                                 static const int size4b = 4;
00085                                 static const int cookiewidth = 8;
00086                                 
00087                                 static const unsigned long Magic_Cookie_4B = 0x51191011;
00088                                 static const unsigned long Node_Open = 0xf1;
00089                                 static const unsigned long Node_Close = 0xf0;
00090                                 static const unsigned long Prop_Open =  0xe1;
00091                                 static const unsigned long Data_End = 0x51190000; // not strictly necessary
00092 
00093 
00094 
00095                                 std::string nname = node_traits::name( src );
00096                                 std::string impl = node_traits::class_name( src );
00097                                 std::string::size_type sizE = 0;
00098                                 std::string::size_type ins;
00099                                 // WTF must all this stream manip be done on every fucking insert?
00100 #define OS_INT(C,W) dest.width(W);dest<<std::hex<<std::right<<(unsigned int)(C);
00101 #define INSERT(vaR,WIDTH) sizE = vaR.size(); OS_INT(sizE,WIDTH); \
00102                 for( ins = 0; ins < sizE; ins++ ) {\
00103             /*OS_INT(vaR[ins],charwidth);*/ \
00104             dest << (unsigned char) vaR[ins]; \
00105         };
00106                                 size_t depth = this->m_depth++;
00107                                 
00108                                 if ( 0 == depth )
00109                                 {
00110                                         dest.setf( std::ios_base::hex );
00111                                         dest.fill('0');
00112                                         dest.setf(std::ios_base::right, std::ios_base::adjustfield);
00113                                         OS_INT(Magic_Cookie_4B,cookiewidth);
00114                                         dest << '\n';
00115                                 }
00116 
00117                                 OS_INT(Node_Open,ctrlwidth);
00118                                 INSERT(nname,size2b);
00119                                 INSERT(impl,size2b);
00120                                 typedef typename node_traits::property_map_type PMT;
00121                 typedef typename PMT::const_iterator CIT;
00122                                 CIT it = node_traits::properties(src).begin();
00123                                 CIT et = node_traits::properties(src).end();
00124                                 std::string propval;
00125                                 std::string propname;
00126                                 for ( ; it != et; ++it )
00127                                 {
00128                                         OS_INT(Prop_Open,ctrlwidth);
00129                                         propname = ( *it ).first;
00130                                         INSERT(propname,size2b);
00131                                         propval = ( *it ).second;
00132                                         INSERT(propval,size4b);
00133                                         //OS_INT(Prop_Close);
00134                                 }
00135 
00136                 typedef typename node_traits::child_list_type CLT;
00137                 typedef typename CLT::const_iterator CLIT;
00138                 CLIT cit = node_traits::children(src).begin();
00139                 CLIT cet = node_traits::children(src).end();
00140                 for( ; cet != cit; ++cit )
00141                 {
00142                     this->serialize_impl( *(*cit), dest );
00143                 }
00144 
00145                                 OS_INT(Node_Close,ctrlwidth);
00146                                 dest << '\n';
00147                                 if( 0 == depth )
00148                                 {
00149                                         OS_INT(Data_End,cookiewidth);
00150                                         dest << std::endl;
00151                                         // maintenance: dest must be flush()ed or the client may be forced to do it.
00152                                 }
00153                                 --this->m_depth;
00154                                 return true;
00155                         }
00156 #undef OS_INT
00157 #undef INSERT
00158 
00159 
00160 
00161                 private:
00162                         size_t m_depth;
00163                 };
00164 
00165     } // namespace io
00166 } // namespace s11n
00167 
00168 #undef INDENT
00169 
00170 #endif // compact_SERIALIZER_H_INCLUDED

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