WvStreams
uniconfgen.cc
1 /*
2  * Worldvisions Weaver Software:
3  * Copyright (C) 2002 Net Integration Technologies, Inc.
4  *
5  * An abstract data container that backs a UniConf tree.
6  */
7 #include "uniconfgen.h"
8 #include "strutils.h"
9 
10 // FIXME: interfaces (IUniConfGen) shouldn't have implementations!
11 IUniConfGen::~IUniConfGen()
12 {
13 }
14 
19 
21 {
22  hold_nesting = 0;
23 }
24 
25 
27 {
28  assert(cblist.isempty());
29 }
30 
31 
33 {
34  hold_nesting++;
35 }
36 
37 
39 {
40  assert(hold_nesting > 0);
41  if (hold_nesting == 1)
42  flush_delta();
43  hold_nesting--;
44 }
45 
46 
48 {
49  deltas.zap();
50 }
51 
52 
54 {
55  UniConfPairList::Iter it(deltas);
56  for (;;)
57  {
58  it.rewind();
59  if (! it.next())
60  break;
61 
62  UniConfKey key((*it).key());
63  WvString value((*it).value());
64 
65  it.xunlink();
66  dispatch_delta(key, value);
67  }
68 }
69 
70 
71 void UniConfGen::dispatch_delta(const UniConfKey &key, WvStringParm value)
72 {
73  cblist(key, value);
74 }
75 
76 
77 void UniConfGen::delta(const UniConfKey &key, WvStringParm value)
78 {
79  if (hold_nesting == 0)
80  {
81  // not nested, dispatch immediately
82  dispatch_delta(key, value);
83  }
84  else
85  {
86  hold_delta();
87  deltas.add(new UniConfPair(key, value), true);
88  unhold_delta();
89  }
90 }
91 
92 
93 void UniConfGen::setv_naive(const UniConfPairList &pairs)
94 {
95  UniConfPairList::Iter pair(pairs);
96  for (pair.rewind(); pair.next(); )
97  set(pair->key(), pair->value());
98 }
99 
100 
102 {
103  bool children = false;
104 
105  hold_delta();
106 
107  Iter *it = iterator(key);
108  if (it)
109  {
110  it->rewind();
111  if (it->next()) children = true;
112  delete it;
113  }
114 
115  unhold_delta();
116  return children;
117 }
118 
119 
121 {
122  return !get(key).isnull();
123 }
124 
125 
126 int UniConfGen::str2int(WvStringParm value, int defvalue) const
127 {
128  // also recognize bool strings as integers
129  const char *strs[] = {
130  "true", "yes", "on", "enabled",
131  "false", "no", "off", "disabled"
132  };
133  const size_t numtruestrs = 4;
134 
135  if (!value.isnull())
136  {
137  // try to recognize an integer
138  char *end;
139  int num = strtol(value.cstr(), &end, 0);
140  if (end != value.cstr())
141  return num; // was a valid integer
142 
143  // try to recognize a special string
144  for (size_t i = 0; i < sizeof(strs) / sizeof(const char*); ++i)
145  if (strcasecmp(value, strs[i]) == 0)
146  return i < numtruestrs;
147  }
148  return defvalue;
149 }
150 
151 
153 {
154  return true;
155 }
156 
157 
158 void UniConfGen::add_callback(void *cookie,
159  const UniConfGenCallback &callback)
160 {
161  cblist.add(callback, cookie);
162 }
163 
164 
165 void UniConfGen::del_callback(void *cookie)
166 {
167  cblist.del(cookie);
168 }
169 
170 
171 
172 class _UniConfGenRecursiveIter : public IUniConfGen::Iter
173 {
175  IUniConfGen *gen;
176  UniConfKey top, current;
177  bool sub_next;
178 
179 public:
181  : top(_top)
182  {
183  gen = _gen;
184  sub_next = false;
185  }
186 
187  virtual ~_UniConfGenRecursiveIter() { }
188 
189  virtual void rewind()
190  {
191  current = "";
192  sub_next = false;
193  itlist.zap();
194 
195  Iter *subi = gen->iterator(top);
196  if (subi)
197  {
198  subi->rewind();
199  itlist.prepend(subi, true);
200  }
201  }
202 
203  virtual bool next()
204  {
205  //assert(!itlist.isempty()); // trying to seek past the end is illegal!
206 
207  if (sub_next)
208  {
209  sub_next = false;
210 
211  UniConfKey subkey(itlist.first()->key());
212  UniConfKey newkey(current, subkey);
213  //fprintf(stderr, "subiter: '%s'\n", newkey.cstr());
214  Iter *newsub = gen->iterator(UniConfKey(top, newkey));
215  if (newsub)
216  {
217  current.append(subkey);
218  //fprintf(stderr, "current is now: '%s'\n", current.cstr());
219  newsub->rewind();
220  itlist.prepend(newsub, true);
221  }
222  }
223 
225  for (i.rewind(); i.next(); )
226  {
227  if (i->next()) // NOTE: not the same as i.next()
228  {
229  // set up so next time, we go into its subtree
230  sub_next = true;
231  return true;
232  }
233 
234  // otherwise, this iterator is empty; move up the tree
235  current = current.removelast();
236  //fprintf(stderr, "current is now: '%s'\n", current.cstr());
237  i.xunlink();
238  }
239 
240  // all done!
241  return false;
242  }
243 
244  virtual UniConfKey key() const
245  {
246  //fprintf(stderr, "current is now: '%s'\n", current.cstr());
247  if (!itlist.isempty())
248  return UniConfKey(current, itlist.first()->key());
249  else
250  return current;
251  }
252 
253  virtual WvString value() const
254  {
255  return gen->get(UniConfKey(top, key()));
256  }
257 };
258 
259 
261 {
262  return new _UniConfGenRecursiveIter(this, key);
263 }
264 
265 
UniConfGen::isok
virtual bool isok()
Determines if the generator is usable and working properly.
Definition: uniconfgen.cc:152
UniConfGen::dispatch_delta
void dispatch_delta(const UniConfKey &key, WvStringParm value)
Immediately sends notification that a key has possibly changed.
Definition: uniconfgen.cc:71
UniConfGen::~UniConfGen
virtual ~UniConfGen()
Destroys the UniConfGen and may discard uncommitted data.
Definition: uniconfgen.cc:26
IUniConfGen::get
virtual WvString get(const UniConfKey &key)=0
Fetches a string value for a key from the registry.
UniConfKey::removelast
UniConfKey removelast(int n=1) const
Returns the path formed by removing the last n segments of this path.
Definition: uniconfkey.h:346
UUID_MAP_ENTRY
#define UUID_MAP_ENTRY(iface)
Add an entry to an interface map.
Definition: utils.h:68
_UniConfGenRecursiveIter
Definition: uniconfgen.cc:172
UniConfGen::str2int
virtual int str2int(WvStringParm s, int defvalue) const
Converts a string to an integer.
Definition: uniconfgen.cc:126
UUID_MAP_BEGIN
#define UUID_MAP_BEGIN(component)
Start the interface map for "component".
Definition: utils.h:63
UniConfGen::recursiveiterator
virtual Iter * recursiveiterator(const UniConfKey &key)
Like iterator(), but the returned iterator is recursive, that is, it will return children of the imme...
Definition: uniconfgen.cc:260
UniConfGen::get
virtual WvString get(const UniConfKey &key)=0
Fetches a string value for a key from the registry.
WvList::first
T * first() const
Returns a pointer to the first element in the linked list.
Definition: wvlinklist.h:241
UniConfGen::unhold_delta
void unhold_delta()
Resumes notifications when each hold_delta() has been matched.
Definition: uniconfgen.cc:38
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
WvListBase::isempty
bool isempty() const
Quickly determines if the list is empty.
Definition: wvlinklist.h:62
IUniConfGen
An abstract data container that backs a UniConf tree.
Definition: uniconfgen.h:39
WvFastString::isnull
bool isnull() const
returns true if this string is null
Definition: wvstring.h:290
UniConfKey
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
Definition: uniconfkey.h:38
UniConfGen::set
virtual void set(const UniConfKey &key, WvStringParm value)=0
Stores a string value for a key into the registry.
UUID_MAP_END
#define UUID_MAP_END
Marks the end of an interface map.
Definition: utils.h:80
UniConfGen::haschildren
virtual bool haschildren(const UniConfKey &key)
Returns true if a key has children.
Definition: uniconfgen.cc:101
UniConfGen::delta
void delta(const UniConfKey &key, WvStringParm value)
Call this when a key's value or children have possibly changed.
Definition: uniconfgen.cc:77
IObject
Definition: IObject.h:65
UniConfGen::clear_delta
void clear_delta()
Clears the list of pending notifications without sending them.
Definition: uniconfgen.cc:47
UniConfGen
A default implementation of IUniConfGen, providing various handy features that save trouble when impl...
Definition: uniconfgen.h:199
UniConfGen::Iter::rewind
virtual void rewind()=0
Rewinds the iterator.
WvList::zap
void zap(bool destroy=true)
Clears the linked list.
Definition: wvlinklist.h:228
IUniConfGen::iterator
virtual Iter * iterator(const UniConfKey &key)=0
Returns an iterator over the children of the specified key.
UniConfGen::Iter::next
virtual bool next()=0
Seeks to the next element in the sequence.
UniConfGen::flush_delta
void flush_delta()
Flushes the list of pending notifications by sending them.
Definition: uniconfgen.cc:53
UniConfGen::iterator
virtual Iter * iterator(const UniConfKey &key)=0
Returns an iterator over the children of the specified key.
UniConfGen::add_callback
virtual void add_callback(void *cookie, const UniConfGenCallback &callback)
Adds a callback for change notification.
Definition: uniconfgen.cc:158
WvList< IUniConfGen::Iter >
UniConfGen::UniConfGen
UniConfGen()
Creates a UniConfGen object.
Definition: uniconfgen.cc:20
UniConfPair
Represents a simple key-value pair.
Definition: uniconfpair.h:16
UniConfGen::del_callback
virtual void del_callback(void *cookie)
Removes a callback for change notification.
Definition: uniconfgen.cc:165
UniConfGen::hold_delta
void hold_delta()
Pauses notifications until matched with a call to unhold_delta().
Definition: uniconfgen.cc:32
UniConfKey::append
void append(const UniConfKey &other)
Appends a path to this path.
Definition: uniconfkey.cc:130
UniConfGen::exists
virtual bool exists(const UniConfKey &key)
Without fetching its value, returns true if a key exists.
Definition: uniconfgen.cc:120
WvList::prepend
void prepend(T *data, bool autofree, const char *id=NULL)
Prepends the element to the beginning of the list.
Definition: wvlinklist.h:293
UniConfGen::Iter
An abstract iterator over keys and values in a generator.
Definition: uniconfgen.h:323