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                 template <typename NodeT, typename ListT>
00045                 void serializer_list( ListT & target, bool onlyShortNames = true )
00046                 {
00047             typedef ::s11n::io::data_node_serializer<NodeT> BaseSerT;
00048             /**
00049                Maintenance note: i don't encourage the
00050                direc use of s11n::fac here, but that is
00051                currently the only way to get the list of
00052                class names from the factory layer.
00053             */
00054                         typedef ::s11n::fac::factory_mgr< BaseSerT > SerCL;
00055             typedef typename SerCL::aliaser_type::alias_map_type AMap;
00056             SerCL const & cl = ::s11n::fac::factory< BaseSerT >();
00057             typename AMap::const_iterator cit = cl.aliases().begin(),
00058                                  cet = cl.aliases().end();
00059                          std::string alias;
00060                          static const std::string nonspecial = 
00061                                  "_0123456789abcdefghijklmnopqrstuvwqxyzABCDEFGHIJKLMNOPQRSTUVWQXYZ";
00062                          for( ; cet != cit; ++cit )
00063                          {
00064                                  alias = (*cit).first;
00065                                  if( onlyShortNames )
00066                                  { // filter out all but "simple" names:
00067                                          if( std::string::npos !=
00068                                              alias.find_first_not_of( nonspecial )
00069                                              )
00070                                          {
00071                                                  continue;
00072                                          }
00073                                  }
00074                                  target.push_back( alias );
00075                          }
00076                 }
00077 
00078 
00079                 /**
00080                    Registers a Serializer type with the s11n::io layer. It must:
00081 
00082                    - be templatized on a DataNodeType
00083 
00084                    - subclass
00085                    s11n::io::data_node_serializer<DataNodeType>
00086 
00087                    - provide a node_type typedef which is the same as
00088                    DataNodeType
00089 
00090            - Be a complete type at the time this function is
00091            called.
00092 
00093                    i.e., the conventions of all of the Serializers
00094                    included with libs11n.
00095 
00096 
00097                    Registering makes the type available to the
00098                    data_node_serializer classloader.
00099 
00100                    Arguments:
00101 
00102                    - classname = SerializerT's stringified class name,
00103                    minus any template parts. e.g. my_serializer.
00104 
00105                    - alias = a "friendly" name for the SerializerT. By
00106                    convention this is the Serializer's class name
00107                    stripped of namespace and any trailing
00108                    "_serializer" part. The alias should, by
00109                    convention, be suitable to use via, e.g. entry as a
00110                    command-line argument.
00111 
00112                    SerializeT's magic_cookie() function is called to
00113                    alias the cookie as an alias for classname. Thus, a
00114                    SerializerT object is (briefly) instantiated.
00115 
00116                    Node that this function essentially performs the
00117                    same operations as the reg_serializer.hpp
00118                    supermacro, and the two should be equivalent
00119                    (though this seems easier to use).
00120                 */
00121                 template <typename SerializerT>
00122                 void register_serializer( const std::string & classname, const std::string & alias )
00123                 {
00124                         //CERR << "register_serializer(" << classname << ","<<alias<<")\n";
00125                         typedef SerializerT ST;
00126                         typedef typename ST::node_type NT;
00127                         typedef s11n::io::data_node_serializer<NT> BaseST;
00128                         ::s11n::cl::classloader_register_subtype< BaseST, ST >( classname );
00129                         ::s11n::cl::classloader_alias< BaseST >( alias, classname );
00130                         ::s11n::cl::classloader_alias< BaseST >( ST().magic_cookie(), classname );
00131             // ^^^ i don't LIKE having to instantiate ST here, but i don't see an
00132             // easy way around it.
00133                 }
00134 
00135                 /**
00136                    Returns a Serializer object, which must have been registered with
00137                    the s11n::cl/s11n::fac classloading API, using an interface type
00138            of s11n::io::data_node_serializer<NodeT>. e.g., register_serializer()
00139            will do the trick.
00140 
00141            If no serializer for classname is found and
00142            classname does not contain the string
00143            "_serializer", then then (classname+"_serializer")
00144            is tried. This is intended to ease DLL lookups for
00145            the conventional abbreviations for the Serializer
00146            classes (i.e., my_serializer).
00147 
00148                    The caller owns the returned pointer, which may be 0.
00149                 */
00150                 template <typename NodeT>
00151                 s11n::io::data_node_serializer<NodeT> *
00152                 create_serializer( const std::string & classname )
00153                 {
00154                         typedef s11n::io::data_node_serializer<NodeT> BaseSerT;
00155                         BaseSerT * s = 0;
00156             // todo: consider using try/catch and return 0, to allow for
00157             // more transparency when swapping out the core's factory layer.
00158             // Some factories may throw on load errors.
00159                         if( 0 != ( s = s11n::cl::classload< BaseSerT >( classname ) ) )
00160                         {
00161                                 return s;
00162                         }
00163                         static const char * addon = "_serializer";
00164                         if( (std::string::npos == classname.find(addon)) ) // try harder!
00165                         {
00166                                 std::string harder = classname + addon;
00167                                 // CERR << "Trying harder for " << classname << " --> " << harder << "!\n";
00168                                 s = create_serializer<NodeT>( harder );
00169                         }
00170                         return s;
00171                 }
00172 
00173         } // namespace io
00174 } // namespace s11n
00175 
00176 
00177 #endif // s11n_SERIALIZERS_HPP_INCLUDED

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