// // 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 // . // #ifndef COMMON_SYMTAB_H #define COMMON_SYMTAB_H #include #include 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