File: symtab.h

package info (click to toggle)
aegis 4.24.3-3
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 34,056 kB
  • ctags: 12,500
  • sloc: cpp: 178,528; sh: 79,948; makefile: 34,813; yacc: 4,610; perl: 1,499; ansic: 492; awk: 325
file content (478 lines) | stat: -rw-r--r-- 13,648 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
//
//	aegis - project change supervisor
//	Copyright (C) 1994, 2002-2008 Peter Miller.
//
//	This program is free software; you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation; either version 3 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program. If not, see
//	<http://www.gnu.org/licenses/>.
//

#ifndef COMMON_SYMTAB_H
#define COMMON_SYMTAB_H

#include <common/mem.h>
#include <common/nstring.h>

class string_list_ty; // forward
class nstring_list; // forward

/** \addtogroup Symtab
  * \brief Symbols table interface
  * \ingroup Common
  * @{
  */

/**
  * The symtab_ty class is used to represent a symbol table.  All data
  * is referenced through void pointers.  You may wish to use the
  * template wrapper for type safety.
  */
class symtab_ty
{
public:
    /**
      * The destructor.
      * \note it isn't virtual, thou shalt not derive from this class.
      */
    ~symtab_ty();

    /**
      * The constructor.
      *
      * \param suggested_size
      *     You are able to suggest how many rows will be in the table.
      *     It is better to under estimate than overestimate and waste
      *     memory.  Optimal resizing happens automagically.
      */
    symtab_ty(int suggested_size = 5);

    /**
      * The size method may be used to determine how many rows there are
      * in the symbol table.
      */
    size_t size() const { return hash_load; }

    /**
      * The empty method may be used to determine if there symbol table
      * is empty (i.e. there are no rows).
      */
    bool empty() const { return (hash_load == 0); }

    /**
      * The clear method may be used to discard all rows of the symbol
      * table.  It is not an error if the symbol table is already empty.
      *
      * \note
      *     This method has O(n) execution time.
      */
    void clear(void);

    /**
      *	The query method may be used to search for a variable.
      *
      * \param key
      *     The row name to search for.
      *
      * \returns
      *     If the variable has been defined, this method returns the
      *     pointer value assigned.  If the variable has not been
      *     defined, it returns the NULL pointer.
      *
      * \note
      *     This method has O(1) execution time.
      *     This method will eventually be DEPRECATED
      */
    void *query(string_ty *key) const;

    /**
      *	The query method may be used to search for a variable.
      *
      * \param key
      *     The row name to search for.
      *
      * \returns
      *     If the variable has been defined, this method returns the
      *     pointer value assigned.  If the variable has not been
      *     defined, it returns the NULL pointer.
      *
      * \note
      *     This method has O(1) execution time.
      */
    void *query(const nstring &key) const;

    /**
      *	The query method may be used to search for a variable.
      *
      * \param keys
      *     The row names to search for.  The first found will be returned.
      *
      * \returns
      *     If the variable has been defined, this method returns the
      *     pointer value assigned.  If the variable has not been
      *     defined, it returns the NULL pointer.
      */
    void *query(const nstring_list &keys) const;

    /**
      *	The query_fuzzy method may be used to search for a variable.
      *
      * \param key
      *     The row name to search for.
      *
      * \returns
      *     The NULL pointer if there is no row of that name and no row
      *     with a similar name, otherwise returns a pointer to the most
      *     similar name.
      *
      * \note
      *     This method has O(n) execution time.
      *     This method will eventually be DEPRECATED
      */
    string_ty *query_fuzzy(string_ty *key) const;

    /**
      *	The query_fuzzy method may be used to search for a variable.
      *
      * \param key
      *     The row name to search for.
      *
      * \returns
      *     The NULL pointer if there is no row of that name and no row
      *     with a similar name, otherwise returns a pointer to the most
      *     similar name.
      *
      * \note
      *     This method has O(n) execution time.
      */
    nstring query_fuzzy(const nstring &key) const;

