serializers.hpp

Go to the documentation of this file.
00001 #ifndef s11n_SERIALIZERS_HPP_INCLUDED
00002 #define s11n_SERIALIZERS_HPP_INCLUDED 1
00003 
00004 ////////////////////////////////////////////////////////////////////////////////
00005 // serializers.hpp: Some utility code for working with
00006 //  s11n::io Serializer types.
00007 //
00008 // License: Public Domain
00009 // Author: stephan@s11n.net
00010 ////////////////////////////////////////////////////////////////////////////////
00011 
00012 #include <s11n.net/s11n/classload.hpp> // factory fucntions
00013 #include <s11n.net/s11n/io/data_node_io.hpp> // data_node_serializer<> class.
00014 #include <s11n.net/s11n/s11n_config.hpp>
00015 
00016 namespace s11n {
00017         namespace io {
00018 
00019                 /**
00020            Intended mainly as a convenience for client
00021            applications, serializer_list() populates the
00022            target list with the names of registered
00023            Serializers.
00024 
00025            ListT must support push_back(std::string).
00026 
00027                    If onlyShortNames is true (the default) then only
00028                    "simple" names (only alphanumeric or underscore
00029                    characters) are put into target, not the "full"
00030                    names of the classes. This is to make the data more
00031                    useful in the context of client applications as,
00032                    e.g., a list of choices for users.
00033            
00034            When onlyShortNames is false then the list may contain
00035            some unsightly magic cookie strings.
00036 
00037            In either case, the list may very well contain
00038            different names for the same underlying Serializer,
00039            as most are registered with several aliases.
00040 
00041            Note that only serializers extending from
00042            s11n::io::data_node_serializer<NodeT> are returned.
00043 
00044            The exact values returned by this function may
00045            change in the future. e.g., at the moment it does
00046            not return the "real" classnames, only registered
00047            aliases, but this is arguable behaviour and may
00048            change.
00049                 */
00050                 template <typename NodeT, typename ListT>
00051                 void serializer_list( ListT & target, bool onlyShortNames = true )
00052                 {
00053             typedef ::s11n::io::data_node_serializer<NodeT> BaseSerT;
00054             /**
00055                Maintenance note: i don't encourage the
00056                direc use of s11n::fac here, but that is
00057                currently the only way to get the list of
00058                class names from the factory layer.
00059             */
00060                         typedef ::s11n::fac::factory_mgr< BaseSerT > SerCL;
00061             typedef typename SerCL::aliaser_type::alias_map_type AMap;
00062             SerCL & cl = ::s11n::fac::factory< BaseSerT >();
00063             typename AMap::const_iterator cit = cl.aliases().begin(),
00064                                  cet = cl.aliases().end();
00065                          std::string alias;
00066                          static const std::string nonspecial = 
00067                                  "_0123456789abcdefghijklmnopqrstuvwqxyzABCDEFGHIJKLMNOPQRSTUVWQXYZ";
00068                          for( ; cet != cit; ++cit )
00069                          {
00070                                  alias = (*cit).first;
00071                                  if( onlyShortNames )
00072                                  { // filter out all but "simple" names:
00073                                          if( std::string::npos !=
00074                                              alias.find_first_not_of( nonspecial )
00075                                              )
00076                                          {
00077                                                  continue;
00078                                          }
00079                                  }
00080                                  target.push_back( alias );
00081                          }
00082                 }
00083 
00084 
00085                 /**
00086                    Registers a Serializer type with the s11n::io layer. It must:
00087 
00088                    - be templatized on a DataNodeType
00089 
00090                    - subclass
00091                    s11n::io::data_node_serializer<DataNodeType>
00092 
00093                    - provide a node_type typedef which is the same as
00094                    DataNodeType
00095 
00096            - Be a complete type at the time this function is
00097            called.
00098 
00099                    i.e., the conventions of all of the Serializers
00100                    included with libs11n.
00101 
00102 
00103                    Registering makes the type available to the
00104                    data_node_serializer classloader.
00105 
00106                    Arguments:
00107 
00108                    - classname = SerializerT's stringified class name,
00109                    minus any template parts. e.g. my_serializer.
00110 
00111                    - alias = a "friendly" name for the SerializerT. By
00112                    convention this is the Serializer's class name
00113                    stripped of namespace and any trailing
00114                    "_serializer" part. The alias should, by
00115                    convention, be suitable to use via, e.g. entry as a
00116                    command-line argument.
00117 
00118                    SerializeT's magic_cookie() function is called to
00119                    alias the cookie as an alias for classname. Thus, a
00120                    SerializerT object is (briefly) instantiated.
00121 
00122                    Node that this function essentially performs the
00123                    same operations as the reg_serializer.hpp
00124                    supermacro, and the two should be equivalent
00125                    (though this seems easier to use).
00126                 */
00127                 template <typename SerializerT>
00128                 void register_serializer( const std::string & classname, const std::string & alias )
00129                 {
00130                         //CERR << "register_serializer(" << classname << ","<<alias<<")\n";
00131                         typedef SerializerT ST;
00132                         typedef typename ST::node_type NT;
00133                         typedef s11n::io::data_node_serializer<NT> BaseST;
00134                         ::s11n::cl::classloader_register_subtype< BaseST, ST >( classname );
00135                         ::s11n::cl::classloader_alias< BaseST >( alias, classname );
00136                         ::s11n::cl::classloader_alias< BaseST >( ST().magic_cookie(), classname );
00137             // ^^^ i don't LIKE having to instantiate ST here, but i don't see an
00138             // easy way around it.
00139                 }
00140 
00141                 /**
00142                    Returns a Serializer object, which must have been registered with
00143                    the s11n::cl/s11n::fac classloading API, using an interface type
00144            of s11n::io::data_node_serializer<NodeT>. e.g., register_serializer()
00145            will do the trick.
00146 
00147            If no serializer for classname is found and
00148            classname does not contain the string
00149            "_serializer", then then (classname+"_serializer")
00150            is tried. This is intended to ease DLL lookups for
00151            the conventional abbreviations for the Serializer
00152            classes (i.e., my_serializer).
00153 
00154                    The caller owns the returned pointer, which may be 0.
00155                 */
00156                 template <typename NodeT>
00157                 s11n::io::data_node_serializer<NodeT> *
00158                 create_serializer( const std::string & classname )
00159                 {
00160                         typedef s11n::io::data_node_serializer<NodeT> BaseSerT;
00161                         BaseSerT * s = 0;
00162             // todo: consider using try/catch and return 0, to allow for
00163             // more transparency when swapping out the core's factory layer.
00164             // Some factories may throw on load errors.
00165                         if( 0 != ( s = s11n::cl::classload< BaseSerT >( classname ) ) )
00166                         {
00167                                 return s;
00168                         }
00169                         static const char * addon = "_serializer";
00170                         if( (std::string::npos == classname.find(addon)) ) // try harder!
00171                         {
00172                                 std::string harder = classname + addon;
00173                                 // CERR << "Trying harder for " << classname << " --> " << harder << "!\n";
00174                                 s = create_serializer<NodeT>( harder );
00175                         }
00176                         return s;
00177                 }
00178 
00179         } // namespace io
00180 } // namespace s11n
00181 
00182 
00183 #endif // s11n_SERIALIZERS_HPP_INCLUDED

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