WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * Support for monikers, which are strings that you can pass to a magic 00006 * factory to get objects supporting a particular interface. See wvmoniker.h. 00007 */ 00008 #include "wvmonikerregistry.h" 00009 #include "strutils.h" 00010 #include <wvassert.h> 00011 #include <stdio.h> 00012 #include "wvscatterhash.h" 00013 00014 #if 0 00015 # define DEBUGLOG(fmt, args...) fprintf(stderr, fmt, ## args) 00016 #else 00017 #ifndef _MSC_VER 00018 # define DEBUGLOG(fmt, args...) 00019 #else // MS Visual C++ doesn't support varags preproc macros 00020 # define DEBUGLOG 00021 #endif 00022 #endif 00023 00024 00025 static unsigned WvHash(const UUID &_uuid) 00026 { 00027 unsigned val = 0; 00028 unsigned int *uuid = (unsigned int *)&_uuid; 00029 int max = sizeof(UUID)/sizeof(*uuid); 00030 00031 for (int count = 0; count < max; count++) 00032 val += uuid[count]; 00033 00034 return val; 00035 } 00036 00037 00038 DeclareWvScatterDict(WvMonikerRegistry, UUID, reg_iid); 00039 static WvMonikerRegistryDict *regs; 00040 00041 00042 00043 WvMonikerRegistry::WvMonikerRegistry(const UUID &iid) 00044 : reg_iid(iid) 00045 { 00046 DEBUGLOG("WvMonikerRegistry creating.\n"); 00047 refcount = 0; 00048 } 00049 00050 00051 WvMonikerRegistry::~WvMonikerRegistry() 00052 { 00053 DEBUGLOG("WvMonikerRegistry destroying.\n"); 00054 } 00055 00056 00057 void WvMonikerRegistry::add(WvStringParm id, WvMonikerCreateFunc *func, 00058 const bool override) 00059 { 00060 DEBUGLOG("WvMonikerRegistry register(%s).\n", id.cstr()); 00061 if (!override) { 00062 RegistrationList::Iter i(list); 00063 for (i.rewind(); i.next(); ) 00064 assert(i.ptr()->id != id); //no duplicates without override 00065 } 00066 list.prepend(new Registration(id, func), true); 00067 } 00068 00069 00070 void WvMonikerRegistry::del(WvStringParm id) 00071 { 00072 DEBUGLOG("WvMonikerRegistry unregister(%s).\n", id.cstr()); 00073 RegistrationList::Iter i(list); 00074 for (i.rewind(); i.next(); ) 00075 { 00076 if (i.ptr()->id == id) { 00077 i.unlink(); 00078 return; 00079 } 00080 } 00081 00082 //We should never get here, as we should never be removing elements which don't exist 00083 assert(false); 00084 } 00085 00086 00087 void *WvMonikerRegistry::create(WvStringParm _s, IObject *obj) 00088 { 00089 WvString t(_s); 00090 WvString s(trim_string(t.edit())); 00091 00092 char *cptr = strchr(s.edit(), ':'); 00093 if (cptr) 00094 *cptr++ = 0; 00095 else 00096 cptr = (char*)""; 00097 00098 DEBUGLOG("WvMonikerRegistry create object ('%s' '%s').\n", s.cstr(), cptr); 00099 00100 RegistrationList::Iter i(list); 00101 for (i.rewind(); i.next(); ) 00102 { 00103 if (i.ptr()->id == s) 00104 return i.ptr()->func(cptr, obj); 00105 } 00106 00107 return NULL; 00108 } 00109 00110 00111 WvMonikerRegistry *WvMonikerRegistry::find_reg(const UUID &iid) 00112 { 00113 DEBUGLOG("WvMonikerRegistry find_reg.\n"); 00114 00115 if (!regs) 00116 regs = new WvMonikerRegistryDict(10); 00117 00118 WvMonikerRegistry *reg = (*regs)[iid]; 00119 00120 if (!reg) 00121 { 00122 // we have to make one! 00123 reg = new WvMonikerRegistry(iid); 00124 regs->add(reg, true); 00125 reg->addRef(); // one reference for being in the list at all 00126 } 00127 00128 reg->addRef(); 00129 return reg; 00130 } 00131 00132 00133 IObject *WvMonikerRegistry::getInterface(const UUID &uuid) 00134 { 00135 #if 0 00136 if (uuid.equals(IObject_IID)) 00137 { 00138 addRef(); 00139 return this; 00140 } 00141 #endif 00142 00143 // we don't really support any interfaces for now. 00144 00145 return 0; 00146 } 00147 00148 00149 unsigned int WvMonikerRegistry::addRef() 00150 { 00151 DEBUGLOG("WvMonikerRegistry addRef.\n"); 00152 return ++refcount; 00153 } 00154 00155 00156 unsigned int WvMonikerRegistry::release() 00157 { 00158 DEBUGLOG("WvMonikerRegistry release.\n"); 00159 00160 if (--refcount > 1) 00161 return refcount; 00162 00163 if (refcount == 1) 00164 { 00165 // the list has one reference to us, but it's no longer needed. 00166 // Note: remove() will delete this object! 00167 regs->remove(this); 00168 if (regs->isempty()) 00169 { 00170 delete regs; 00171 regs = NULL; 00172 } 00173 return 0; 00174 } 00175 00176 /* protect against re-entering the destructor */ 00177 refcount = 1; 00178 delete this; 00179 return 0; 00180 } 00181 00182 00183 WvMonikerBase::WvMonikerBase(const UUID &iid, WvStringParm _id, 00184 WvMonikerCreateFunc *func, const bool override) 00185 : id(_id) 00186 { 00187 DEBUGLOG("WvMoniker creating(%s).\n", id.cstr()); 00188 reg = WvMonikerRegistry::find_reg(iid); 00189 if (reg) 00190 reg->add(id, func, override); 00191 } 00192 00193 00194 WvMonikerBase::~WvMonikerBase() 00195 { 00196 DEBUGLOG("WvMoniker destroying(%s).\n", id.cstr()); 00197 if (reg) 00198 { 00199 reg->del(id); 00200 WVRELEASE(reg); 00201 } 00202 } 00203 00204 00205 void *wvcreate(const UUID &iid, WvStringParm moniker, IObject *obj) 00206 { 00207 assert(!moniker.isnull()); 00208 // fprintf(stderr, "wvcreate: Looking for '%s'\n", moniker.cstr()); 00209 WvMonikerRegistry *reg = WvMonikerRegistry::find_reg(iid); 00210 if (reg) 00211 { 00212 void *ret = reg->create(moniker, obj); 00213 WVRELEASE(reg); 00214 return ret; 00215 } 00216 else 00217 return NULL; 00218 }