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 
25 static 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 
38 DeclareWvScatterDict(WvMonikerRegistry, UUID, reg_iid);
39 static WvMonikerRegistryDict *regs;
40 
41 
42 
43 WvMonikerRegistry::WvMonikerRegistry(const UUID &iid)
44  : reg_iid(iid)
45 {
46  DEBUGLOG("WvMonikerRegistry creating.\n");
47  refcount = 0;
48 }
49 
50 
51 WvMonikerRegistry::~WvMonikerRegistry()
52 {
53  DEBUGLOG("WvMonikerRegistry destroying.\n");
54 }
55 
56 
57 void 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 
70 void 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 
87 void *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 
111 WvMonikerRegistry *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 
133 IObject *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 
149 unsigned int WvMonikerRegistry::addRef()
150 {
151  DEBUGLOG("WvMonikerRegistry addRef.\n");
152  return ++refcount;
153 }
154 
155 
156 unsigned 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 
183 WvMonikerBase::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 
194 WvMonikerBase::~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 
205 void *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 }
WvMonikerRegistry
A list for holding moniker-prefix to factory-function mappings.
Definition: wvmonikerregistry.h:18
trim_string
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...
Definition: strutils.cc:59
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
IObject
Definition: IObject.h:65
_GUID
The structure underlying UUIDs.
Definition: uuid.h:94