Jabber WindowGram Client (JWGC)

Introduction Screenshots Installation Downloads
Documentation Browse Source Resources Project Site

Stable Version
-none-

Latest Version
beta5



Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

string_dictionary.c

Go to the documentation of this file.
00001 /*
00002  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
00003  *      For copying and distribution information, see the file
00004  *      "mit-copyright.h".
00005  *
00006  *      Modified for jwgc by Daniel Henninger.
00007  */
00008 
00009 #include "mit-copyright.h"
00010 
00011 /*
00012  * dictionary - a module implementing a generic dictionary.  That is,
00013  *              any type can be used for the values that keys are bound to.
00014  *              Keys are always strings.
00015  *
00016  * Overview:
00017  *
00018  *        A dictionary is a set of bindings which bind values of some
00019  *    type (this type is the generic parameter of the dictionary) to
00020  *    strings.  At most one value can be bound to any one string.
00021  *    The value that a string is bound to can be changed later.
00022  *    Bindings can also be deleted later.  It is also possible to
00023  *    enumerate all of the bindings in a dictionary.  Dictionarys
00024  *    are heap based and must be created & destroyed accordingly.
00025  *
00026  *    Note: This module assumes that malloc NEVER returns 0 for reasonable
00027  *          requests.  It is the users responsibility to either ensure that
00028  *          this happens or supply a version of malloc with error
00029  *          handling.
00030  *
00031  *    Dictionarys are mutable.
00032  *
00033  * Implementation:
00034  *
00035  *        A standard chaining hash table is used to implement dictionarys.
00036  *    Each dictionary has an associated size (# of slots), allowing
00037  *    different size dictionaries as needed.
00038  */
00039 
00040 #include "string_dictionary.h"
00041 #include "new_string.h"
00042 
00043 #include "main.h"
00044 
00045 #ifndef NULL
00046 #define NULL 0
00047 #endif
00048 
00049 /*
00050  *    string_dictionary string_dictionary_Create(int size):
00051  *        Requires: size > 0
00052  *        Effects: Returns a new empty dictionary containing no bindings.
00053  *                 The returned dictionary must be destroyed using
00054  *                 string_dictionary_Destroy.  Size is a time vs space
00055  *                 parameter.  For this implementation, space used is
00056  *                 proportional to size and time used is proportional
00057  *                 to number of bindings divided by size.  It is preferable
00058  *                 that size is a prime number.
00059  */
00060 
00061 string_dictionary 
00062 string_dictionary_Create(size)
00063         int size;
00064 {
00065         int i;
00066         string_dictionary result;
00067 
00068         result = (string_dictionary) malloc(sizeof(struct _string_dictionary));
00069         result->size = size;
00070         result->slots = (string_dictionary_binding **) malloc(
00071                                 size * sizeof(string_dictionary_binding *));
00072 
00073         for (i = 0; i < size; i++)
00074                 result->slots[i] = NULL;
00075 
00076         return (result);
00077 }
00078 
00079 /*
00080  *    void string_dictionary_Destroy(string_dictionary d):
00081  *        Requires: d is a non-destroyed string_dictionary
00082  *        Modifies: d
00083  *        Effects: Destroys dictionary d freeing up the space it consumes.
00084  *                 Dictionary d should never be referenced again.  Note that
00085  *                 free is NOT called on the values of the bindings.  If
00086  *                 this is needed, the client must do this first using
00087  *                 string_dictionary_Enumerate.
00088  */
00089 
00090 void 
00091 string_dictionary_Destroy(d)
00092         string_dictionary d;
00093 {
00094         int i;
00095         string_dictionary_binding *binding_ptr, *new_binding_ptr;
00096 
00097         for (i = 0; i < d->size; i++) {
00098                 binding_ptr = d->slots[i];
00099                 while (binding_ptr) {
00100                         new_binding_ptr = binding_ptr->next;
00101                         free(binding_ptr->key);
00102                         free(binding_ptr);
00103                         binding_ptr = new_binding_ptr;
00104                 }
00105         }
00106         free(d->slots);
00107         free(d);
00108 }
00109 
00110 /*
00111  *    void string_dictionary_Enumerate(string_dictionary d; void (*proc)()):
00112  *        Requires: proc is a void procedure taking 1 argument, a
00113  *                  string_dictionary_binding pointer, which does not
00114  *                  make any calls using dictionary d.
00115  *        Effects: Calls proc once with each binding in dictionary d.
00116  *                 Order of bindings passed is undefined.  Note that
00117  *                 only the value field of the binding should be considered
00118  *                 writable by proc.
00119  */
00120 
00121 void 
00122 string_dictionary_Enumerate(d, proc)
00123         string_dictionary d;
00124         void (*proc) ( /* string_dictionary_binding *b */ );
00125 {
00126         int i;
00127         string_dictionary_binding *binding_ptr;
00128 
00129         for (i = 0; i < d->size; i++) {
00130                 binding_ptr = d->slots[i];
00131                 while (binding_ptr) {
00132                         proc(binding_ptr);
00133                         binding_ptr = binding_ptr->next;
00134                 }
00135         }
00136 }
00137 
00138 /*
00139  *  Private routine:
00140  *
00141  *    unsigned int dictionary__hash(char *s):
00142  *        Effects: Hashs s to an unsigned integer.  This number mod the
00143  *                 hash table size is supposed to roughly evenly distribute
00144  *                 keys over the table's slots.
00145  */
00146 
00147 static unsigned int 
00148 dictionary__hash(s)
00149         char *s;
00150 {
00151         unsigned int result = 0;
00152 
00153         if (!s)
00154                 return (result);
00155 
00156         while (s[0]) {
00157                 result <<= 1;
00158                 result += s[0];
00159                 s++;
00160         }
00161 
00162         return (result);
00163 }
00164 
00165 /*
00166  *    string_dictionary_binding *string_dictionary_Lookup(string_dictionary d,
00167  *                                                        char *key):
00168  *        Effects: If key is not bound in d, returns 0.  Othersize,
00169  *                 returns a pointer to the binding that binds key.
00170  *                 Note the access restrictions on bindings...
00171  */
00172 
00173 string_dictionary_binding *
00174 string_dictionary_Lookup(d, key)
00175         string_dictionary d;
00176         char *key;
00177 {
00178         string_dictionary_binding *binding_ptr;
00179 
00180         binding_ptr = d->slots[dictionary__hash(key) % (d->size)];
00181         while (binding_ptr) {
00182                 if (string_Eq(key, binding_ptr->key))
00183                         return (binding_ptr);
00184                 binding_ptr = binding_ptr->next;
00185         }
00186 
00187         return (NULL);
00188 }
00189 
00190 /*
00191  *    string_dictionary_binding *string_dictionary_Define(string_dictionary d,
00192  *                                            char *key,
00193  *                                            int *already_existed):
00194  *        Modifies: d
00195  *        Effects: If key is bound in d, returns a pointer to the binding
00196  *                 that binds key.  Otherwise, adds a binding of key to
00197  *                 d and returns its address.  If already_existed is non-zero
00198  *                 then *already_existed is set to 0 if key was not
00199  *                 previously bound in d and 1 otherwise.
00200  *                 Note the access restrictions on bindings...  Note also
00201  *                 that the value that key is bounded to if a binding is
00202  *                 created is undefined.  The caller should set the value
00203  *                 in this case.
00204  */
00205 
00206 string_dictionary_binding *
00207 string_dictionary_Define(d, key, already_existed)
00208         string_dictionary d;
00209         char *key;
00210         int *already_existed;
00211 {
00212         string_dictionary_binding **ptr_to_the_slot, *binding_ptr;
00213 
00214         ptr_to_the_slot = &(d->slots[dictionary__hash(key) % (d->size)]);
00215 
00216         binding_ptr = *ptr_to_the_slot;
00217         while (binding_ptr) {
00218                 if (string_Eq(binding_ptr->key, key)) {
00219                         if (already_existed)
00220                                 *already_existed = 1;
00221                         return (binding_ptr);
00222                 }
00223                 binding_ptr = binding_ptr->next;
00224         }
00225 
00226         if (already_existed)
00227                 *already_existed = 0;
00228         binding_ptr = (string_dictionary_binding *) malloc(
00229                                          sizeof(string_dictionary_binding));
00230         binding_ptr->next = *ptr_to_the_slot;
00231         binding_ptr->key = string_Copy(key);
00232         *ptr_to_the_slot = binding_ptr;
00233         return (binding_ptr);
00234 }
00235 
00236 /*
00237  *    void string_dictionary_Delete(string_dictionary d,
00238  *                                  string_dictionary_binding *b):
00239  *        Requires: *b is a binding in d.
00240  *        Modifies: d
00241  *        Effects: Removes the binding *b from d.  Note that if
00242  *                 b->value needs to be freed, it should be freed
00243  *                 before making this call.
00244  */
00245 
00246 void 
00247 string_dictionary_Delete(d, b)
00248         string_dictionary d;
00249         string_dictionary_binding *b;
00250 {
00251         string_dictionary_binding **ptr_to_binding_ptr;
00252 
00253         ptr_to_binding_ptr = &(d->slots[dictionary__hash(b->key) % (d->size)]);
00254 
00255         while (*ptr_to_binding_ptr != b)
00256                 ptr_to_binding_ptr = &((*ptr_to_binding_ptr)->next);
00257 
00258         *ptr_to_binding_ptr = b->next;
00259         free(b->key);
00260         free(b);
00261 }


Last updated at Tue Dec 18 21:07:42 PST 2007. This site and project hosted by...SourceForge.net Logo
Source Perspective by Fisheye