Main Page   Class Hierarchy   Compound List   File List   Compound Members  

scf.h

00001 /*
00002     Crystal Space Shared Class Facility (SCF)
00003     Copyright (C) 1999 by Andrew Zabolotny
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 #ifndef __CSSCF_H__
00021 #define __CSSCF_H__
00022 
00023 /*
00024     PLEASE USE 8-SPACE TAB WIDTH WHEN EDITING THIS FILE!
00025 */
00026 
00030 typedef uint32 scfInterfaceID;
00031 
00036 #ifdef SCF_DEBUG
00037 #  define SCF_TRACE(x)                                                  \
00038    {                                                                    \
00039      printf ("SCF [%s:%d]:\n", __FILE__, __LINE__);                     \
00040      printf x; SCF_PRINT_CALL_ADDRESS                                   \
00041    }
00042 #else
00043 #  define SCF_TRACE(x)
00044 #endif
00045 
00050 #if (__GNUC__ >= 2) && (__GNUC_MINOR__ >= 8)
00051 #  define SCF_PRINT_CALL_ADDRESS                                        \
00052    printf ("  Called from address %p\n", __builtin_return_address (0));
00053 #else
00054 #  define SCF_PRINT_CALL_ADDRESS
00055 #endif
00056 
00058 #define SCF_CONSTRUCT_VERSION(Major,Minor,Micro)                        \
00059   ((Major << 24) | (Minor << 16) | Micro)
00060 
00073 #define SCF_VERSION(Name,Major,Minor,Micro)                             \
00074   const int VERSION_##Name = SCF_CONSTRUCT_VERSION (Major, Minor, Micro)
00075 
00076 SCF_VERSION (iBase, 0, 1, 0);
00077 
00083 struct iBase
00084 {
00086   virtual void IncRef () = 0;
00088   virtual void DecRef () = 0;
00090   virtual int GetRefCount () = 0;
00092   virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) = 0;
00097   static void* QueryInterfaceSafe (iBase* ibase, scfInterfaceID iInterfaceID,
00098         int iVersion)
00099   {
00100     if (ibase == NULL) return NULL;
00101     else return ibase->QueryInterface (iInterfaceID, iVersion);
00102   }
00103 };
00104 
00106 #define SCF_INC_REF(ptr) {if (ptr) {ptr->IncRef();}}
00107 
00109 #define SCF_DEC_REF(ptr) {if (ptr) {ptr->DecRef();}}
00110 
00116 #define SCF_SET_REF(var,ref) \
00117   { \
00118     if (ref) ref->IncRef (); \
00119     if (var) var->DecRef (); \
00120     var = ref; \
00121   }
00122 
00127 #define SCF_DECLARE_IBASE                                               \
00128   int scfRefCount;              /* Reference counter */                 \
00129   SCF_DECLARE_EMBEDDED_IBASE (iBase)
00130 
00135 #define SCF_DECLARE_EMBEDDED_IBASE(OuterClass)                          \
00136 public:                                                                 \
00137   OuterClass *scfParent;        /* The parent object */                 \
00138   virtual void IncRef ();                                               \
00139   virtual void DecRef ();                                               \
00140   virtual int GetRefCount ();                                           \
00141   virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion)
00142 
00151 #define SCF_CONSTRUCT_IBASE(Parent)                                     \
00152   scfRefCount = 1; scfParent = Parent; if (scfParent) scfParent->IncRef();
00153 
00161 #define SCF_CONSTRUCT_EMBEDDED_IBASE(Interface)                         \
00162   Interface.scfParent = this;
00163 
00169 #define SCF_IMPLEMENT_IBASE_INCREF(Class)                               \
00170 void Class::IncRef ()                                                   \
00171 {                                                                       \
00172   SCF_TRACE (("  (%s *)%p->IncRef (%d)\n", #Class, this, scfRefCount + 1));\
00173   scfRefCount++;                                                        \
00174 }
00175 
00181 #define SCF_IMPLEMENT_IBASE_DECREF(Class)                               \
00182 void Class::DecRef ()                                                   \
00183 {                                                                       \
00184   scfRefCount--;                                                        \
00185   if (scfRefCount <= 0)                                                 \
00186   {                                                                     \
00187     SCF_TRACE (("  delete (%s *)%p\n", #Class, this));                  \
00188     if (scfParent)                                                      \
00189       scfParent->DecRef ();                                             \
00190     delete this;                                                        \
00191   }                                                                     \
00192   else                                                                  \
00193     SCF_TRACE (("  (%s *)%p->DecRef (%d)\n", #Class, this, scfRefCount));\
00194 }
00195 
00200 #define SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class)                          \
00201 int Class::GetRefCount ()                                               \
00202 {                                                                       \
00203   return scfRefCount;                                                   \
00204 }
00205 
00212 #define SCF_IMPLEMENT_IBASE_QUERY(Class)                                \
00213 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \
00214 {                                                                       \
00215   SCF_TRACE (("  (%s *)%p->QueryInterface (%u, %08X)\n",                \
00216     #Class, this, iInterfaceID, iVersion));
00217 
00224 #define SCF_IMPLEMENT_IBASE_QUERY_END                                   \
00225   return scfParent ?                                                    \
00226     scfParent->QueryInterface (iInterfaceID, iVersion) : NULL;          \
00227 }
00228 
00234 #define SCF_IMPLEMENT_IBASE(Class)                                      \
00235   SCF_IMPLEMENT_IBASE_INCREF(Class)                                     \
00236   SCF_IMPLEMENT_IBASE_DECREF(Class)                                     \
00237   SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class)                                \
00238   SCF_IMPLEMENT_IBASE_QUERY(Class)
00239 
00244 #define SCF_IMPLEMENT_IBASE_END                                         \
00245   SCF_IMPLEMENT_IBASE_QUERY_END
00246 
00253 #define SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class)                      \
00254 void Class::IncRef ()                                                   \
00255 {                                                                       \
00256   SCF_TRACE (("  (%s *)%p->IncRef (%d)\n", #Class, this,                \
00257     scfParent->GetRefCount () + 1));                                    \
00258   scfParent->IncRef ();                                                 \
00259 }
00260 
00267 #define SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class)                      \
00268 void Class::DecRef ()                                                   \
00269 {                                                                       \
00270   scfParent->DecRef ();                                                 \
00271   SCF_TRACE (("  (%s *)%p->DecRef (%d)\n", #Class, this,                \
00272     scfParent->GetRefCount ()));                                                \
00273 }
00274 
00279 #define SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class)                 \
00280 int Class::GetRefCount ()                                               \
00281 {                                                                       \
00282   return scfParent->GetRefCount ();                                     \
00283 }
00284 
00291 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class)                       \
00292 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \
00293 {                                                                       \
00294   SCF_TRACE (("  (%s *)%p->QueryInterface (%u, %08X)\n",                \
00295     #Class, this, iInterfaceID, iVersion));
00296 
00303 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END                          \
00304   return scfParent->QueryInterface (iInterfaceID, iVersion);            \
00305 }
00306 
00313 #define SCF_IMPLEMENT_EMBEDDED_IBASE(Class)                             \
00314   SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class)                            \
00315   SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class)                            \
00316   SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class)                       \
00317   SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class)
00318 
00323 #define SCF_IMPLEMENT_EMBEDDED_IBASE_END                                \
00324   SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END
00325 
00332 #define SCF_IMPLEMENTS_INTERFACE(Interface)                             \
00333   SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, this)
00334 
00339 #define SCF_IMPLEMENTS_EMBEDDED_INTERFACE(Interface)                    \
00340   SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, (&scf##Interface))
00341 
00345 #define SCF_IMPLEMENTS_INTERFACE_COMMON(Interface,Object)               \
00346   static scfInterfaceID scfID_##Interface = (scfInterfaceID)-1;         \
00347   if (scfID_##Interface == (scfInterfaceID)-1)                          \
00348     scfID_##Interface = iSCF::SCF->GetInterfaceID (#Interface);         \
00349   if (iInterfaceID == scfID_##Interface &&                              \
00350     scfCompatibleVersion (iVersion, VERSION_##Interface))               \
00351   {                                                                     \
00352     (Object)->IncRef ();                                                \
00353     return STATIC_CAST(Interface*, Object);                             \
00354   }
00355 
00366 #define SCF_DECLARE_IBASE_EXT(ParentClass)                              \
00367   typedef ParentClass __scf_superclass;                                 \
00368   virtual void IncRef ();                                               \
00369   virtual void DecRef ();                                               \
00370   virtual int GetRefCount ();                                           \
00371   virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion)
00372 
00379 #define SCF_IMPLEMENT_IBASE_EXT_INCREF(Class)                           \
00380 void Class::IncRef ()                                                   \
00381 {                                                                       \
00382   __scf_superclass::IncRef ();                                          \
00383 }
00384 
00391 #define SCF_IMPLEMENT_IBASE_EXT_DECREF(Class)                           \
00392 void Class::DecRef ()                                                   \
00393 {                                                                       \
00394   __scf_superclass::DecRef ();                                          \
00395 }
00396 
00403 #define SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class)                      \
00404 int Class::GetRefCount ()                                               \
00405 {                                                                       \
00406   return __scf_superclass::GetRefCount ();                              \
00407 }
00408 
00415 #define SCF_IMPLEMENT_IBASE_EXT_QUERY(Class)                            \
00416 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \
00417 {
00418 
00425 #define SCF_IMPLEMENT_IBASE_EXT_QUERY_END                               \
00426   return __scf_superclass::QueryInterface (iInterfaceID, iVersion);     \
00427 }
00428 
00433 #define SCF_IMPLEMENT_IBASE_EXT(Class)                                  \
00434   SCF_IMPLEMENT_IBASE_EXT_INCREF(Class)                                 \
00435   SCF_IMPLEMENT_IBASE_EXT_DECREF(Class)                                 \
00436   SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class)                            \
00437   SCF_IMPLEMENT_IBASE_EXT_QUERY(Class)
00438 
00443 #define SCF_IMPLEMENT_IBASE_EXT_END                                     \
00444   SCF_IMPLEMENT_IBASE_EXT_QUERY_END
00445 
00452 #define SCF_IMPLEMENT_FACTORY(Class)                                    \
00453 void *Create_##Class (iBase *iParent)                                   \
00454 {                                                                       \
00455   void *ret = new Class (iParent);                                      \
00456   SCF_TRACE (("  %p = new %s ()\n", ret, #Class));                      \
00457   return ret;                                                           \
00458 }
00459 
00464 #define SCF_DECLARE_FACTORY(Class)  void *Create_##Class (iBase *iParent);
00465 
00471 struct scfClassInfo
00472 {
00474   char *ClassID;
00476   char *Description;
00482   char *Dependencies;
00484   void *(*Factory) (iBase *iParent);
00485 };
00486 
00487 /*
00488  * The following set of macros are used to define the table that contains
00489  * information about all classes exported from a shared library. This table
00490  * is used with both static and dynamic class linking.
00491  */
00492 
00508 #define SCF_EXPORT_CLASS_TABLE(LibraryName)                             \
00509 static inline void                                                      \
00510 SCF_EXPORTED_NAME(LibraryName,_scfUnitInitialize)(iSCF *SCF)            \
00511 { iSCF::SCF = SCF; }                                                    \
00512 SCF_EXPORT_FUNCTION scfClassInfo*                                       \
00513 SCF_EXPORTED_NAME(LibraryName,_scfInitialize)(iSCF *SCF)                \
00514 {                                                                       \
00515   SCF_EXPORTED_NAME(LibraryName,_scfUnitInitialize)(SCF);               \
00516   static scfClassInfo ExportClassTable [] =                             \
00517   {
00518 
00520 #define SCF_EXPORT_CLASS(Class, ClassID, Description)                   \
00521     { ClassID, Description, NULL, Create_##Class },
00522 
00524 #define SCF_EXPORT_CLASS_DEP(Class, ClassID, Description, Dependencies) \
00525     { ClassID, Description, Dependencies, Create_##Class },
00526 
00528 #define SCF_EXPORT_CLASS_TABLE_END                                      \
00529     { 0, 0, 0, 0 }                                                      \
00530   };                                                                    \
00531   return ExportClassTable;                                              \
00532 }
00533 
00541 #define SCF_REGISTER_STATIC_LIBRARY(LibraryName)                        \
00542   extern "C" scfClassInfo *LibraryName##_scfInitialize (iSCF*);         \
00543   class __##LibraryName##_Init                                          \
00544   {                                                                     \
00545   public:                                                               \
00546     __##LibraryName##_Init ()                                           \
00547     { if (!iSCF::SCF) scfInitialize ();                                 \
00548       iSCF::SCF->RegisterClassList(LibraryName##_scfInitialize(iSCF::SCF)); }\
00549   } __##LibraryName##_dummy;
00550 
00556 #define SCF_REGISTER_STATIC_CLASS(Class,ClassID,Description)            \
00557   SCF_REGISTER_STATIC_CLASS_DEP (Class,ClassID,Description,NULL);
00558 
00563 #define SCF_REGISTER_STATIC_CLASS_DEP(Class,ClassID,Description,Dependency)\
00564   extern void *Create_##Class (iBase *);                                \
00565   static scfClassInfo Class##_ClassInfo =                               \
00566   { ClassID, Description, Dependency, Create_##Class };                 \
00567   class __##Class##_Init                                                \
00568   {                                                                     \
00569   public:                                                               \
00570     __##Class##_Init ()                                                 \
00571     { if (!iSCF::SCF) scfInitialize ();                                 \
00572       iSCF::SCF->RegisterStaticClass (&Class##_ClassInfo); }            \
00573   } __##Class##_dummy;
00574 
00575 //--------------------------------------------- Class factory interface -----//
00576 
00577 SCF_VERSION (iFactory, 0, 0, 1);
00578 
00591 struct iFactory : public iBase
00592 {
00594   virtual void *CreateInstance () = 0;
00596   virtual void TryUnload () = 0;
00598   virtual const char *QueryDescription () = 0;
00600   virtual const char *QueryDependencies () = 0;
00602   virtual const char *QueryClassID () = 0;
00603 };
00604 
00605 //----------------------------------------------- Client-side functions -----//
00606 
00607 struct iConfigFile;
00608 struct iStrVector;
00609 
00616 #define SCF_DECLARE_FAST_INTERFACE(Interface)                           \
00617 inline static scfInterfaceID scfGetID_##Interface ()                    \
00618 {                                                                       \
00619   static scfInterfaceID ID = (scfInterfaceID)-1;                        \
00620   if (ID == (scfInterfaceID)(-1))                                       \
00621     ID = iSCF::SCF->GetInterfaceID (#Interface);                        \
00622   return ID;                                                            \
00623 }
00624 
00629 #define SCF_CREATE_INSTANCE(ClassID,Interface)                          \
00630   (Interface *)iSCF::SCF->CreateInstance (                              \
00631   ClassID, #Interface, VERSION_##Interface)
00632 
00637 #define SCF_QUERY_INTERFACE(Object,Interface)                           \
00638   (Interface *)(Object)->QueryInterface (                               \
00639     iSCF::SCF->GetInterfaceID (#Interface), VERSION_##Interface)
00640 
00648 #define SCF_QUERY_INTERFACE_FAST(Object,Interface)                      \
00649   (Interface*)(Object)->QueryInterface (                                \
00650   scfGetID_##Interface (), VERSION_##Interface)
00651 
00657 #define SCF_QUERY_INTERFACE_SAFE(Object,Interface)                      \
00658   (Interface *)(iBase::QueryInterfaceSafe ((Object),                    \
00659     iSCF::SCF->GetInterfaceID (#Interface), VERSION_##Interface))
00660 
00668 extern void scfInitialize (iConfigFile *iConfig = 0);
00669 
00676 static inline bool scfCompatibleVersion (int iVersion, int iItfVersion)
00677 {
00678   return ((iVersion & 0xff000000) == (iItfVersion & 0xff000000))
00679       && ((iVersion & 0x00ffffff) <= (iItfVersion & 0x00ffffff));
00680 }
00681 
00682 SCF_VERSION (iSCF, 0, 0, 1);
00683 
00690 struct iSCF : public iBase
00691 {
00693   static iSCF *SCF;
00694 
00699   virtual void RegisterConfigClassList (iConfigFile *Config) = 0;
00700 
00707   virtual bool ClassRegistered (const char *iClassID) = 0;
00708 
00724   virtual void *CreateInstance (const char *iClassID,
00725         const char *iInterface, int iVersion) = 0;
00726 
00732   virtual const char *GetClassDescription (const char *iClassID) = 0;
00733 
00739   virtual const char *GetClassDependencies (const char *iClassID) = 0;
00740 
00747   virtual void UnloadUnusedModules () = 0;
00748   
00756   virtual bool RegisterClass (const char *iClassID,
00757         const char *iLibraryName, const char *Dependencies = NULL) = 0;
00758 
00765   virtual bool RegisterStaticClass (scfClassInfo *iClassInfo) = 0;
00766 
00775   virtual bool RegisterClassList (scfClassInfo *iClassInfo) = 0;
00776 
00783   virtual bool UnregisterClass (const char *iClassID) = 0;
00784 
00790   virtual scfInterfaceID GetInterfaceID (const char *iInterface) = 0;
00791 
00798   virtual void Finish () = 0;
00799 
00810   virtual iStrVector* QueryClassList (char const* pattern) = 0;
00811 };
00812 
00813 //-------------------------------------------- System-dependent defines -----//
00814 
00815 /*
00816  * A macro to export a function from a shared library.
00817  * Some platforms may need to override this.  For instance, Windows requires
00818  * extra `__declspec' goop when exporting a function from a plug-in module.
00819  */
00820 #if !defined(SCF_EXPORT_FUNCTION)
00821 #  define SCF_EXPORT_FUNCTION extern "C"
00822 #endif
00823 
00824 /*
00825  * A macro used to build exported function names.
00826  * Usually "Prefix" is derived from shared library name, thus for each library
00827  * we'll have different exported names.  This prevents naming collisions when
00828  * static linking is used, and on platforms where plug-in symbols are exported
00829  * by default.  However, this may be bad for platforms which need to build
00830  * special export-tables on-the-fly at compile-time since distinct names make
00831  * the job more difficult.  Such platforms may need to override the default
00832  * expansion of this macro to use only the `Suffix' and ignore the `Prefix'
00833  * when composing the name.
00834  */
00835 #if !defined(SCF_EXPORTED_NAME)
00836 #  define SCF_EXPORTED_NAME(Prefix, Suffix) Prefix ## Suffix
00837 #endif
00838 
00839 #endif // __CSSCF_H__

Generated for Crystal Space by doxygen 1.2.5 written by Dimitri van Heesch, ©1997-2000