data_node_format.hpp

Go to the documentation of this file.
00001 #ifndef s11n_DATA_NODE_FORMAT_H_INCLUDED
00002 #define s11n_DATA_NODE_FORMAT_H_INCLUDED
00003 ////////////////////////////////////////////////////////////////////////////////
00004 // data_node_format.hpp
00005 // Contains some helpers related to parsing/formating data_node-style objects.
00006 //
00007 // License: Public Domain
00008 // Author: stephan@s11n.net
00009 ////////////////////////////////////////////////////////////////////////////////
00010 
00011 
00012 #include <string>
00013 #include <list>
00014 #include <map>
00015 #include <stdexcept>
00016 
00017 #include <s11n.net/s11n/s11n_debuggering_macros.hpp> // COUT/CERR
00018 #include <s11n.net/s11n/phoenix.hpp>
00019 #include <s11n.net/s11n/io/strtool.hpp>
00020 #include <s11n.net/s11n/classload.hpp> // classload()
00021 
00022 #include <s11n.net/s11n/algo.hpp> // some utility functors
00023 #include <s11n.net/s11n/memory.hpp> // cleanup stuff
00024 #include <s11n.net/s11n/serialize.hpp> // data_node_serializer<> and friends
00025 
00026 #include <s11n.net/s11n/traits.hpp>
00027 #include <s11n.net/s11n/io/data_node_io.hpp> // default serializer interfaces
00028 
00029 ////////////////////////////////////////////////////////////////////////////////
00030 // NO DEPS ON data_node.hpp ALLOWED!
00031 ////////////////////////////////////////////////////////////////////////////////
00032 
00033 #include <s11n.net/s11n/io/FlexLexer.hpp>
00034 // cl_ABSTRACT_BASE(FlexLexer);
00035 
00036 
00037 namespace s11n {
00038         namespace io {
00039 
00040                 namespace Private {
00041                         /**
00042                            A helper to hide FlexLexer subclasses from needing to be
00043                            included in header files. (FlexLexer's subclassing technique
00044                            (via macros) makes them impracticle to mix together
00045                            in the same headers.)
00046 
00047                            May throw std::runtime_error.
00048                          */
00049                         int lex_api_hider_yylex( FlexLexer *, std::istream & );
00050 
00051                 }
00052 
00053                 /**
00054                    A typedef representing a map of tokens used for
00055                    "entity translations" by s11n parsers/serializers.
00056                 */
00057                 typedef std::map<std::string,std::string> entity_translation_map;
00058 
00059 
00060                 /**
00061                    tree_builder exists mainly so some lex-based code
00062                    can get access to a non-templated type (so we don't
00063                    have to hard-code the parsers to a node_type).
00064 
00065                    It provides only the interface needed by the current
00066                    lex-based parsers, not some ultimately reusable
00067                    interface.
00068 
00069                    It is not functionally useful by itself - it must
00070                    be subclassed and all of it's virtual methods must be
00071                    implemented.
00072                 */
00073                 class tree_builder
00074                 {
00075                 public:
00076                         tree_builder() : m_autodel(true) {}
00077 
00078                         virtual ~tree_builder() {}
00079 
00080                         /**
00081                            Starts a new node with the the given class
00082                            name and node name.
00083 
00084                            Return value indicates success or failure.
00085                         */
00086                         virtual bool
00087                         open_node( const std::string & classname, const std::string & nodename ) = 0;
00088 
00089                         /**
00090                            Closes the current node.
00091 
00092                            Return value indicates success or failure.
00093                         */
00094                         virtual bool
00095                         close_node() = 0;
00096 
00097                         /**
00098                            Sets property key to val for the current node.
00099 
00100                            Return value indicates success or failure.
00101                         */
00102                         virtual bool
00103                         add_property( const std::string & key, const std::string & val ) = 0;
00104 
00105                         /**
00106                            Returns the depth level of the parser,
00107                            where the root node is 1.
00108                         */
00109                         virtual size_t node_depth() const = 0;
00110 
00111 
00112                         /**
00113                            Changes the implementation class name of
00114                            the current node.
00115                         */
00116                         virtual bool change_node_class( const std::string & newclassname ) = 0;
00117 
00118                         /**
00119                            If auto_delete() is on (the default) then
00120                            this object should delete it's children
00121                            when it is destroyed, otherwise it will
00122                            not. It is up to subclasses to honor this,
00123                            as this base type does no handling of
00124                            children.
00125                         */
00126                         void auto_delete( bool b )
00127                         {
00128                                 this->m_autodel = b;
00129                         }
00130 
00131                         /**
00132                            This is the getter for auto_delete( bool ).
00133                         */
00134                         bool auto_delete() const
00135                         {
00136                                 return this->m_autodel;
00137                         }
00138 
00139             /**
00140                Should reset the state of this object to
00141                it's default. How it sets the auto_delete()
00142                flag is implementation-dependent. The default
00143                implementation does nothing, as this type has
00144                no state other than the auto_delete() flag.
00145             */
00146             virtual void reset()
00147             {
00148             }
00149 
00150                 private:
00151                         bool m_autodel;
00152 
00153                 };
00154 
00155 
00156 
00157                 /**
00158                    tree_builder_context is a helper for accessing some
00159                    template-dependent code from non-template-aware
00160                    lexer code. It's usage is admitedly a bit strange
00161                    (indeed, it's whole existance is).
00162 
00163                    This object sets up a "context channel" where
00164                    a given FlexLexer can, in a thread-safe manner,
00165                    communicate data back to a data_node_tree_builder<NodeType>
00166                    without knowing the exact NodeType.
00167 
00168                    For samples see the s11n lexers, under src/serializers/XXX/XXX_serializer.flex.
00169 
00170                    All of it's methods, except for builder(), mirror
00171                    those of a tree_builder object, so see that class
00172                    for the API docs. For the "mirrored" functions, the
00173                    object being proxied is that set via builder(). It
00174                    is intended that only the lexers associated with
00175                    this context actually use it's API.
00176 
00177                    Calling the proxied functions when no builder is
00178                    set has no effect. Calling them with no bind()ed 
00179                    FlexLexer may be fatal.
00180 
00181                 */
00182                 template <typename ContextT>
00183                 class tree_builder_context
00184                 {
00185                 public:
00186                         /** The context type for this class. */
00187                         typedef ContextT context_type;
00188                         /**
00189                            Sets the current builder object for this context.
00190 
00191                            Pointer ownership does not change by
00192                            calling this function.
00193 
00194                            This must be carefully marshalled: it must
00195                            always be set immediately before the
00196                            matching lexer is used, and unbind(lexer)
00197                            should be called immediately afterwards to
00198                            free up the internal marshaling data. Failing
00199                            to call unbind will mean a resource leak
00200                            (albeit a small one).
00201 
00202                            Preconditions:
00203 
00204                            - lexer and builder must be valid pointers
00205                            and must out-live the expected lifetime of
00206                            this context object, which internally
00207                            associates these two objects.
00208                         */
00209                         static void bind( const FlexLexer * lexer, tree_builder * builder )
00210                         {
00211                                 lmap()[lexer].builder = builder;
00212                         }
00213 
00214                         /**
00215                            Frees up the internal resources used by the
00216                            marshaling process for the given lexer.
00217                         */
00218                         static void unbind( const FlexLexer * lexer )
00219                         {
00220                                 lmap().erase( lexer );
00221                         }
00222 
00223                         /**
00224                            Gets the current builder object for this
00225                            context, which must have been previously
00226                            set up via a call to bind(lexer,builder).
00227 
00228                            Ownership of the returned pointer does not
00229                            change by calling this function.
00230                         */
00231                         static tree_builder * builder( const FlexLexer * lexer )
00232                         {
00233                                 return lmap()[lexer].builder;
00234                         }
00235 
00236 
00237 #define IFNOLEXER(RET) if( lmap().end() == lmap().find(lexer) ) return RET;
00238                         /**
00239                            See tree_builder::open_node().
00240                         */
00241                         static bool open_node( const FlexLexer * lexer,
00242                                                const std::string & classname,
00243                                                const std::string & nodename )
00244                         {
00245                                 IFNOLEXER(false);
00246                                 return lmap()[lexer].builder->open_node( classname, nodename );
00247                         }
00248 
00249                         /**
00250                            See tree_builder::clode_node().
00251                         */
00252                         static bool close_node( const FlexLexer * lexer )
00253                         {
00254                                 IFNOLEXER(false);
00255                                 return lmap()[lexer].builder->close_node();
00256                         }
00257 
00258                         /**
00259                            See tree_builder::add_property().
00260                         */
00261                         static bool
00262                         add_property(  const FlexLexer * lexer,
00263                                        const std::string & key,
00264                                        const std::string & val )
00265                         {
00266                                 IFNOLEXER(false);
00267                                 return lmap()[lexer].builder->add_property( key, val );
00268                         }
00269 
00270                         /**
00271                            See tree_builder::node_depth().
00272                         */
00273                         static size_t node_depth(  const FlexLexer * lexer )
00274                         {
00275                                 IFNOLEXER(0);
00276                                 return lmap()[lexer].builder->node_depth();
00277                         }
00278 
00279                         /**
00280                            See tree_builder::change_node_class().
00281                         */
00282                         static bool change_node_class(  const FlexLexer * lexer,
00283                                                         const std::string & newclassname )
00284                         {
00285                                 IFNOLEXER(false);
00286                                 return lmap()[lexer].builder->change_node_class( newclassname );
00287                         }
00288 #undef IFNOLEXER
00289 
00290                         /**
00291                            This is intended for direct access by a lexer associated
00292                            with this context, and ONLY by such lexers.
00293 
00294                            Except for the builder member, these are
00295                            temporary holding points for vars common to
00296                            most lexers, placed here to avoid using
00297                            global data in the lexer code.
00298                         */
00299                         struct lexer_metadata
00300                         {
00301                                 tree_builder * builder;
00302 
00303                                 size_t internaldepth; // current internal depth (not always the same as node_depth())
00304                                 std::string nodename; // name of current node
00305                                 std::string nodeclass; // class name of current node
00306                                 std::string property; // property value buffer
00307                                 std::string bufferyy; // lexer-dependent
00308                                 lexer_metadata()
00309                                 {
00310                                         builder = 0;
00311                                         internaldepth = 0;
00312                                         nodename = nodeclass = property = bufferyy = "";
00313                                 }
00314                         };
00315 
00316                         /**
00317                            Returns the lexer_metadata for the given lexer, creating one
00318                            if needed. It is assumed that the lexer has been bound via a
00319                            call to bind().
00320                         */
00321                         static lexer_metadata & metadata( const FlexLexer * lexer )
00322                         {
00323                                 return lmap()[lexer];
00324                         }
00325 
00326                 private:
00327                         /** Convenience typedef. */
00328                         typedef tree_builder_context<context_type> this_type;
00329                         /** lexer-to-metadata map */
00330                         typedef std::map<const FlexLexer *,lexer_metadata> lexer_map;
00331                         static lexer_map & lmap()
00332                         {
00333                                 return ::s11n::Detail::phoenix<
00334                                         lexer_map,
00335                                         this_type
00336                                         >::instance();
00337                         }
00338 
00339                 };
00340 
00341                 /**
00342                    data_node_tree_builder is a helper class for
00343                    building trees from deserialized data, designed
00344                    particularly for use with lex/callback-based tree
00345                    builders.
00346 
00347                    It owns all objects which build up it's tree. If
00348                    you want them you must manually remove them from the
00349                    container. You normally do not want them, however - they're
00350                    mostly throwaway nodes on their way to becoming fully
00351                    deserialized objects.
00352 
00353                    This class only provides methods for building a tree, not
00354                    for traversing it. Once you have built a tree, traverse it
00355                    starting at the root_node().
00356 
00357                    Based on usage conventions this type supports only
00358                    a single root node.
00359                 */
00360                 template <typename NodeType>
00361                 class data_node_tree_builder : public tree_builder
00362                 {
00363                 public:
00364                         typedef NodeType node_type;
00365 
00366                         typedef std::list< node_type * > child_list_type;
00367 
00368                         /** Creates a default builder. */
00369                         data_node_tree_builder() : m_node_count(0), m_node(0),m_root(0)
00370                         {
00371                         }
00372 
00373                         /**
00374                            Deletes this object's children if
00375                            auto_delete() returns true.
00376                         */
00377                         virtual ~data_node_tree_builder()
00378                         {
00379                                 if( this->auto_delete() && this->m_root )
00380                                 {
00381                                         //CERR << "data_node_tree_builder<> cleaning up root node.\n";
00382                                         delete( this->m_root );
00383                                 }
00384                                 else
00385                                 {
00386                                         //CERR << "data_node_tree_builder<> was relieved of child duty (or had no child).\n";
00387                                 }
00388                         }
00389 
00390 
00391                         /**
00392                            Opens a new node, making that the current node.
00393                            classname will be used for the node's impl_class()
00394                            (see docs for node_type::impl_class()). name will
00395                            be the object's name, which is important for
00396                            de/serializing the node (see node_type::name()).
00397 
00398                            It returns false on error, else true. The default
00399                            implementation has no error conditions, and
00400                            therefor always returns true.
00401 
00402                            Node that classnames and node names need not be
00403                            unique (nor make up unique combinations). Any
00404                            number of nodes may have the same name or
00405                            classname.
00406                         */
00407                         bool open_node( const std::string & classname, const std::string & nodename )
00408                         {
00409                                 ++m_node_count;
00410 
00411                                 this->m_node = ( this->m_nodestack.empty() 
00412                                                  ? 0
00413                                                  : this->m_nodestack.back() );
00414                                 typedef ::s11n::node_traits<node_type> NTR;
00415                                 node_type * newnode = new node_type();
00416                                 if ( m_node )
00417                                 { // if we're in a node, add new node as a child to that one:
00418                                         NTR::children( *m_node ).push_back( newnode );
00419                                 }
00420                                 this->m_node = newnode;
00421                                 NTR::name( *m_node, nodename );
00422                                 NTR::class_name( *m_node, classname );
00423                                 this->m_nodestack.push_back( m_node );
00424                                 bool ret = true;
00425                                 if ( 1 == this->m_nodestack.size() )
00426                                 {
00427                                         if( m_root )
00428                                         {
00429                                                 CERR << "open_node("<<classname<<","<<nodename<<") WARNING: deleting extra root node!\n";
00430                                                 delete( m_node );
00431                         m_node = 0;
00432                                                 ret = false;
00433                                         }
00434                                         else
00435                                         {
00436                                                 m_root = m_node;
00437                                         }
00438                                 }
00439                                 return ret;
00440                         }
00441 
00442                         /**
00443                            Closes the most-recently-opened node, effectively
00444                            popping the previous node off of the node stack (it
00445                            is not destroyed).  It is an error to call this more
00446                            often than calling open_node().
00447 
00448                            It returns false on error (e.g., called
00449                            with no opened node).
00450                         */
00451                         virtual bool close_node()
00452                         {
00453                                 if ( !m_node || m_nodestack.empty() )
00454                                 {
00455                                         CERR << "close_node() error: called with an empty node stack!" << std::endl;
00456                                         return false;
00457                                 }
00458                                 m_nodestack.pop_back();
00459                                 if ( m_nodestack.empty() )
00460                                 {
00461                                         m_node = NULL;
00462                                 }
00463                                 else
00464                                 {
00465                                         m_node = m_nodestack.back();
00466                                 }
00467                                 return true;
00468                         }
00469 
00470 
00471                         /**
00472                            Adds the given key/value pair to the
00473                            current node and returns true. If no node
00474                            is currently opened it returns false.
00475                         */
00476                         virtual bool add_property( const std::string & key, const std::string & val )
00477                         {
00478                                 if( ! this->m_node ) return false;
00479                                 typedef ::s11n::node_traits<node_type> NTR;
00480                                 NTR::set( *m_node, key, val );
00481                                 return true;
00482                         }
00483 
00484                         /**
00485                            Returns the total number of nodes opened via open_node().
00486                         */
00487                         size_t node_count() const
00488                         {
00489                                 return m_node_count;
00490                         }
00491 
00492 
00493                         /**
00494                            Returns the current depth of opened nodes. A return
00495                            value of 1 means the current node is the root node,
00496                            for example, and 0 means that no node has yet been
00497                            opened.
00498                         */
00499                         size_t node_depth() const
00500                         {
00501                                 return m_nodestack.size();
00502                         }
00503 
00504 
00505                         /**
00506                            Returns the most recent root node parsed out of the
00507                            input object.
00508 
00509                            Use auto_delete() to determine ownership of
00510                            the returned pointer.
00511                         */
00512                         node_type * root_node() const
00513                         {
00514                                 return m_root;
00515                         }
00516 
00517 
00518                         /**
00519                            Returns the current node.
00520 
00521                            Use auto_delete() to determine ownership of
00522                            the returned pointer.
00523                         */
00524                         node_type * current_node() const
00525                         {
00526                                 return m_node;
00527                         }
00528 
00529                         /**
00530                            Changes class name of current node, if one
00531                            is set. Returns false only if no node is
00532                            currently opened, else it returns true.
00533                         */
00534                         virtual bool change_node_class( const std::string & newclassname )
00535                         {
00536                                 if( ! this->m_node ) return false;
00537                                 typedef ::s11n::node_traits<node_type> NTR;
00538                                 NTR::class_name( *(this->m_node), newclassname );
00539                                 return true;
00540                         }
00541 
00542                         /**
00543                            Deletes this object's root_node() if auto_delete() is true. Cleans
00544                up all internal data structures so that this object has an empty
00545                state.
00546                         */
00547                         virtual void reset()
00548                         {
00549                                 if( this->auto_delete() && this->m_root ) delete this->m_root;
00550                                 this->m_root = 0;
00551                 // todo: back-port the following three lines to 1.0.x:
00552                 this->m_node = 0;
00553                 this->m_node_count = 0;
00554                 this->m_nodestack = node_stack();
00555                         }
00556 
00557                 private:
00558                         size_t m_node_count;
00559                         node_type * m_node;
00560                         node_type * m_root;
00561                         typedef std::deque < node_type * > node_stack;
00562                         node_stack m_nodestack;                        
00563                 };
00564 
00565 
00566 
00567                 /**
00568                    This function exists for a really long, strange
00569                    reason involving accessing templatized types from
00570                    template-free code (FlexLexers).
00571 
00572                    - lexerClassName is the name of a FlexLexer
00573                    subclass. It must be registered with the FlexLexer
00574                    classloader.
00575 
00576                    - src is the stream to pass on to the lexer.
00577 
00578                    - BuilderContext should be the same one expected by
00579                    the specific lexer. See the existing lexers for
00580                    examples. You want to pass the actual
00581                    BuilderContext's context here, not a
00582                    tree_builder_context<> type.
00583 
00584                    The caller owns the returned poiner, which may be 0.
00585 
00586            As of s11n version 1.1.3, this function may throw
00587            on error, and is guaranteed to propagate any
00588            exceptions it catches (after cleaning up). Except
00589            when passing on a (...) exception, all thrown
00590            exceptions are guaranteed to be std::exception
00591            types.
00592                 */
00593                 template <typename NodeType, typename BuilderContext>
00594                 NodeType * deserialize_lex_forwarder( const std::string & lexerClassName,
00595                                                       std::istream & src
00596                                                       )
00597                 {
00598                         // CERR << "deserialize_lex_forwarder("<<lexerClassName<<")\n";
00599             s11n::Detail::auto_ptr<FlexLexer> lexer( ::s11n::cl::classload<FlexLexer>( lexerClassName ) );
00600                         if( ! lexer.get() )
00601                         {
00602                 throw ::s11n::s11n_exception(
00603                                  "%s:%d: s11n::io::deserialize_lex_forwarder(): Lexer '%s' was not found by classload<FlexLexer>(). It is probably not registered with the classloader.",
00604                                  __FILE__,
00605                                  __LINE__,
00606                                  lexerClassName.c_str() );
00607                         }
00608 
00609                         typedef s11n::io::data_node_tree_builder<NodeType> BuilderType;
00610                         typedef tree_builder_context<BuilderContext> BC;
00611                         s11n::Detail::auto_ptr<BuilderType> treebuilder( new BuilderType );
00612                         treebuilder->auto_delete( true ); // if we throw, let it clean up
00613                         try
00614                         {
00615                                 BC::bind( lexer.get(), treebuilder.get() );
00616                                 // ^^^ sets up the comm channel between the builder and lexer
00617                                 Private::lex_api_hider_yylex(lexer.get(),src); // executes the lexer
00618                         }
00619                         catch ( const std::exception & ex )
00620                         {
00621                 BC::unbind( lexer.get() ); // free up lexer-to-builder binding
00622                 throw ex;
00623                         }
00624                         catch (...)
00625                         {
00626                 BC::unbind( lexer.get() ); // free up lexer-to-builder binding
00627                                 throw;
00628                         }
00629                         BC::unbind( lexer.get() ); // free up lexer-to-builder binding
00630             treebuilder->auto_delete( false ); // we're taking ownership of the children
00631             return treebuilder->root_node();
00632                 }
00633 
00634                 /**
00635                    tree_builder_lexer is a type intended to ease the
00636                    implementation of lex-based node tree parsers.
00637 
00638                    It is useless standalone: it must be subclassed.
00639 
00640                    It holds the class name of a FlexLexer type so it
00641                    can be dynamically loaded as needed. It takes the
00642                    responsibility of instantiating that type and
00643                    passing off input to subclasses.
00644                 */
00645                 template <typename NodeType, typename LexerSharingContext>
00646                 class tree_builder_lexer : public data_node_serializer<NodeType>
00647                 {
00648                 public:
00649 
00650                         typedef NodeType node_type;
00651                         typedef LexerSharingContext sharing_context;
00652                         typedef data_node_serializer<NodeType> parent_type; // convenience typedef.
00653 
00654                         /**
00655                            lexerClassName = the class name of the FlexLexer subtype
00656                            associated with this serializer.
00657                         */
00658                         explicit tree_builder_lexer( const std::string & lexerClassName )
00659                                 : m_impl(lexerClassName)
00660                         {}
00661 
00662                         virtual ~tree_builder_lexer(){}
00663 
00664                         /**
00665                            Overridden to parse src using this object's lexer.
00666                            It uses <code>deserialize_lex_forwarder<sharing_context>()</code>,
00667                            passing it this object's lexer_class().
00668                         */
00669                         virtual node_type * deserialize( std::istream & src )
00670                         {
00671                                 return deserialize_lex_forwarder<
00672                                         node_type,
00673                                         sharing_context
00674                                         >( this->lexer_class(), src );
00675                         }
00676 
00677                         virtual node_type * deserialize( const std::string & src )
00678                         { // Forwarding this avoids an odd compiler error sometimes,
00679                           // where the compiler doesn't see that this function
00680                           // exists which called from client code. ???
00681                                 return this->parent_type::deserialize( src );
00682                         }
00683 
00684 
00685                         /**
00686                            Returns this object's lexer class name.
00687                         */
00688                         std::string lexer_class() const { return this->m_impl; }
00689 
00690 
00691                 protected:
00692                         /**
00693                            Sets this object's lexer class name.
00694                         */
00695                         void lexer_class( const std::string & classname )
00696                         {
00697                                 this->m_impl = classname;
00698                         }
00699 
00700                 private:
00701                         std::string m_impl; // implementation class name for a FlexLexer subclass
00702                 };
00703 
00704 
00705 
00706 
00707                 /**
00708                    A helper for serializing properties to a
00709                    stream. Intended for use by Serializers, not
00710                    Serializables.
00711 
00712                    NodeType is the container type used for data
00713                    serialization (e.g. s11n::data_node).
00714 
00715                 */
00716                 template <typename NodeType>
00717                 class key_value_serializer
00718                 {
00719                 public:
00720                         typedef NodeType node_type;
00721                         typedef typename node_type::value_type pair_type;
00722 
00723                         typedef std::map<std::string,std::string> entity_translation_map;
00724 
00725                         /**
00726                            map: needed so we can do entity translation
00727                            in a unified manner here. It must outlive
00728                            this object. Pass it 0 for no translation.
00729                            Translations are only applied on VALUES,
00730                            not KEYS.
00731 
00732                            prefix: inserted before each property.
00733 
00734                            separator: inserted between the key and value.
00735 
00736                            suffix: appended after each entry.
00737 
00738 
00739                         */
00740                         key_value_serializer( const entity_translation_map * map,
00741                                               std::ostream & dest,
00742                                               const std::string & prefix,
00743                                               const std::string & separator,
00744                                               const std::string & suffix
00745                                               )
00746                                 : m_pre(prefix), m_sep(separator), m_suf(suffix), m_os(dest), m_map(map)
00747                         {
00748                         }
00749 
00750                         /**
00751                            Sends the following formatted string to os:
00752 
00753                            {prefix}{src.first}{separator}{src.second}{suffix}
00754 
00755                         */
00756                         void operator()( const pair_type & src ) const
00757                         {
00758                                 static const std::string errval = "";
00759                                 std::string key = strtool::to( src.first );
00760                                 std::string val = strtool::to( src.second );
00761                                 // should we xlate the key as well?
00762                                 if( this->m_map )
00763                                 {
00764                                        strtool::translate_entities( val, *(this->m_map) );
00765                                 }
00766                                 this->m_os << this->m_pre;
00767                                 this->m_os << key;
00768                                 this->m_os << this->m_sep;
00769                                 this->m_os << val;
00770                                 this->m_os << this->m_suf;
00771                         }
00772                 private:
00773                         std::string m_pre;
00774                         std::string m_sep;
00775                         std::string m_suf;
00776                         std::ostream & m_os;
00777                         const entity_translation_map * m_map;
00778                 };
00779 
00780 
00781 
00782 
00783 
00784                 /**
00785                    A helper functor to loop over serializable children
00786                    of a node from within a Serializer implementation.
00787 
00788                    Designed for use with std::for_each().
00789 
00790                    SerializerT must be compatible with
00791                    <code>data_node_serializer<></code>.
00792 
00793                 */
00794                 template <typename SerializerT>
00795                 struct node_child_simple_formatter
00796                 {
00797                         typedef SerializerT serializer_type;
00798 //                         typedef typename SerializerT::node_type node_type;
00799                         /**
00800                            Preconditions:
00801 
00802                            - Ser must be valid references.
00803 
00804                            - Both ser and os must outlive this
00805                            object. More correctly, this object's
00806                            operator() must not be called after either
00807                            ser or os are destroyed.
00808 
00809                         */
00810                         node_child_simple_formatter( serializer_type & ser, std::ostream & os,
00811                                                const std::string & prefix = "", const std::string & suffix = "\n" )
00812                                 : m_ser(ser), m_os(&os), m_pre(prefix), m_suf(suffix)
00813                         {
00814                         }
00815 
00816                         /**
00817                            Serializes src into this object's target
00818                            container, using this object's serializer.
00819                         */
00820                         template <typename NodeType>
00821                         bool operator()( const NodeType * src ) const
00822                         {
00823                                 if( ! src ) return false;
00824                                 if( ! this->m_pre.empty() ) *(this->m_os) << this->m_pre;
00825                                 bool b = this->m_ser.serialize( *src, *(this->m_os) );
00826                                 if( ! this->m_suf.empty() ) *(this->m_os) << this->m_suf;
00827                                 return b;
00828                         }
00829 
00830                 private:
00831                         serializer_type & m_ser;
00832                         std::ostream * m_os;
00833                         std::string m_pre;
00834                         std::string m_suf;
00835                 };
00836 
00837 
00838 
00839         } // namespace io
00840 } // namespace s11n
00841 
00842 // cl_CLASSLOADER_ABSTRACT_BASE(s11n::io::tree_builder);
00843 #include <s11n.net/s11n/factory.hpp>
00844 #define S11N_FACREG_TYPE s11n::io::tree_builder
00845 #define S11N_FACREG_TYPE_NAME "s11n::io::tree_builder"
00846 #define S11N_FACREG_TYPE_IS_ABSTRACT 1
00847 #include <s11n.net/s11n/factory_reg.hpp>
00848 
00849 #endif // s11n_DATA_NODE_FORMAT_H_INCLUDED

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