csutil/scf.h
Go to the documentation of this file.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 00031 class csPluginPaths; 00032 00033 #include "ref.h" 00034 #include "array.h" 00035 00039 typedef unsigned long scfInterfaceID; 00040 00045 #ifdef SCF_DEBUG 00046 # define SCF_TRACE(x) \ 00047 { \ 00048 printf ("SCF [%s:%d]:\n", __FILE__, __LINE__); \ 00049 printf x; SCF_PRINT_CALL_ADDRESS \ 00050 } 00051 #else 00052 # define SCF_TRACE(x) 00053 #endif 00054 00059 #if (__GNUC__ >= 3) || ((__GNUC__ >= 2) && (__GNUC_MINOR__ >= 8)) 00060 # define SCF_PRINT_CALL_ADDRESS \ 00061 printf (" Called from address %p\n", __builtin_return_address (0)); 00062 #else 00063 # define SCF_PRINT_CALL_ADDRESS 00064 #endif 00065 00067 #define SCF_CONSTRUCT_VERSION(Major,Minor,Micro) \ 00068 ((Major << 24) | (Minor << 16) | Micro) 00069 00075 struct iBase 00076 { 00078 virtual void IncRef () = 0; 00080 virtual void DecRef () = 0; 00082 virtual int GetRefCount () = 0; 00084 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) = 0; 00089 static void* QueryInterfaceSafe (iBase* ibase, scfInterfaceID iInterfaceID, 00090 int iVersion) 00091 { 00092 if (ibase == 0) return 0; 00093 else return ibase->QueryInterface (iInterfaceID, iVersion); 00094 } 00096 virtual void AddRefOwner (iBase** ref_owner) = 0; 00098 virtual void RemoveRefOwner (iBase** ref_owner) = 0; 00099 }; 00100 00105 #define SCF_DECLARE_IBASE \ 00106 int scfRefCount; /* Reference counter */ \ 00107 csArray<iBase**>* scfWeakRefOwners; \ 00108 void scfRemoveRefOwners (); \ 00109 SCF_DECLARE_EMBEDDED_IBASE (iBase) 00110 00115 #define SCF_DECLARE_EMBEDDED_IBASE(OuterClass) \ 00116 public: \ 00117 OuterClass *scfParent; /* The parent object */ \ 00118 virtual void IncRef (); \ 00119 virtual void DecRef (); \ 00120 virtual int GetRefCount (); \ 00121 virtual void AddRefOwner (iBase** ref_owner); \ 00122 virtual void RemoveRefOwner (iBase** ref_owner); \ 00123 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00124 00134 #define SCF_CONSTRUCT_IBASE(Parent) \ 00135 scfRefCount = 1; \ 00136 scfWeakRefOwners = 0; \ 00137 scfParent = Parent; if (scfParent) scfParent->IncRef(); 00138 00148 #define SCF_CONSTRUCT_EMBEDDED_IBASE(Interface) \ 00149 Interface.scfParent = this; 00150 00156 #define SCF_DESTRUCT_IBASE() \ 00157 scfRemoveRefOwners (); 00158 00165 #define SCF_DESTRUCT_EMBEDDED_IBASE(Interface) \ 00166 Interface.scfParent = 0; 00167 00173 #define SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00174 void Class::IncRef () \ 00175 { \ 00176 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, scfRefCount + 1));\ 00177 scfRefCount++; \ 00178 } 00179 00188 #define SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00189 void Class::DecRef () \ 00190 { \ 00191 if (scfRefCount == 1) \ 00192 { \ 00193 SCF_TRACE ((" delete (%s *)%p\n", #Class, this)); \ 00194 scfRemoveRefOwners (); \ 00195 if (scfParent) \ 00196 scfParent->DecRef (); \ 00197 delete this; \ 00198 return; \ 00199 } \ 00200 scfRefCount--; \ 00201 } 00202 00209 #define SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(Class) \ 00210 void Class::scfRemoveRefOwners () \ 00211 { \ 00212 if (!scfWeakRefOwners) return; \ 00213 for (int i = 0 ; i < scfWeakRefOwners->Length () ; i++) \ 00214 { \ 00215 iBase** p = (*scfWeakRefOwners)[i]; \ 00216 *p = 0; \ 00217 } \ 00218 delete scfWeakRefOwners; \ 00219 scfWeakRefOwners = 0; \ 00220 } 00221 00226 #define SCF_IMPLEMENT_IBASE_REFOWNER(Class) \ 00227 void Class::AddRefOwner (iBase** ref_owner) \ 00228 { \ 00229 if (!scfWeakRefOwners) \ 00230 scfWeakRefOwners = new csArray<iBase**>; \ 00231 scfWeakRefOwners->Push (ref_owner); \ 00232 } \ 00233 void Class::RemoveRefOwner (iBase** ref_owner) \ 00234 { \ 00235 if (!scfWeakRefOwners) \ 00236 scfWeakRefOwners = new csArray<iBase**>; \ 00237 scfWeakRefOwners->Delete (ref_owner); \ 00238 } 00239 00244 #define SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00245 int Class::GetRefCount () \ 00246 { \ 00247 return scfRefCount; \ 00248 } 00249 00256 #define SCF_IMPLEMENT_IBASE_QUERY(Class) \ 00257 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00258 { \ 00259 SCF_TRACE ((" (%s *)%p->QueryInterface (%u, %08X)\n", \ 00260 #Class, this, iInterfaceID, iVersion)); 00261 00268 #define SCF_IMPLEMENT_IBASE_QUERY_END \ 00269 return scfParent ? \ 00270 scfParent->QueryInterface (iInterfaceID, iVersion) : 0; \ 00271 } 00272 00278 #define SCF_IMPLEMENT_IBASE(Class) \ 00279 SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00280 SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00281 SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00282 SCF_IMPLEMENT_IBASE_REFOWNER(Class) \ 00283 SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(Class) \ 00284 SCF_IMPLEMENT_IBASE_QUERY(Class) 00285 00290 #define SCF_IMPLEMENT_IBASE_END \ 00291 SCF_IMPLEMENT_IBASE_QUERY_END 00292 00299 #define SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00300 void Class::IncRef () \ 00301 { \ 00302 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, \ 00303 scfParent->GetRefCount () + 1)); \ 00304 scfParent->IncRef (); \ 00305 } 00306 00313 #define SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00314 void Class::DecRef () \ 00315 { \ 00316 SCF_TRACE ((" (%s *)%p->DecRef (%d)\n", #Class, this, \ 00317 scfParent->GetRefCount ()-1)); \ 00318 scfParent->DecRef (); \ 00319 } 00320 00325 #define SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00326 int Class::GetRefCount () \ 00327 { \ 00328 return scfParent->GetRefCount (); \ 00329 } 00330 00335 #define SCF_IMPLEMENT_EMBEDDED_IBASE_REFOWNER(Class) \ 00336 void Class::AddRefOwner (iBase** ref_owner) \ 00337 { \ 00338 scfParent->AddRefOwner (ref_owner); \ 00339 } \ 00340 void Class::RemoveRefOwner (iBase** ref_owner) \ 00341 { \ 00342 scfParent->RemoveRefOwner (ref_owner); \ 00343 } 00344 00351 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) \ 00352 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00353 { \ 00354 SCF_TRACE ((" (%s *)%p->QueryInterface (%u, %08X)\n", \ 00355 #Class, this, iInterfaceID, iVersion)); 00356 00363 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END \ 00364 return scfParent->QueryInterface (iInterfaceID, iVersion); \ 00365 } 00366 00373 #define SCF_IMPLEMENT_EMBEDDED_IBASE(Class) \ 00374 SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00375 SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00376 SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00377 SCF_IMPLEMENT_EMBEDDED_IBASE_REFOWNER(Class) \ 00378 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) 00379 00384 #define SCF_IMPLEMENT_EMBEDDED_IBASE_END \ 00385 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END 00386 00393 #define SCF_IMPLEMENTS_INTERFACE(Interface) \ 00394 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, this) 00395 00400 #define SCF_IMPLEMENTS_EMBEDDED_INTERFACE(Interface) \ 00401 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, (&scf##Interface)) 00402 00406 #define SCF_IMPLEMENTS_INTERFACE_COMMON(Interface,Object) \ 00407 static scfInterfaceID Interface##_scfID = (scfInterfaceID)-1; \ 00408 if (Interface##_scfID == (scfInterfaceID)-1) \ 00409 Interface##_scfID = iSCF::SCF->GetInterfaceID (#Interface); \ 00410 if (iInterfaceID == Interface##_scfID && \ 00411 scfCompatibleVersion (iVersion, scfInterface<Interface>::GetVersion())) \ 00412 { \ 00413 (Object)->IncRef (); \ 00414 return CS_STATIC_CAST(Interface*, Object); \ 00415 } 00416 00427 #define SCF_DECLARE_IBASE_EXT(ParentClass) \ 00428 typedef ParentClass __scf_superclass; \ 00429 virtual void IncRef (); \ 00430 virtual void DecRef (); \ 00431 virtual int GetRefCount (); \ 00432 virtual void AddRefOwner (iBase** ref_owner); \ 00433 virtual void RemoveRefOwner (iBase** ref_owner); \ 00434 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00435 00442 #define SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00443 void Class::IncRef () \ 00444 { \ 00445 __scf_superclass::IncRef (); \ 00446 } 00447 00454 #define SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00455 void Class::DecRef () \ 00456 { \ 00457 __scf_superclass::DecRef (); \ 00458 } 00459 00466 #define SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00467 int Class::GetRefCount () \ 00468 { \ 00469 return __scf_superclass::GetRefCount (); \ 00470 } 00471 00476 #define SCF_IMPLEMENT_IBASE_EXT_REFOWNER(Class) \ 00477 void Class::AddRefOwner (iBase** ref_owner) \ 00478 { \ 00479 __scf_superclass::AddRefOwner (ref_owner); \ 00480 } \ 00481 void Class::RemoveRefOwner (iBase** ref_owner) \ 00482 { \ 00483 __scf_superclass::RemoveRefOwner (ref_owner); \ 00484 } 00485 00492 #define SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) \ 00493 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00494 { 00495 00502 #define SCF_IMPLEMENT_IBASE_EXT_QUERY_END \ 00503 return __scf_superclass::QueryInterface (iInterfaceID, iVersion); \ 00504 } 00505 00510 #define SCF_IMPLEMENT_IBASE_EXT(Class) \ 00511 SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00512 SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00513 SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00514 SCF_IMPLEMENT_IBASE_EXT_REFOWNER(Class) \ 00515 SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) 00516 00521 #define SCF_IMPLEMENT_IBASE_EXT_END \ 00522 SCF_IMPLEMENT_IBASE_EXT_QUERY_END 00523 00539 #define SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00540 static inline void Class ## _scfUnitInitialize(iSCF* SCF) \ 00541 { iSCF::SCF = SCF; } \ 00542 CS_EXPORTED_FUNCTION \ 00543 void CS_EXPORTED_NAME(Class,_scfInitialize)(iSCF* SCF) \ 00544 { Class ## _scfUnitInitialize(SCF); } 00545 00551 #define SCF_IMPLEMENT_FACTORY_FINIS(Class) \ 00552 CS_DECLARE_STATIC_VARIABLE_CLEANUP \ 00553 CS_EXPORTED_FUNCTION \ 00554 void CS_EXPORTED_NAME(Class,_scfFinalize)() \ 00555 { \ 00556 CS_STATIC_VARIABLE_CLEANUP \ 00557 iSCF::SCF = 0; \ 00558 } 00559 00566 #define SCF_IMPLEMENT_FACTORY_CREATE(Class) \ 00567 CS_EXPORTED_FUNCTION \ 00568 void* CS_EXPORTED_NAME(Class,_Create)(iBase *iParent) \ 00569 { \ 00570 void *ret = new Class (iParent); \ 00571 SCF_TRACE ((" %p = new %s ()\n", ret, #Class)); \ 00572 return ret; \ 00573 } 00574 00581 #define SCF_IMPLEMENT_FACTORY(Class) \ 00582 SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00583 SCF_IMPLEMENT_FACTORY_FINIS(Class) \ 00584 SCF_IMPLEMENT_FACTORY_CREATE(Class) 00585 00586 #define SCF_STATIC_CLASS_CONTEXT "*static*" 00587 00596 #define SCF_REGISTER_STATIC_CLASS(Class,Ident,Desc,Dep) \ 00597 CS_EXPORTED_FUNCTION void* CS_EXPORTED_NAME(Class,_Create)(iBase*); \ 00598 class Class##_StaticInit__ \ 00599 { \ 00600 public: \ 00601 Class##_StaticInit__() \ 00602 { \ 00603 scfInitialize(0); \ 00604 iSCF::SCF->RegisterClass( \ 00605 CS_EXPORTED_NAME(Class,_Create), Ident, Desc, Dep, \ 00606 SCF_STATIC_CLASS_CONTEXT); \ 00607 } \ 00608 } Class##_static_init__; 00609 00614 #define SCF_REGISTER_STATIC_LIBRARY(Module, MetaInfo) \ 00615 class Module##_StaticInit \ 00616 { \ 00617 public: \ 00618 Module##_StaticInit() \ 00619 { \ 00620 scfInitialize(0); \ 00621 iSCF::SCF->RegisterClasses(MetaInfo, SCF_STATIC_CLASS_CONTEXT); \ 00622 } \ 00623 } Module##_static_init__; 00624 00633 #define SCF_REGISTER_FACTORY_FUNC(Class) \ 00634 CS_EXPORTED_FUNCTION void* CS_EXPORTED_NAME(Class,_Create)(iBase*); \ 00635 class Class##_StaticInit \ 00636 { \ 00637 public: \ 00638 Class##_StaticInit() \ 00639 { \ 00640 scfInitialize(0); \ 00641 iSCF::SCF->RegisterFactoryFunc(CS_EXPORTED_NAME(Class,_Create),#Class); \ 00642 } \ 00643 } Class##_static_init__; 00644 00645 //--------------------------------------------- Class factory interface -----// 00646 00660 struct iFactory : public iBase 00661 { 00663 virtual void *CreateInstance () = 0; 00665 virtual void TryUnload () = 0; 00667 virtual const char *QueryDescription () = 0; 00669 virtual const char *QueryDependencies () = 0; 00671 virtual const char *QueryClassID () = 0; 00672 }; 00673 00674 //----------------------------------------------- Client-side functions -----// 00675 00676 struct iDocument; 00677 struct iStringArray; 00678 00680 typedef void* (*scfFactoryFunc)(iBase*); 00681 00686 #define SCF_CREATE_INSTANCE(ClassID,Interface) \ 00687 csPtr<Interface> ( \ 00688 (Interface *)iSCF::SCF->CreateInstance ( \ 00689 ClassID, #Interface, scfInterface<Interface>::GetVersion())) 00690 00703 #define SCF_VERSION(Name,Major,Minor,Micro) \ 00704 struct Name; \ 00705 CS_SPECIALIZE_TEMPLATE \ 00706 class scfInterface<Name> \ 00707 { \ 00708 public: \ 00709 static int GetVersion() \ 00710 { \ 00711 return SCF_CONSTRUCT_VERSION(Major, Minor, Micro); \ 00712 } \ 00713 static scfInterfaceID GetID() \ 00714 { \ 00715 static scfInterfaceID ID = (scfInterfaceID)-1; \ 00716 if (ID == (scfInterfaceID)(-1)) \ 00717 ID = iSCF::SCF->GetInterfaceID(#Name); \ 00718 return ID; \ 00719 } \ 00720 static char const* GetName() \ 00721 { \ 00722 return #Name; \ 00723 } \ 00724 }; 00725 00732 template <class T> class scfInterface 00733 { 00734 public: 00739 static int GetVersion() { return 0; } 00740 00748 static scfInterfaceID GetID() { return (scfInterfaceID)(-1); } 00749 00753 static char const* GetName() { return 0; } 00754 }; 00755 00760 #define SCF_QUERY_INTERFACE(Object,Interface) \ 00761 csPtr<Interface> ((Interface *)(Object)->QueryInterface ( \ 00762 scfInterface<Interface>::GetID (), scfInterface<Interface>::GetVersion())) 00763 00769 #define SCF_QUERY_INTERFACE_SAFE(Object,Interface) \ 00770 csPtr<Interface> ((Interface *)(iBase::QueryInterfaceSafe ((Object), \ 00771 scfInterface<Interface>::GetID (), scfInterface<Interface>::GetVersion()))) 00772 00786 extern void scfInitialize (csPluginPaths* pluginPaths); 00787 00792 extern void scfInitialize (int argc, const char* const argv[]); 00793 00800 static inline bool scfCompatibleVersion (int iVersion, int iItfVersion) 00801 { 00802 return ((iVersion & 0xff000000) == (iItfVersion & 0xff000000)) 00803 && ((iVersion & 0x00ffffff) <= (iItfVersion & 0x00ffffff)); 00804 } 00805 00806 #ifdef CS_DEBUG 00807 struct iObjectRegistry; 00808 #endif 00809 00816 struct iSCF : public iBase 00817 { 00823 static iSCF* SCF; 00824 00825 #ifdef CS_DEBUG 00826 // This is EXTREMELY dirty but I see no other solution for now. 00827 // For debugging reasons I must have a global (global over the application 00828 // and all plugins)pointer to the object registry. I have no other 00829 // global object to tag this pointer on that except for iSCF. 00830 // This pointer is only here in debug mode though. That ensures that it 00831 // cannot be misused in real code. 00832 // If you know another solution for this problem? This global pointer 00833 // will be used by csDebuggingGraph in csutil. 00834 iObjectRegistry* object_reg; 00835 #endif 00836 00840 virtual void RegisterClasses (iDocument* metadata, 00841 const char* context = 0) = 0; 00842 00848 virtual void RegisterClasses (char const* xml, 00849 const char* context = 0) = 0; 00850 00854 virtual void RegisterClasses (const char* pluginPath, 00855 iDocument* metadata, const char* context = 0) = 0; 00856 00863 virtual bool ClassRegistered (const char *iClassID) = 0; 00864 00880 virtual void *CreateInstance (const char *iClassID, 00881 const char *iInterface, int iVersion) = 0; 00882 00888 virtual const char *GetClassDescription (const char *iClassID) = 0; 00889 00895 virtual const char *GetClassDependencies (const char *iClassID) = 0; 00896 00903 virtual void UnloadUnusedModules () = 0; 00904 00915 virtual bool RegisterClass (const char *iClassID, 00916 const char *iLibraryName, const char *iFactoryClass, 00917 const char *Description, const char *Dependencies = 0, 00918 const char* context = 0) = 0; 00919 00926 virtual bool RegisterClass (scfFactoryFunc, const char *iClassID, 00927 const char *Description, const char *Dependencies = 0, 00928 const char* context = 0) = 0; 00929 00937 virtual bool RegisterFactoryFunc (scfFactoryFunc, const char *FactClass) = 0; 00938 00945 virtual bool UnregisterClass (const char *iClassID) = 0; 00946 00951 virtual char const* GetInterfaceName (scfInterfaceID) const = 0; 00952 00958 virtual scfInterfaceID GetInterfaceID (const char *iInterface) = 0; 00959 00966 virtual void Finish () = 0; 00967 00978 virtual iStringArray* QueryClassList (char const* pattern) = 0; 00979 00983 virtual void ScanPluginsPath (const char* path, bool recursive = false, 00984 const char* context = 0) = 0; 00985 00995 virtual bool RegisterPlugin (const char* path) = 0; 00996 }; 00997 00998 SCF_VERSION (iFactory, 0, 0, 1); 00999 SCF_VERSION (iBase, 0, 1, 0); 01000 SCF_VERSION (iSCF, 0, 2, 1); 01001 01002 /* @} */ 01003 01004 #endif // __CSSCF_H__
Generated for Crystal Space by doxygen 1.2.18