    /**
      * The assign method is used to assign a value to a given variable.
      *
      * \param key
      *     They key (usually a variable name or simialar).
      * \param value
      *     The value to be assigned to that name.
      *
      * \note
      *     The key is copied, the value pointed to is not.
      * \note
      *     If there is already a key of that name, the old data will be
      *     discarded, via the reap function, if one has been supplied.
      * \note
      *     This method has O(1) execution time.
      *     This method will eventually be DEPRECATED
      */
    void assign(string_ty *key, void *value);

    /**
      * The assign method is used to assign a value to a given variable.
      *
      * \param key
      *     They key (usually a variable name or simialar).
      * \param value
      *     The value to be assigned to that name.
      *
      * \note
      *     The key is copied, the value pointed to is not.
      * \note
      *     If there is already a key of that name, the old data will be
      *     discarded, via the reap function, if one has been supplied.
      * \note
      *     This method has O(1) execution time.
      */
    void assign(const nstring &key, void *value);

    /**
      * The assign_push function is used to assign a value to a given
      * variable.  Any previous value will be obscured until this one is
      * removed with the remove method.
      *
      * \param key
      *     They key (usually a variable name or simialar).
      * \param value
      *     The value to be assigned to that name.
      *
      * \note
      *     The key is copied, the value pointed to is not.
      * \note
      *     This method has O(1) execution time.
      *     This method will eventually be DEPRECATED
      */
    void assign_push(string_ty *key, void *value);

    /**
      * The assign_push function is used to assign a value to a given
      * variable.  Any previous value will be obscured until this one is
      * removed with the remove method.
      *
      * \param key
      *     They key (usually a variable name or simialar).
      * \param value
      *     The value to be assigned to that name.
      *
      * \note
      *     The key is copied, the value pointed to is not.
      * \note
      *     This method has O(1) execution time.
      */
    void assign_push(const nstring &key, void *value);

    /**
      *	The remove method is used to remove a variable from the symbol table.
      *
      * \param key
      *     The name of the row to be removed.
      *
      * \note
      *    The name is freed, the data is reaped.
      *    (By default, reap does nothing.)
      * \note
      *     This method has O(1) execution time.
      *     This method will eventually be DEPRECATED
      */
    void remove(string_ty *key);

    /**
      *	The remove method is used to remove a variable from the symbol table.
      *
      * \param key
      *     The name of the row to be removed.
      *
      * \note
      *    The name is freed, the data is reaped.
      *    (By default, reap does nothing.)
      * \note
      *     This method has O(1) execution time.
      */
    void remove(const nstring &key);

    /**
      * The dump method is used to dump the contents of the symbol
      * table.
      *
      * \param caption
      *     The caption will be used to indicate why the symbol
      *     table was dumped.
      *
      * \note
      *    This function is only available when symbol DEBUG is defined.
      * \note
      *     This method has O(n) execution time.
      */
    void dump(const char *caption) const;

    /**
      * The keys method may be used to extract the list of row names
      * from the symbol table.
      *
      * \param result
      *     Where to put the row names.  It is cleared before any row
      *     names are placed in it.  It is not sorted.
      *
      * \note
      *     If you have used assign_push method, it is possible to have
      *     duplicates in they list of keys.
      * \note
      *     This method has O(n) execution time.
      *     This method will eventually be DEPRECATED
      */
    void keys(string_list_ty *result) const;

    /**
      * The keys method may be used to extract the list of row names
      * from the symbol table.
      *
      * \param result
      *     Where to put the row names.  It is cleared before any row
      *     names are placed in it.  It is not sorted.
      *
      * \note
      *     If you have used assign_push method, it is possible to have
      *     duplicates in they list of keys.
      * \note
      *     This method has O(n) execution time.
      */
    void keys(nstring_list &result) const;

    typedef void (*callback_t)(const symtab_ty *stp, const nstring &key,
        void *data, void *arg);

