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

Generated on Sat Mar 20 12:29:24 2010 for libs11n-1.2.10 by  doxygen 1.6.1