00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef __OASYS_TYPE_COLLECTION_H__
00039 #define __OASYS_TYPE_COLLECTION_H__
00040
00041 #include <map>
00042
00043 #include "../debug/Logger.h"
00044 #include "Serialize.h"
00045 #include "MarshalSerialize.h"
00046
00047 namespace oasys {
00048
00099 class TypeCollectionHelper;
00100
00101 namespace TypeCollectionErr {
00102 enum {
00103 TYPECODE = 1,
00104 MEMORY,
00105 };
00106 };
00107
00111 class TypeCollectionHelper {
00112 public:
00113 virtual SerializableObject* new_object() = 0;
00114 virtual const char* name() const = 0;
00115 virtual ~TypeCollectionHelper() {}
00116 };
00117
00123 template<typename _Collection, typename _Type> class TypeCollectionCode;
00124
00128 class TypeCollection {
00129 public:
00131 typedef u_int32_t TypeCode_t;
00132
00133 enum {
00134 UNKNOWN_TYPE = 0xffffffff
00135 };
00136
00138 typedef int (*Allocator_t)(TypeCode_t typecode,
00139 SerializableObject** data);
00140
00141 TypeCollection() {}
00142
00143 void reg(TypeCode_t typecode, TypeCollectionHelper* helper) {
00144 ASSERT(dispatch_.find(typecode) == dispatch_.end());
00145 dispatch_[typecode] = helper;
00146 }
00147
00151 const char* type_name(TypeCode_t typecode) {
00152 if(dispatch_.find(typecode) == dispatch_.end()) {
00153 return "";
00154 }
00155
00156 return dispatch_[typecode]->name();
00157 }
00158
00159 protected:
00160 std::map<TypeCode_t, TypeCollectionHelper*> dispatch_;
00161 };
00162
00163 template<typename _Collection>
00164 class TypeCollectionInstance : public TypeCollection {
00165 public:
00171 static TypeCollectionInstance<_Collection>* instance() {
00172 if(!instance_) {
00173 instance_ = new TypeCollectionInstance<_Collection>();
00174 }
00175 return instance_;
00176 }
00177
00185 template<typename _Type>
00186 int new_object(TypeCode_t typecode, _Type** obj, bool check_type = true)
00187 {
00188
00189
00190 if(check_type &&
00191 (TypeCollectionCode<_Collection, _Type>::TYPECODE_LOW > typecode ||
00192 TypeCollectionCode<_Collection, _Type>::TYPECODE_HIGH < typecode))
00193 {
00194 return TypeCollectionErr::TYPECODE;
00195 }
00196
00197
00198
00199
00200 ASSERT(dispatch_.find(typecode) != dispatch_.end());
00201 *obj = dynamic_cast<_Type*>(dispatch_[typecode]->new_object());
00202 if (*obj == NULL) {
00203 log_crit("/oasys/type_collection", "out of memory");
00204 return TypeCollectionErr::MEMORY;
00205 }
00206
00207 return 0;
00208 }
00209
00210 private:
00211 static TypeCollectionInstance<_Collection>* instance_;
00212 };
00213
00219 template<typename _Collection, typename _Class>
00220 class TypeCollectionDispatch : public TypeCollectionHelper {
00221 public:
00223 TypeCollectionDispatch<_Collection, _Class>(TypeCollection::TypeCode_t typecode,
00224 const char* name)
00225 : name_(name)
00226 {
00227 TypeCollectionInstance<_Collection>::instance()->reg(typecode, this);
00228 }
00229
00240 SerializableObject* new_object() {
00241 return static_cast<SerializableObject*>
00242 (new _Class(Builder()));
00243 }
00244
00245 const char* name() const { return name_; }
00246
00247 private:
00248 const char* name_;
00249 };
00250
00254 #define TYPE_COLLECTION_DEFINE(_collection, _class, _typecode) \
00255 oasys::TypeCollectionDispatch<_collection, _class> \
00256 _class ## TypeCollectionInstance(_typecode, #_collection "::" #_class);
00257
00261 #define TYPE_COLLECTION_DECLARE(_Collection, _Class, _code) \
00262 namespace oasys { \
00263 template<> \
00264 struct TypeCollectionCode<_Collection, _Class> { \
00265 enum { \
00266 TYPECODE_LOW = _code, \
00267 TYPECODE_HIGH = _code \
00268 }; \
00269 enum { \
00270 TYPECODE = _code \
00271 }; \
00272 }; \
00273 }
00274
00285 #define TYPE_COLLECTION_GROUP(_Collection, _Class, _low, _high) \
00286 namespace oasys { \
00287 template<> \
00288 struct TypeCollectionCode<_Collection, _Class> { \
00289 enum { \
00290 TYPECODE_LOW = _low, \
00291 TYPECODE_HIGH = _high, \
00292 }; \
00293 }; \
00294 }
00295
00299 #define TYPE_COLLECTION_INSTANTIATE(_Collection) \
00300 template<> class oasys::TypeCollectionInstance<_Collection>* \
00301 oasys::TypeCollectionInstance<_Collection>::instance_ = 0
00302
00303 };
00304
00305 #endif //__OASYS_TYPE_COLLECTION_H__