    /**
      * The walk method is used to invoke a func tion for every row of
      * the symbol table.
      *
      * \param func
      *     A pointer to the function to be called.
      * \param arg
      *     An extra argument passed to the function.
      *
      * \note
      *     This method has O(n) execution time.
      */
    void walk(callback_t func, void *arg) const;

    typedef void (*reaper_t)(void *);

    /**
      * The set_reap method is used to set the reaping function to be
      * used on the data of row tables when they are remove()ed or
      * assign()ed over.
      */
    void set_reap(reaper_t func) { reap = func; }

    /**
      * The valid method determines whether the symbol table's internal
      * values are self consistent.  Usually only used for debugging.
      */
    bool valid() const;

private:
    /**
      * The split method is used to double the number of buckets in the
      * symbol table, which results in halving the load.  The symbols
      * are then redistributed into the new buckets.
      *
      * \note
      *    It is only sensable to do this when the symbol table load
      *    exceeds some reasonable threshold.  A threshold of 80% is
      *    used.
      * \note
      *     The probablity of another split thus halves every time this
      *     method is called, resulting in overall O(1) behaviour
      *     because (sigma(2 ** -n) == 1).
      */
    void split(void);

    /**
      * The grim reaper.  Default to NULL, i.e. nothing is done.
      */
    reaper_t reap;

    struct row_t
    {
        row_t() : data(0), overflow(0) { }
	nstring key;
	void *data;
	row_t *overflow;
    };

    /**
      * The hash_table instance variable is used to remember the base
      * address of the array of buckets.  On average, there will only be
      * 0.5 to 0.8 rows per bucket.
      */
    row_t **hash_table;

    /**
      * The hash_modulus instance variable is used to remember the size
      * of the array of buckets.  It is always a power of two.
      */
    str_hash_ty hash_modulus;

    /**
      * The hash_mask instance variable is used to remember the bit mask
      * used to place rows into buckets.  Because hash_modulus is always
      * a power of two, this mask will always be one less than the hash
      * modulus; we cache it for efficiency.
      */
    str_hash_ty hash_mask;

    /**
      * The hash_load instance variable is used to remember how many
      * rows are present in the table.
      */
    str_hash_ty hash_load;

    /**
      * The copy constructor.  Do not use.
      */
    symtab_ty(const symtab_ty &);

    /**
      * The assignment operator.  Do not use.
      */
    symtab_ty &operator=(const symtab_ty &);

    friend class symtab_iterator;
};

inline symtab_ty *
symtab_alloc(int n)
{
    // 37 files still use this function
    return new symtab_ty(n);
}

inline void
symtab_free(symtab_ty *stp)
{
    // 21 files still use this function
    delete stp;
}

inline void *
symtab_query(const symtab_ty *stp, string_ty *key)
{
    // 36 files still use this function
    return stp->query(key);
}

inline string_ty *
symtab_query_fuzzy(const symtab_ty *stp, string_ty *key)
{
    // 7 files still use this function
    return stp->query_fuzzy(key);
}

inline void
symtab_assign(symtab_ty *stp, string_ty *key, void *value)
{
    // 39 files still use this function
    stp->assign(key, value);
}

inline DEPRECATED void
symtab_assign_push(symtab_ty *stp, string_ty *key, void *value)
{
    stp->assign_push(key, value);
}

inline void
symtab_delete(symtab_ty *stp, string_ty *key)
{
    // 2 files still use this function
    stp->remove(key);
}

inline DEPRECATED void
symtab_dump(const symtab_ty *stp, const char *caption)
{
    stp->dump(caption);
}

inline DEPRECATED void
symtab_walk(const symtab_ty *stp, symtab_ty::callback_t func, void *arg)
{
    stp->walk(func, arg);
}

inline DEPRECATED void
symtab_keys(const symtab_ty *stp, string_list_ty *result)
{
    stp->keys(result);
}

/** @} */

#endif // COMMON_SYMTAB_H