WvStreams
wvmoniker.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Support for monikers, which are strings that you can pass to a magic
6 * factory to get objects supporting a particular interface. See wvmoniker.h.
7 */
8#include "wvmonikerregistry.h"
9#include "strutils.h"
10#include <wvassert.h>
11#include <stdio.h>
12#include "wvscatterhash.h"
13
14#if 0
15# define DEBUGLOG(fmt, args...) fprintf(stderr, fmt, ## args)
16#else
17#ifndef _MSC_VER
18# define DEBUGLOG(fmt, args...)
19#else // MS Visual C++ doesn't support varags preproc macros
20# define DEBUGLOG
21#endif
22#endif
23
24
25static unsigned WvHash(const UUID &_uuid)
26{
27 unsigned val = 0;
28 unsigned int *uuid = (unsigned int *)&_uuid;
29 int max = sizeof(UUID)/sizeof(*uuid);
30
31 for (int count = 0; count < max; count++)
32 val += uuid[count];
33
34 return val;
35}
36
37
38DeclareWvScatterDict(WvMonikerRegistry, UUID, reg_iid);
39static WvMonikerRegistryDict *regs;
40
41
42
43WvMonikerRegistry::WvMonikerRegistry(const UUID &iid)
44 : reg_iid(iid)
45{
46 DEBUGLOG("WvMonikerRegistry creating.\n");
47 refcount = 0;
48}
49
50
51WvMonikerRegistry::~WvMonikerRegistry()
52{
53 DEBUGLOG("WvMonikerRegistry destroying.\n");
54}
55
56
57void WvMonikerRegistry::add(WvStringParm id, WvMonikerCreateFunc *func,
58 const bool override)
59{
60 DEBUGLOG("WvMonikerRegistry register(%s).\n", id.cstr());
61 if (!override) {
62 RegistrationList::Iter i(list);
63 for (i.rewind(); i.next(); )
64 assert(i.ptr()->id != id); //no duplicates without override
65 }
66 list.prepend(new Registration(id, func), true);
67}
68
69
70void WvMonikerRegistry::del(WvStringParm id)
71{
72 DEBUGLOG("WvMonikerRegistry unregister(%s).\n", id.cstr());
73 RegistrationList::Iter i(list);
74 for (i.rewind(); i.next(); )
75 {
76 if (i.ptr()->id == id) {
77 i.unlink();
78 return;
79 }
80 }
81
82 //We should never get here, as we should never be removing elements which don't exist
83 assert(false);
84}
85
86
87void *WvMonikerRegistry::create(WvStringParm _s, IObject *obj)
88{
89 WvString t(_s);
90 WvString s(trim_string(t.edit()));
91
92 char *cptr = strchr(s.edit(), ':');
93 if (cptr)
94 *cptr++ = 0;
95 else
96 cptr = (char*)"";
97
98 DEBUGLOG("WvMonikerRegistry create object ('%s' '%s').\n", s.cstr(), cptr);
99
100 RegistrationList::Iter i(list);
101 for (i.rewind(); i.next(); )
102 {
103 if (i.ptr()->id == s)
104 return i.ptr()->func(cptr, obj);
105 }
106
107 return NULL;
108}
109
110
111WvMonikerRegistry *WvMonikerRegistry::find_reg(const UUID &iid)
112{
113 DEBUGLOG("WvMonikerRegistry find_reg.\n");
114
115 if (!regs)
116 regs = new WvMonikerRegistryDict(10);
117
118 WvMonikerRegistry *reg = (*regs)[iid];
119
120 if (!reg)
121 {
122 // we have to make one!
123 reg = new WvMonikerRegistry(iid);
124 regs->add(reg, true);
125 reg->addRef(); // one reference for being in the list at all
126 }
127
128 reg->addRef();
129 return reg;
130}
131
132
133IObject *WvMonikerRegistry::getInterface(const UUID &uuid)
134{
135#if 0
136 if (uuid.equals(IObject_IID))
137 {
138 addRef();
139 return this;
140 }
141#endif
142
143 // we don't really support any interfaces for now.
144
145 return 0;
146}
147
148
149unsigned int WvMonikerRegistry::addRef()
150{
151 DEBUGLOG("WvMonikerRegistry addRef.\n");
152 return ++refcount;
153}
154
155
156unsigned int WvMonikerRegistry::release()
157{
158 DEBUGLOG("WvMonikerRegistry release.\n");
159
160 if (--refcount > 1)
161 return refcount;
162
163 if (refcount == 1)
164 {
165 // the list has one reference to us, but it's no longer needed.
166 // Note: remove() will delete this object!
167 regs->remove(this);
168 if (regs->isempty())
169 {
170 delete regs;
171 regs = NULL;
172 }
173 return 0;
174 }
175
176 /* protect against re-entering the destructor */
177 refcount = 1;
178 delete this;
179 return 0;
180}
181
182
183WvMonikerBase::WvMonikerBase(const UUID &iid, WvStringParm _id,
184 WvMonikerCreateFunc *func, const bool override)
185 : id(_id)
186{
187 DEBUGLOG("WvMoniker creating(%s).\n", id.cstr());
188 reg = WvMonikerRegistry::find_reg(iid);
189 if (reg)
190 reg->add(id, func, override);
191}
192
193
194WvMonikerBase::~WvMonikerBase()
195{
196 DEBUGLOG("WvMoniker destroying(%s).\n", id.cstr());
197 if (reg)
198 {
199 reg->del(id);
200 WVRELEASE(reg);
201 }
202}
203
204
205void *wvcreate(const UUID &iid, WvStringParm moniker, IObject *obj)
206{
207 assert(!moniker.isnull());
208 // fprintf(stderr, "wvcreate: Looking for '%s'\n", moniker.cstr());
209 WvMonikerRegistry *reg = WvMonikerRegistry::find_reg(iid);
210 if (reg)
211 {
212 void *ret = reg->create(moniker, obj);
213 WVRELEASE(reg);
214 return ret;
215 }
216 else
217 return NULL;
218}
The basic interface which is included by all other XPLC interfaces and objects.
Definition: IObject.h:65
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition: wvstring.h:94
bool isnull() const
returns true if this string is null
Definition: wvstring.h:290
A list for holding moniker-prefix to factory-function mappings.
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:330
The structure underlying UUIDs.
Definition: uuid.h:94
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...
Definition: strutils.cc:59