feisty meow concerns codebase  2.140
symbol_table.h
Go to the documentation of this file.
1 #ifndef SYMBOL_TABLE_CLASS
2 #define SYMBOL_TABLE_CLASS
3 
4 /*****************************************************************************\
5 * *
6 * Name : symbol_table *
7 * Author : Chris Koeritz *
8 * *
9 *******************************************************************************
10 * Copyright (c) 1991-$now By Author. This program is free software; you can *
11 * redistribute it and/or modify it under the terms of the GNU General Public *
12 * License as published by the Free Software Foundation; either version 2 of *
13 * the License or (at your option) any later version. This is online at: *
14 * http://www.fsf.org/copyleft/gpl.html *
15 * Please send any updates to: fred@gruntose.com *
16 \*****************************************************************************/
17 
18 #include "pointer_hash.h"
19 #include "string_hash.h"
20 #include "symbol_table.h"
21 
22 #include <basis/astring.h>
23 #include <basis/functions.h>
24 #include <basis/guards.h>
25 
26 namespace structures {
27 
28 template <class contents> class internal_symbol_indexer;
29 template <class contents> class internal_symbol_info;
30 template <class contents> class internal_symbol_list;
31 
33 
34 template <class contents>
36 {
37 public:
39 
43 
45 
47 
48  int symbols() const;
50 
51  int estimated_elements() const;
53 
56 
59 
61 
62  basis::outcome add(const basis::astring &name, const contents &storage);
64 
68  const basis::astring &name(int index) const;
70 
72  void names(string_set &to_fill) const;
74 
75  contents &operator [] (int index);
77  const contents &operator [] (int index) const;
79 
80  const contents &get(int index) const { return operator[](index); }
82  contents &use(int index) { return operator[](index); }
84 
85  contents *find(const basis::astring &name) const;
87 
88  contents *find(const basis::astring &name,
89  basis::string_comparator_function *comparator) const;
91 
97  int dep_find(const basis::astring &name) const;
99 
103 
106  basis::outcome retrieve(int index, basis::astring &symbol_name, contents &contains) const;
107 
110 
114 
115  void reset(); //<! removes all symbols from the table.
116 
117 private:
118  internal_symbol_list<contents> *_symbol_list;
120 
121  internal_symbol_info<contents> *get_index(int index) const;
123 };
124 
126 
127 template <class contents>
129  const symbol_table<contents> &b);
131 
133 
134 // implementations below...
135 
136 //#define DEBUG_SYMBOL_TABLE
137  // uncomment for noisier debugging.
138 
139 #ifdef DEBUG_SYMBOL_TABLE
140  #undef LOG
141  #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
142 #endif
143 
145 
146 // this structure keeps track of our symbol table elements.
147 
148 template <class contents>
150 {
151 public:
152  contents _content; // the object provided by the user.
153  basis::astring _name; // symbol's name.
154 
155  internal_symbol_info(const contents &content, const basis::astring &name)
156  : _content(content), _name(name) {}
157 };
158 
160 
161 // this is our tracking system that allows us to offer array like services.
162 // each symbol held has an address as one of our wrappers. thus we can
163 // list those addresses in a hash table along with listing the contents
164 // in the main hash table. the pointer_hash gives us a list of ids set, so
165 // we can have some ordering for the items in the table.
166 
167 template <class contents>
169 {
170 public:
172 
174 };
175 
176 template <class contents>
178 : public pointer_hash<internal_pointer_hider<contents> >
179 {
180 public:
182  : pointer_hash<internal_pointer_hider<contents> >(elems) {}
183 };
184 
186 
187 // this object maintains the symbol table's contents.
188 
189 template <class contents>
191 : public string_hash<internal_symbol_info<contents> >
192 {
193 public:
195  : string_hash<internal_symbol_info<contents> >(elems) {}
196 };
197 
199 
200 // the main algorithms class implementing the external interface.
201 
202 #undef static_class_name
203 #define static_class_name() "symbol_table"
204 
205 template <class contents>
207 : _symbol_list(new internal_symbol_list<contents>(estimated_elements)),
208  _tracker(new internal_symbol_indexer<contents>(estimated_elements))
209 {}
210 
211 template <class contents>
213 : _symbol_list(new internal_symbol_list<contents>
214  (to_copy._symbol_list->estimated_elements())),
215  _tracker(new internal_symbol_indexer<contents>(to_copy.estimated_elements()))
216 { *this = to_copy; }
217 
218 template <class contents>
220 {
221  WHACK(_symbol_list);
222  WHACK(_tracker);
223 }
224 
225 template <class contents>
227 { return _symbol_list->estimated_elements(); }
228 
229 template <class contents>
230 void symbol_table<contents>::rehash(int estimated_elements)
231 {
232  _symbol_list->rehash(estimated_elements);
233  _tracker->rehash(estimated_elements);
234 }
235 
236 template <class contents>
238 { rehash(new_elements); }
239 
240 template <class contents>
242 { return _tracker->ids().elements(); }
243 
244 template <class contents>
246  operator =(const symbol_table &to_copy)
247 {
248  if (this == &to_copy) return *this;
249  reset();
250  for (int i = 0; i < to_copy.symbols(); i++) {
251  internal_symbol_info<contents> *info = to_copy.get_index(i);
252  if (info) {
254  = new internal_symbol_info<contents>(*info);
255  _symbol_list->add(info->_name, new_info);
257  new internal_pointer_hider<contents>(new_info);
258  _tracker->add(new_info, new_track);
259  }
260  }
261  return *this;
262 }
263 
264 template <class contents>
266 {
267  _symbol_list->reset();
268  _tracker->reset();
269 }
270 
271 template <class contents>
273 {
274  bounds_return(index, 0, symbols() - 1, basis::bogonic<basis::astring>());
275  return get_index(index)->_name;
276 }
277 
278 template <class contents>
280 {
281  to_fill.reset();
282  for (int i = 0; i < symbols(); i++)
283  to_fill += get_index(i)->_name;
284 }
285 
286 template <class contents>
288  get_index(int index) const
289 {
290  bounds_return(index, 0, symbols() - 1, NULL_POINTER);
291  return _tracker->find(_tracker->ids()[index])->_held;
292 }
293 
294 template <class contents>
295 const contents &symbol_table<contents>::operator [] (int index) const
296 {
297  bounds_return(index, 0, symbols() - 1, basis::bogonic<contents>());
298  internal_symbol_info<contents> *found = get_index(index);
299  if (!found) return basis::bogonic<contents>();
300  return found->_content;
301 }
302 
303 template <class contents>
305 {
306  bounds_return(index, 0, symbols() - 1, basis::bogonic<contents>());
307  internal_symbol_info<contents> *found = get_index(index);
308  if (!found) return basis::bogonic<contents>();
309  return found->_content;
310 }
311 
312 template <class contents>
313 contents *symbol_table<contents>::find(const basis::astring &name) const
314 {
315 // FUNCDEF("find [name]");
316  internal_symbol_info<contents> *found = _symbol_list->find(name);
317  if (!found) return NULL_POINTER;
318  return &found->_content;
319 }
320 
321 template <class contents>
323 {
324  internal_symbol_info<contents> *entry = _symbol_list->find(name);
325  if (!entry) return basis::common::NOT_FOUND;
326 
327  for (int i = 0; i < symbols(); i++) {
328  if (_tracker->ids()[i] == entry) return i;
329  }
330  return basis::common::NOT_FOUND; // this is bad; it should have been found.
331 }
332 
333 template <class contents>
335 {
337  contents *_found;
339 
341 };
342 
343 template <class contents>
344 bool sym_tab_finder_apply(const basis::astring &key, contents &current,
345  void *data_link)
346 {
347 #ifdef DEBUG_SYMBOL_TABLE
348  FUNCDEF("sym_tab_finder_apply");
349 #endif
351  = (sym_tab_apply_data<contents> *)data_link;
352 #ifdef DEBUG_SYMBOL_TABLE
353  LOG(basis::astring(" checking ") + key);
354 #endif
355  bool equals = package->_scf(key, package->_to_find);
356  if (equals) {
357  package->_found = &current;
358  return false; // done.
359  }
360  return true; // keep going.
361 }
362 
363 template <class contents>
365  basis::string_comparator_function *comparator) const
366 {
367 #ifdef DEBUG_SYMBOL_TABLE
368  FUNCDEF("find [comparator]");
369 #endif
370  if (!comparator) return find(name); // devolve to simplified call.
371 #ifdef DEBUG_SYMBOL_TABLE
372  LOG(basis::astring("looking for ") + name);
373 #endif
375  pack._to_find = name;
376  pack._scf = comparator;
377  // iterate across all the items in the hash.
378  _symbol_list->apply(sym_tab_finder_apply, &pack);
379  return pack._found;
380 }
381 
382 template <class contents>
383 basis::outcome symbol_table<contents>::add(const basis::astring &name, const contents &to_add)
384 {
385 // FUNCDEF("add");
386  internal_symbol_info<contents> *found = _symbol_list->find(name);
387  if (!found) {
388  // not there already.
390  = new internal_symbol_info<contents>(to_add, name);
391  _symbol_list->add(name, new_item);
393  new internal_pointer_hider<contents>(new_item);
394  _tracker->add(new_item, new_track);
395  return basis::common::IS_NEW;
396  }
397  // overwrite the existing contents.
398  found->_content = to_add;
399  return basis::common::EXISTING;
400 }
401 
402 template <class contents>
404 {
405  basis::astring dead_name = name(index);
406  return whack(dead_name);
407 }
408 
409 template <class contents>
411 {
412 // FUNCDEF("whack");
413  internal_symbol_info<contents> *sep_ind = _symbol_list->find(name);
414  // we need this pointer so we can find the tracker entry easily.
415  bool found_it = _symbol_list->zap(name);
416  if (found_it) {
417  _tracker->zap(sep_ind);
418  }
419  return found_it? basis::common::OKAY : basis::common::NOT_FOUND;
420 }
421 
422 template <class contents>
424  contents &got) const
425 {
426  bounds_return(index, 0, symbols() - 1, basis::common::NOT_FOUND);
427  internal_symbol_info<contents> *found = get_index(index);
428  name = found->_name;
429  got = found->_content;
430  return basis::common::OKAY;
431 }
432 
434 
435 template <class contents>
437  const symbol_table<contents> &b)
438 {
439 // FUNCDEF("symbol_table_compare");
440 
441  string_set names_a;
442  a.names(names_a);
443  string_set names_b;
444  b.names(names_b);
445  if (names_a != names_b) return false;
446 
447  for (int i = 0; i < names_a.elements(); i++) {
448  const basis::astring &current_key = names_a[i];
449  const contents *a_value = a.find(current_key);
450  const contents *b_value = b.find(current_key);
451  if (!a_value || !b_value) continue; // not good.
452  if (*a_value != *b_value) return false;
453  }
454  return true;
455 }
456 
457 #ifdef DEBUG_SYMBOL_TABLE
458  #undef LOG
459 #endif
460 
461 #undef static_class_name
462 
463 } //namespace.
464 
465 #endif
466 
467 
#define LOG(s)
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition: array.h:349
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
Outcomes describe the state of completion for an operation.
Definition: outcome.h:31
internal_pointer_hider(internal_symbol_info< contents > *held)
Definition: symbol_table.h:173
internal_symbol_info< contents > * _held
Definition: symbol_table.h:171
internal_symbol_info(const contents &content, const basis::astring &name)
Definition: symbol_table.h:155
A hash table for storing pointers.
Definition: pointer_hash.h:38
int elements() const
Returns the number of elements in this set.
Definition: set.h:47
Implements a hash table indexed on character strings.
Definition: string_hash.h:29
A simple object that wraps a templated set of strings.
Definition: set.h:168
Maintains a list of names, where each name has a type and some contents.
Definition: symbol_table.h:36
basis::outcome retrieve(int index, basis::astring &symbol_name, contents &contains) const
Locates the symbol at position "index" and stores it to the parameters.
Definition: symbol_table.h:423
symbol_table(int estimated_elements=100)
constructs a symbol table with sufficient size for "estimated_elements".
Definition: symbol_table.h:206
void names(string_set &to_fill) const
returns the names of all the symbols currently held.
Definition: symbol_table.h:279
symbol_table & operator=(const symbol_table< contents > &to_copy)
Definition: symbol_table.h:246
int estimated_elements() const
returns the number of symbols the table is optimized for.
Definition: symbol_table.h:226
basis::outcome zap_index(int index)
zaps the entry at the specified index. slower than whack().
Definition: symbol_table.h:403
const basis::astring & name(int index) const
returns the name held at the "index".
Definition: symbol_table.h:272
symbol_table(const symbol_table< contents > &to_copy)
Definition: symbol_table.h:212
contents * find(const basis::astring &name) const
returns the contents held for "name" or NULL_POINTER if it wasn't found.
Definition: symbol_table.h:313
int dep_find(const basis::astring &name) const
Searches for a symbol by its "name".
Definition: symbol_table.h:322
contents & use(int index)
named equivalent for the bracket operator.
Definition: symbol_table.h:82
void rehash(int estimated_elements)
resizes underlying table to support "estimated_elements".
Definition: symbol_table.h:230
basis::outcome add(const basis::astring &name, const contents &storage)
Enters a symbol name into the table along with some contents.
Definition: symbol_table.h:383
contents & operator[](int index)
provides access to the symbol_table's contents at the "index".
Definition: symbol_table.h:304
void hash_appropriately(int estimated_elements)
Resizes the number of table slots to have space for "estimated_elements".
Definition: symbol_table.h:237
contents * find(const basis::astring &name, basis::string_comparator_function *comparator) const
Specialized search via a comparison method "comparator".
Definition: symbol_table.h:364
basis::outcome whack(const basis::astring &name)
removes a symbol from the table.
Definition: symbol_table.h:410
int symbols() const
returns the number of symbols listed in the table.
Definition: symbol_table.h:241
const contents & get(int index) const
named equivalent for the bracket operator.
Definition: symbol_table.h:80
#define NULL_POINTER
The value representing a pointer to nothing.
Definition: definitions.h:32
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
#define bounds_return(value, low, high, to_return)
Verifies that "value" is between "low" and "high", inclusive.
Definition: guards.h:48
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition: functions.h:121
bool string_comparator_function(const astring &a, const astring &b)
returns true if the strings "a" and "b" are considered equal.
Definition: astring.h:449
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
bool sym_tab_finder_apply(const basis::astring &key, contents &current, void *data_link)
Definition: symbol_table.h:344
void pack(basis::byte_array &packed_form, const set< contents > &to_pack)
provides a way to pack any set that stores packable objects.
Definition: set.h:131
bool symbol_table_compare(const symbol_table< contents > &a, const symbol_table< contents > &b)
returns true if table "a" and table "b" have the same contents.
Definition: symbol_table.h:436
basis::string_comparator_function * _scf
Definition: symbol_table.h:336