00001 #ifndef s11n_JS_SERIALIZER_HPP_INCLUDED
00002 #define s11n_JS_SERIALIZER_HPP_INCLUDED 1
00003
00004 #include <s11n.net/s11n/traits.hpp>
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #define MAGIC_COOKIE_JS "// s11n::io::js_serializer"
00019
00020 #include <stdexcept>
00021 #include <sstream>
00022 namespace s11n {
00023
00024 namespace io {
00025
00026 namespace sharing {
00027
00028
00029
00030 struct js_sharing_context {};
00031
00032 }
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 std::string quote_js_string( std::string const & s );
00044
00045
00046
00047
00048 template <typename NodeType>
00049 class js_serializer : public data_node_serializer<NodeType>
00050 {
00051 public:
00052 typedef NodeType node_type;
00053
00054 typedef js_serializer<node_type> this_type;
00055
00056 js_serializer() : m_depth(0)
00057 {
00058 this->magic_cookie( MAGIC_COOKIE_JS );
00059 }
00060
00061 virtual ~js_serializer() {}
00062
00063
00064
00065
00066 virtual bool serialize( const node_type & src, std::ostream & dest )
00067 {
00068 this->m_depth = 0;
00069 return this->serialize_impl( src, dest );
00070 }
00071
00072
00073
00074
00075
00076 virtual node_type * deserialize( std::istream & src )
00077 {
00078 throw ::s11n::s11n_exception( "js_serializer() does not support DEserialization." );
00079 return 0;
00080 }
00081
00082 private:
00083 size_t m_depth;
00084 bool serialize_impl( const node_type & src, std::ostream & dest )
00085 {
00086 typedef ::s11n::node_traits<node_type> NT;
00087
00088
00089 #define INDENT(LEVEL,ECHO) indent = ""; for( size_t i = 0; i < depth + LEVEL; i++ ) { indent += '\t'; if(ECHO) dest << '\t'; }
00090
00091 size_t depth = this->m_depth++;
00092 if ( 0 == depth )
00093 {
00094 dest << this->magic_cookie() << '\n';
00095 }
00096
00097
00098 std::string nname = NT::name(src);
00099 std::string impl = NT::class_name(src);
00100 std::string indent;
00101 dest << "(function() {\n";
00102 INDENT(1,0);
00103 dest << indent << "var self = new Object();\n";
00104 dest << indent << "self.$name = '" << nname << "';\n";
00105 dest << indent << "self.$class = '"<< impl <<"';\n";
00106 typedef typename NT::property_map_type PMT;
00107 typedef typename PMT::const_iterator CHIT;
00108 CHIT cit, cet;
00109 cit = NT::properties(src).begin();
00110 cet = NT::properties(src).end();
00111 std::string propval;
00112 std::string key;
00113
00114
00115 if( cet != cit )
00116 {
00117 dest << indent << "var p = self.$properties = new Array();\n";
00118
00119
00120
00121 for ( ; cet != cit; ++cit )
00122 {
00123 dest << indent << "p["<<quote_js_string((*cit).first) <<"] = "
00124 << quote_js_string( ( *cit ).second ) << ";\n";
00125 continue;
00126
00127
00128
00129
00130
00131
00132
00133 }
00134
00135
00136 }
00137
00138
00139 typedef typename NT::child_list_type CHLT;
00140 typename CHLT::const_iterator chit = NT::children(src).begin(),
00141 chet = NT::children(src).end();
00142 if( chet != chit )
00143 {
00144 INDENT(1,0);
00145 dest << indent << "self.$children = (function() {\n";
00146 node_type const * node = 0;
00147 INDENT(2,0);
00148 dest << indent << "var a = new Array();\n";
00149 size_t pos = 0;
00150 for( ; chet != chit; ++chit )
00151 {
00152 node = *chit;
00153
00154 dest << indent << "a["<<pos++<<"] = ";
00155 try
00156 {
00157 ++m_depth;
00158 this->serialize_impl( *node, dest );
00159 --m_depth;
00160 }
00161 catch(...)
00162 {
00163 --m_depth;
00164 throw;
00165 }
00166 }
00167 dest << indent << "return a;\n";
00168 INDENT(1,0);
00169 dest << indent << "})();\n";
00170 }
00171 INDENT(1,0);
00172 dest << indent << "return self;\n";
00173
00174
00175 INDENT(((0==depth) ? 0 : 1),0);
00176 dest << indent << "})();\n";
00177 if( 0 == depth )
00178 {
00179 dest << "\n";
00180 dest.flush();
00181
00182 }
00183 --this->m_depth;
00184 return true;
00185 #undef INDENT
00186 }
00187
00188 };
00189
00190 }
00191 }
00192
00193 #undef MAGIC_COOKIE_JS
00194 #endif // s11n_JS_SERIALIZER_HPP_INCLUDED