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
26namespace structures {
27
28template <class contents> class internal_symbol_indexer;
29template <class contents> class internal_symbol_info;
30template <class contents> class internal_symbol_list;
31
33
34template <class contents>
36{
37public:
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
117private:
118 internal_symbol_list<contents> *_symbol_list;
120
121 internal_symbol_info<contents> *get_index(int index) const;
123};
124
126
127template <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
148template <class contents>
150{
151public:
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
167template <class contents>
175
176template <class contents>
178: public pointer_hash<internal_pointer_hider<contents> >
179{
180public:
182 : pointer_hash<internal_pointer_hider<contents> >(elems) {}
183};
184
186
187// this object maintains the symbol table's contents.
188
189template <class contents>
191: public string_hash<internal_symbol_info<contents> >
192{
193public:
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
205template <class contents>
207: _symbol_list(new internal_symbol_list<contents>(estimated_elements)),
208 _tracker(new internal_symbol_indexer<contents>(estimated_elements))
209{}
210
211template <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
218template <class contents>
220{
221 WHACK(_symbol_list);
222 WHACK(_tracker);
223}
224
225template <class contents>
227{ return _symbol_list->estimated_elements(); }
228
229template <class contents>
230void symbol_table<contents>::rehash(int estimated_elements)
231{
232 _symbol_list->rehash(estimated_elements);
233 _tracker->rehash(estimated_elements);
234}
235
236template <class contents>
238{ rehash(new_elements); }
239
240template <class contents>
242{ return _tracker->ids().elements(); }
243
244template <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) {
255 _symbol_list->add(info->_name, new_info);
258 _tracker->add(new_info, new_track);
259 }
260 }
261 return *this;
262}
263
264template <class contents>
266{
267 _symbol_list->reset();
268 _tracker->reset();
269}
270
271template <class contents>
273{
274 bounds_return(index, 0, symbols() - 1, basis::bogonic<basis::astring>());
275 return get_index(index)->_name;
276}
277
278template <class contents>
280{
281 to_fill.reset();
282 for (int i = 0; i < symbols(); i++)
283 to_fill += get_index(i)->_name;
284}
285
286template <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
294template <class contents>
295const 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
303template <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
312template <class contents>
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
321template <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
333template <class contents>
342
343template <class contents>
344bool 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
363template <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
382template <class contents>
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);
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
402template <class contents>
404{
405 basis::astring dead_name = name(index);
406 return whack(dead_name);
407}
408
409template <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
422template <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
435template <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)
internal_symbol_info< contents > * _held
internal_symbol_info(const contents &content, const basis::astring &name)
A hash table for storing pointers.
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.
basis::outcome retrieve(int index, basis::astring &symbol_name, contents &contains) const
Locates the symbol at position "index" and stores it to the parameters.
symbol_table(int estimated_elements=100)
constructs a symbol table with sufficient size for "estimated_elements".
void names(string_set &to_fill) const
returns the names of all the symbols currently held.
symbol_table & operator=(const symbol_table< contents > &to_copy)
const contents & get(int index) const
named equivalent for the bracket operator.
int estimated_elements() const
returns the number of symbols the table is optimized for.
basis::outcome zap_index(int index)
zaps the entry at the specified index. slower than whack().
const basis::astring & name(int index) const
returns the name held at the "index".
symbol_table(const symbol_table< contents > &to_copy)
contents * find(const basis::astring &name) const
returns the contents held for "name" or NULL_POINTER if it wasn't found.
int dep_find(const basis::astring &name) const
Searches for a symbol by its "name".
void rehash(int estimated_elements)
resizes underlying table to support "estimated_elements".
basis::outcome add(const basis::astring &name, const contents &storage)
Enters a symbol name into the table along with some contents.
contents & operator[](int index)
provides access to the symbol_table's contents at the "index".
contents & use(int index)
named equivalent for the bracket operator.
void hash_appropriately(int estimated_elements)
Resizes the number of table slots to have space for "estimated_elements".
contents * find(const basis::astring &name, basis::string_comparator_function *comparator) const
Specialized search via a comparison method "comparator".
basis::outcome whack(const basis::astring &name)
removes a symbol from the table.
int symbols() const
returns the number of symbols listed in the table.
#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:54
#define bounds_return(value, low, high, to_return)
Verifies that "value" is between "low" and "high", inclusive.
Definition guards.h:48
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)
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.
basis::string_comparator_function * _scf