00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __OASYS_TYPE_COLLECTION_H__
00018 #define __OASYS_TYPE_COLLECTION_H__
00019
00020 #include <map>
00021
00022 #include "../debug/Logger.h"
00023 #include "Serialize.h"
00024 #include "MarshalSerialize.h"
00025
00026 namespace oasys {
00027
00078 class TypeCollectionHelper;
00079
00080 namespace TypeCollectionErr {
00081 enum {
00082 TYPECODE = 1,
00083 MEMORY,
00084 };
00085 };
00086
00090 class TypeCollectionHelper {
00091 public:
00092 virtual SerializableObject* new_object() = 0;
00093 virtual const char* name() const = 0;
00094 virtual ~TypeCollectionHelper() {}
00095 };
00096
00102 template<typename _Collection, typename _Type> class TypeCollectionCode;
00103
00107 class TypeCollection {
00108 public:
00110 typedef u_int32_t TypeCode_t;
00111
00112 enum {
00113 UNKNOWN_TYPE = 0xffffffff
00114 };
00115
00117 typedef int (*Allocator_t)(TypeCode_t typecode,
00118 SerializableObject** data);
00119
00120 TypeCollection() {}
00121
00122 void reg(TypeCode_t typecode, TypeCollectionHelper* helper) {
00123 ASSERT(dispatch_.find(typecode) == dispatch_.end());
00124 dispatch_[typecode] = helper;
00125 }
00126
00130 const char* type_name(TypeCode_t typecode) {
00131 if(dispatch_.find(typecode) == dispatch_.end()) {
00132 return "";
00133 }
00134
00135 return dispatch_[typecode]->name();
00136 }
00137
00138 protected:
00139 std::map<TypeCode_t, TypeCollectionHelper*> dispatch_;
00140 };
00141
00142 template<typename _Collection>
00143 class TypeCollectionInstance : public TypeCollection {
00144 public:
00150 static TypeCollectionInstance<_Collection>* instance() {
00151 if(!instance_) {
00152 instance_ = new TypeCollectionInstance<_Collection>();
00153 }
00154 return instance_;
00155 }
00156
00164 template<typename _Type>
00165 int new_object(TypeCode_t typecode, _Type** obj, bool check_type = true)
00166 {
00167
00168
00169 if(check_type &&
00170 (TypeCollectionCode<_Collection, _Type>::TYPECODE_LOW > typecode ||
00171 TypeCollectionCode<_Collection, _Type>::TYPECODE_HIGH < typecode))
00172 {
00173 return TypeCollectionErr::TYPECODE;
00174 }
00175
00176
00177
00178
00179 ASSERT(dispatch_.find(typecode) != dispatch_.end());
00180 *obj = dynamic_cast<_Type*>(dispatch_[typecode]->new_object());
00181 if (*obj == NULL) {
00182 log_crit_p("/oasys/type_collection", "out of memory");
00183 return TypeCollectionErr::MEMORY;
00184 }
00185
00186 return 0;
00187 }
00188
00189 private:
00190 static TypeCollectionInstance<_Collection>* instance_;
00191 };
00192
00198 template<typename _Collection, typename _Class>
00199 class TypeCollectionDispatch : public TypeCollectionHelper {
00200 public:
00202 TypeCollectionDispatch<_Collection, _Class>(TypeCollection::TypeCode_t typecode,
00203 const char* name)
00204 : name_(name)
00205 {
00206 TypeCollectionInstance<_Collection>::instance()->reg(typecode, this);
00207 }
00208
00219 SerializableObject* new_object() {
00220 return static_cast<SerializableObject*>
00221 (new _Class(Builder()));
00222 }
00223
00224 const char* name() const { return name_; }
00225
00226 private:
00227 const char* name_;
00228 };
00229
00233 #define TYPE_COLLECTION_DEFINE(_collection, _class, _typecode) \
00234 oasys::TypeCollectionDispatch<_collection, _class> \
00235 _class ## TypeCollectionInstance(_typecode, #_collection "::" #_class);
00236
00240 #define TYPE_COLLECTION_DECLARE(_Collection, _Class, _code) \
00241 namespace oasys { \
00242 template<> \
00243 struct TypeCollectionCode<_Collection, _Class> { \
00244 enum { \
00245 TYPECODE_LOW = _code, \
00246 TYPECODE_HIGH = _code \
00247 }; \
00248 enum { \
00249 TYPECODE = _code \
00250 }; \
00251 }; \
00252 }
00253
00264 #define TYPE_COLLECTION_GROUP(_Collection, _Class, _low, _high) \
00265 namespace oasys { \
00266 template<> \
00267 struct TypeCollectionCode<_Collection, _Class> { \
00268 enum { \
00269 TYPECODE_LOW = _low, \
00270 TYPECODE_HIGH = _high, \
00271 }; \
00272 }; \
00273 }
00274
00278 #define TYPE_COLLECTION_INSTANTIATE(_Collection) \
00279 template<> class oasys::TypeCollectionInstance<_Collection>* \
00280 oasys::TypeCollectionInstance<_Collection>::instance_ = 0
00281
00282 };
00283
00284 #endif //__OASYS_TYPE_COLLECTION_H__