TypeCollection.h

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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         // Check that the given typecode is within the legal bounds
00168         // for the _Type of the return
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         // Based on the lookup in the dispatch, create a new object
00177         // and cast it to the given type. Note the use of dynamic cast to 
00178         // safely downcast.
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 }; // namespace oasys
00283 
00284 #endif //__OASYS_TYPE_COLLECTION_H__

Generated on Thu Jun 7 12:54:30 2007 for DTN Reference Implementation by  doxygen 1.5.1