00001 #ifndef s11n_ABSTRACT_CREATOR_H_INCLUDED 00002 #define s11n_ABSTRACT_CREATOR_H_INCLUDED 1 00003 00004 //////////////////////////////////////////////////////////////////////// 00005 // abstract_creatore.hpp: 00006 // Defines a difficult-to-describe class. See the docs. 00007 // 00008 // Author: stephan beal <stephan@s11n.net> 00009 // License: Public Domain 00010 //////////////////////////////////////////////////////////////////////// 00011 00012 #include <string> 00013 #include "classload.hpp" // classloader-related funcs 00014 #include <s11n.net/s11n/traits.hpp> // s11n_traits 00015 00016 namespace s11n { namespace Private { 00017 00018 00019 /** 00020 abstract_creator is an internal helper to avoid some code 00021 having to know if a type is created on a stack or the 00022 heap. This makes some template code easier to write, as it 00023 avoids syntax errors when trying something like: 00024 00025 <pre> 00026 if( object type is a pointer type ) delete(object); 00027 else { ... } 00028 </pre> 00029 00030 This implementation creates items the stack via the default 00031 ctor. If instantiated with (T *) a pointer/heap-based 00032 specialization is activated instead. 00033 00034 Designed for use with, e.g., ListType<T>, for which T 00035 may be either T or (T *). 00036 00037 These objects contain no state information. 00038 00039 The member function release() was removed in s11n 1.1.3, 00040 as it was potentially dangerous. s11n_traits::cleanup_functor 00041 replaces that functionality and does so correctly. 00042 */ 00043 template <typename T> 00044 struct abstract_creator 00045 { 00046 /** Same as (T). */ 00047 typedef T value_type; 00048 00049 /** Same as (T). */ 00050 typedef T base_value_type; 00051 00052 /** 00053 This implementation assigns v to value_type() and 00054 returns true. 00055 00056 The string argument is bogus for this implementation, 00057 and is used by the pointer specialization to implement 00058 polymorphic classloading of value_type. 00059 00060 Historical note: before s11n release 0.9.17 this function 00061 incorrectly did nothing. While this works for many 00062 cases, it caused a subtle, hard-to-track bug in 00063 s11n::list::deserialize_list(), in which a deserialized 00064 list was re-used when the function was called recursively. 00065 Many thanks to Patrick Lin for reporting that problem. 00066 00067 */ 00068 static bool create( value_type & v, 00069 const std::string & /* implclass */ = std::string() ) throw() 00070 { 00071 // if( 0 ) CERR << "create(&) implclass="<<implclass<<": initializing @" <<std::hex<<&v <<"\n"; 00072 try 00073 { 00074 v = value_type(); 00075 } 00076 catch(...) 00077 { 00078 return false; 00079 } 00080 return true; 00081 } 00082 00083 }; // abstract_creator<T> 00084 00085 /** 00086 A specialization of abstract_creator to create objects on 00087 the heap, using the s11n::cl API. 00088 */ 00089 template <typename T> 00090 struct abstract_creator<T *> 00091 { 00092 /** Same as (T *). */ 00093 typedef T * value_type; 00094 00095 /** Same as (T). */ 00096 typedef T base_value_type; 00097 00098 /** 00099 Tries to create a value_type object, 00100 using classload<base_value_type>( key ) 00101 to create it. v is assigned to it's value, which 00102 may be 0. Returns true if an object is created, 00103 else false. 00104 00105 If the call succeeds, the caller owns the memory 00106 pointed to by v. 00107 00108 If implclass is NOT passed then it must guess and 00109 for polymorphic types it is likely to guess 00110 incorrectly. It relies on 00111 s11n_traits<base_value_type>::class_name(v) 00112 returning a valid value, which is normally only 00113 useful for monomorphic types and base-most 00114 Serializables in a registered hierarchy (which are, 00115 for s11n purposes, the same thing). 00116 00117 Maintenance note: new classloader registrations may 00118 need to be installed as new types show up, 00119 especially for streamables/PODs (because those 00120 aren't normally registered as classes), or this 00121 function won't handle them. In s11n this 00122 registration is handled by most of the various 00123 proxy installation macros. See the headers under 00124 s11n.net/s11n/proxy/pod_*.hpp for examples. 00125 */ 00126 static bool create( value_type & v, 00127 const std::string & implclass = std::string() /* guess! */ ) throw() 00128 { 00129 try 00130 { 00131 typedef s11n_traits<base_value_type> STR; 00132 const std::string key = 00133 (! implclass.empty()) 00134 ? implclass 00135 : STR::class_name(v); // reminder: v is a ref to a pointer! 00136 v = ::s11n::cl::classload<base_value_type>( key ); 00137 // if( 0 ) CERR << "create(*) implclass=["<<key<<"] allocated @" <<std::hex<<&v <<"\n"; 00138 } 00139 catch(...) 00140 { 00141 return false; 00142 } 00143 return 0 != &v; 00144 } 00145 }; // abstract_creator<T *> 00146 00147 00148 } } // namespaces 00149 00150 #endif // s11n_ABSTRACT_CREATOR_H_INCLUDED 00151