#ifndef s11n_net_s11n_v1_1_MAP_TPP_INCLUDED #define s11n_net_s11n_v1_1_MAP_TPP_INCLUDED // This file holds the implementations for template code declared // in mapish.hpp. #include // lexical casting #include // core serialize funcs #include // s11n_exception class #include // abstract_creator class template bool s11n::map::serialize_streamable_map( NodeType & dest, const MapType & src ) { typedef ::s11n::node_traits TR; typedef typename MapType::value_type VT; typedef typename VT::first_type FT; typedef typename VT::second_type ST; VT p; typename MapType::const_iterator it = src.begin(); ::s11n::Detail::variant v1, v2; for( ; src.end() != it; ++it ) { v1 = (*it).first; v2 = (*it).second; TR::set(dest, v1.str(), v2.str() ); } return true; } template bool s11n::map::serialize_streamable_map( NodeType & dest, const std::string & subnodename, const MapType & src ) { typedef ::s11n::node_traits TR; std::auto_ptr ch( TR::create( subnodename ) ); if( serialize_streamable_map( *ch, src ) ) { TR::children(dest).push_back( ch.release() ); } return 0 == ch.get(); } template bool s11n::map::deserialize_streamable_map( const NodeType & src, MapType & dest ) { typedef ::s11n::node_traits NTR; typedef typename MapType::value_type VT; // pair typedef typename VT::first_type T1; typedef typename VT::second_type T2; const T1 default1 = T1(); const T2 default2 = T2(); typedef typename NTR::property_map_type PMT; typedef typename PMT::const_iterator CIT; CIT it = NTR::properties(src).begin(); CIT et = NTR::properties(src).end(); ::s11n::Detail::variant v1, v2; for( ; et != it; ++it ) { v1 = (*it).first; v2 = (*it).second; dest.insert( std::make_pair( v1.template cast_to( default1 ), v2.template cast_to( default2 ) ) ); } return true; } template bool s11n::map::deserialize_streamable_map( const NodeType & src, const std::string & subnodename, MapType & dest ) { const NodeType * ch = ::s11n::find_child_by_name( src, subnodename ); if( ! ch ) return false; return deserialize_streamable_map( *ch, dest ); } template bool s11n::map::serialize_streamable_pair( NodeType & dest, const PairType & src ) { typedef s11n::node_traits TR; typedef ::s11n::s11n_traits STR; TR::class_name( dest, STR::class_name(&src) ); typedef typename PairType::first_type FT; typedef typename PairType::second_type ST; TR::set( dest, "first", src.first ); TR::set( dest, "second", src.second ); return true; } template PairType s11n::map::deserialize_streamable_pair( const NodeType & src ) { typedef ::s11n::node_traits TR; if( ! TR::is_set( src, "first" ) ) { throw ::s11n::s11n_exception( "deserialize_streamable_pair(): 'first' property not set!", __FILE__, __LINE__ ); } if( ! TR::is_set( src, "second" ) ) { throw ::s11n::s11n_exception( "deserialize_streamable_pair(): 'second' property not set!", __FILE__, __LINE__ ); } typedef typename PairType::first_type T1; typedef typename PairType::second_type T2; T1 default1 = T1(); T2 default2 = T2(); return std::make_pair( TR::get( src, "first", default1 ), TR::get( src, "second", default2 ) ); } template bool s11n::map::deserialize_streamable_pair( const NodeType & src, PairType & dest ) { typedef ::s11n::node_traits TR; typedef typename PairType::first_type FT; typedef typename PairType::second_type ST; if( ! TR::is_set( src, "first" ) ) { throw ::s11n::s11n_exception( "deserialize_streamable_pair(): 'first' property not set!", __FILE__, __LINE__ ); } if( ! TR::is_set( src, "second" ) ) { throw ::s11n::s11n_exception( "deserialize_streamable_pair(): 'second' property not set!", __FILE__, __LINE__ ); } dest.first = TR::get( src, "first", dest.first ); dest.second = TR::get( src, "second", dest.second ); return true; } template bool s11n::map::serialize_streamable_map_pairs( NodeType & dest, const MapType & src ) { typedef s11n::node_traits TR; typedef ::s11n::s11n_traits STR; TR::class_name( dest, STR::class_name(&src) ); typedef typename MapType::value_type VT; typedef typename VT::first_type FT; typedef typename VT::second_type ST; typename MapType::const_iterator it = src.begin(); for( ; src.end() != it; ++it ) { if( ! serialize_streamable_pair( create_child( dest, "pair" ), *it ) ) { return false; } } return true; } template bool s11n::map::deserialize_streamable_map_pairs( const NodeType & src, MapType & dest ) { typedef typename MapType::value_type VT; // pair typedef typename VT::first_type T1; typedef typename VT::second_type T2; typedef std::list ChList; typedef typename ChList::const_iterator ChIt; static const T1 default1 = T1(); static const T2 default2 = T2(); //::s11n::object_reference_wrapper dwrap(dest); // in case dest is a pointer type ChList namedch; if( 0 == ::s11n::find_children_by_name( src, "pair", namedch ) ) return true; // fine ChIt it = namedch.begin(); ChIt et = namedch.end(); if( et == it ) return true; typedef ::s11n::node_traits TR; const NodeType * ch = 0; VT p = VT(default1,default2); MapType buf; try { for( ; et != it; ++it ) { ch = *it; buf.insert( deserialize_streamable_pair( *ch ) ); } } catch(...) { using namespace ::s11n::debug; S11N_TRACE(TRACE_ERROR) << "deserialize_streamable_map_pairs(): srcnode="< bool s11n::map::serialize_pair( NodeType & dest, const PairType & src ) { typedef s11n::node_traits NT; typedef ::s11n::s11n_traits STR; typedef typename PairType::first_type FstT; typedef typename PairType::second_type SndT; NT::class_name( dest, STR::class_name(&src) ); std::auto_ptr ch( NT::create("first") ); // if( ! ::s11n::serialize( *ch, src.first ) ) // Compiler bug??? ^^^^ fully qualifying that causes a compile error, but doing the // same thing on .second below does not! if( ! serialize( *ch, src.first ) ) { return false; } std::auto_ptr ch2( NT::create("second") ); if( ! ::s11n::serialize( *ch2, src.second ) ) { return false; } NT::children(dest).push_back( ch.release() ); NT::children(dest).push_back( ch2.release() ); return true; } template bool s11n::map::deserialize_pair( const NodeType & src, PairType & dest ) { typedef ::s11n::node_traits NTR; typedef typename PairType::first_type FT; typedef typename PairType::second_type ST; typedef typename ::s11n::type_traits::type FT_base; typedef typename ::s11n::type_traits::type ST_base; const NodeType * ch = 0; //////////////////////////////////////////////// // The abstract_creator code below is simply // to treat pointer and value types // identically with this same code base. See // its docs for what it does (or doesn't do, // in the case of reference types). typedef s11n::Private::abstract_creator AC1st; typedef s11n::Private::abstract_creator AC2nd; using namespace ::s11n::debug; #define ERRMSG S11N_TRACE(TRACE_ERROR) << "deserialize_pair(node name="<( *ch, f ) ) { ::s11n::cleanup_serializable( f ); ERRMSG << "first deserialize(..., first ) failed.\n"; return false; } } catch(...) // deser threw { ERRMSG << "first deserialize() threw. Cleaning up, then propagating it...\n"; ::s11n::cleanup_serializable( f ); throw; } //////////////////////////////////////// .second: ch = ::s11n::find_child_by_name( src, "second" ); if( ! ch ) { ERRMSG << "no 'second' node found!\n"; ::s11n::cleanup_serializable( f ); return false; } implclass = NTR::class_name( *ch ); ST s; // value of .second try { if( ! AC2nd::create( s, implclass ) ) { ERRMSG << "Internal error: could not create .second element." <<"type='"<( f ); return false; } if( ! s11n::deserialize( *ch, s ) ) { ERRMSG << "deserialize(node, second) failed.\n"; ::s11n::cleanup_serializable( f ); ::s11n::cleanup_serializable( s ); return false; } } catch(...) { ERRMSG << "second deserialize() threw. Cleaning up, then propagating it...\n"; ::s11n::cleanup_serializable( f ); ::s11n::cleanup_serializable( s ); throw; } dest.first = f; dest.second = s; return true; #undef ERRMSG } template bool s11n::map::serialize_map( NodeType & dest, const MapType & src ) { typedef typename MapType::const_iterator CIT; typedef typename MapType::value_type PairType; typedef node_traits TR; typedef ::s11n::s11n_traits STR; if( ! TR::empty( dest ) ) { throw ::s11n::s11n_exception( "serialize_map(tgt_node=["+TR::name(dest)+"]) requires that the target node be empty.", __FILE__, __LINE__ ); } TR::class_name( dest, STR::class_name(&src) ); CIT b = src.begin(); CIT e = src.end(); for( ; e != b; ++b ) { std::auto_ptr ch( TR::create("pair") ); if( ! serialize_pair( *ch, *b ) ) { using namespace ::s11n::debug; S11N_TRACE(TRACE_ERROR) << "serialize_map: child pair failed serialize.\n"; return false; } dest.children().push_back( ch.release() ); // transfer ownership } return true; } template bool s11n::map::serialize_map( NodeType & dest, const std::string & subnodename, const MapType & src ) { typedef node_traits TR; std::auto_ptr ch( TR::create(subnodename) ); if( ! serialize_map( *ch, src ) ) { return false; } TR::children(dest).push_back( ch.release() ); return true; } template bool s11n::map::deserialize_map( const NodeType & src, MapType & dest ) { typedef node_traits TR; typedef typename NodeType::child_list_type::const_iterator CIT; //typedef typename SerializableType::value_type VT; // ^^^ no, because VT::first_type is const! // Thus we hand-create a compatible pair type: typedef typename MapType::key_type KType; typedef typename MapType::mapped_type VType; typedef std::pair< KType, VType > PairType; PairType pair; CIT b = TR::children(src).begin(); CIT e = TR::children(src).end(); if( e == b ) return true; const NodeType *ch = 0; using namespace ::s11n::debug; #define ERRMSG S11N_TRACE(TRACE_ERROR) << "deserialize_map(node,map) srcnode="<( *ch, pair ) ) { // ^^^ is this fails, pair is now guaranteed to be unmodified (1.1.3) ERRMSG << "map child failed deser: node name='"<( buffer ); return false; } buffer.insert( pair ); } } catch(...) { ERRMSG << "Passing on exception. Map cleaned using s11n_traits::cleanup_functor.\n"; ::s11n::cleanup_serializable( buffer ); throw; } #undef ERRMSG dest.swap( buffer ); return true; } template bool s11n::map::deserialize_map( const NodeType & src, const std::string & subnodename, MapType & dest ) { const NodeType * ch = ::s11n::find_child_by_name( src, subnodename ); if( ! ch ) return false; return deserialize_map( *ch, dest ); } #endif // s11n_net_s11n_v1_1_MAP_TPP_INCLUDED