dictionary.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006  SRI International
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00017  *
00018  * SRI International: 333 Ravenswood Ave, Menlo Park, CA 94025
00019  */
00020 
00021 #ifndef lint
00022 /*static char dictionary_c_rcsid[] = "$Header: /home/zuma1/OAA/CVSRepository/oaa2/src/oaalib/c/src/dictionary.c,v 1.12 2006/10/29 22:12:13 agno Exp $";*/
00023 #endif /*lint*/
00024 
00025 
00026 #include "dictionary.h"
00027 #include "libicl.h"
00028 #ifdef _WINDOWS
00029 #include <stdlib.h>
00030 #endif
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 
00035 /****************************************************************************
00036  * Definition for utility dictionary type and functions for manipulating it
00037  ****************************************************************************/
00038 
00043 DICTIONARY *dict_new(int (*_compar)(void *, void *), void (*_keyfree)(void *)) {
00044   DICTIONARY *newdict = (DICTIONARY *)malloc(sizeof(DICTIONARY));
00045 
00046   newdict->size = 0;
00047   newdict->capacity = INIT_CAPACITY;
00048   newdict->compar = _compar;
00049   newdict->keyfree = _keyfree;
00050 
00051   if(!(newdict->key = (void *)calloc(INIT_CAPACITY, sizeof(void*)))) {
00052     return NULL;
00053   }
00054   if(!(newdict->value = (void *)calloc(INIT_CAPACITY, sizeof(void*)))) {
00055     return NULL;
00056   }
00057   return newdict;
00058 }
00063 int dict_expand_capacity(DICTIONARY *dict) {
00064   void **newkey, **newval;
00065   int newcap, i, n;
00066 
00067   if(!dict)     /* null passed in, return error */
00068     return -1;
00069   newcap = dict->capacity + INIT_CAPACITY;
00070   if(!(newkey = (void *)calloc(newcap, sizeof(void*))))
00071     return dict->capacity;
00072   if(!(newval = (void *)calloc(newcap, sizeof(void*))))
00073     return dict->capacity;
00074   for(i=0, n=dict->size; i<n; i++) {
00075     newkey[i] = dict->key[i];
00076     newval[i] = dict->value[i];
00077   }
00078   free(dict->key);
00079   free(dict->value);
00080   dict->key = newkey;
00081   dict->value = newval;
00082   return(dict->capacity = newcap);
00083 }
00087 void *dict_get(DICTIONARY *d, void *key) {
00088   int i, n;
00089 
00090   for(i=0, n=d->size; i<n; i++) {
00091     if(d->compar(key, d->key[i]) == 1) {
00092       return d->value[i];
00093     }
00094   }
00095   return NULL;
00096 }
00097 
00102 int dict_get_nth(DICTIONARY *d, void **key, void **value, int n) {
00103   if((n >= 0) && (n < d->size)) {
00104     *key = d->key[n];
00105     *value = d->value[n];
00106     return 1;
00107   }
00108   return 0;
00109 }
00110 
00114 int dict_index_for_key(DICTIONARY *d, void *key) {
00115   int i,n;
00116 
00117   for(i=0, n=d->size; i<n; i++) {
00118     if(d->compar(key, d->key[i]) == 1) {
00119       return i;
00120     }
00121   }
00122   return -1;
00123 }
00124 
00129 void *dict_put(DICTIONARY *d, void *key, void *value) {
00130   int oldsize, index;
00131   void *ret = NULL;
00132 
00133   if(!d) return ret;
00134   oldsize = d->size;
00135   /* Check to see if this is a new key */
00136   if((index = dict_index_for_key(d, key)) < 0) {
00137     /* Check capacity and expand if neccessary */
00138     if(oldsize >= d->capacity)
00139       if(dict_expand_capacity(d) <= oldsize)
00140         return NULL;
00141     /* add key/value pair at end */
00142     d->key[oldsize] = key;
00143     d->value[oldsize] = value;
00144     d->size++;
00145   } else { /* must be an existing key */
00146     ret = d->value[index];
00147     d->value[index] = value;
00148   }
00149   return ret;
00150 }
00151 
00157 void *dict_put_nonunique(DICTIONARY *d, void *key, void *value) {
00158   int oldsize;
00159   void *ret = NULL;
00160 
00161   if(!d) return ret;
00162   oldsize = d->size;
00163   /* Check capacity and expand if neccessary */
00164   if(oldsize >= d->capacity)
00165     if(dict_expand_capacity(d) <= oldsize)
00166       return NULL;
00167   /* add key/value pair at end */
00168   d->key[oldsize] = key;
00169   d->value[oldsize] = value;
00170   d->size++;
00171   return value;
00172 }
00173 
00178 void *dict_remove(DICTIONARY *d, void *key) {
00179   void *ret = NULL;
00180   int index, i, n;
00181 
00182   if(!d) return ret;
00183   index = dict_index_for_key(d, key);
00184   if(index >= 0) {
00185     /* remember the return value */
00186     ret = d->value[index];
00187     /* free the key */
00188     if (d->keyfree)
00189       d->keyfree(d->key[index]);
00190 
00191     /* shift the remaining contents up */
00192     for(i=index+1, n=d->size; i<n; i++) {
00193       d->key[i-1] = d->key[i];
00194       d->value[i-1] = d->value[i];
00195     }
00196     d->size--;
00197   }
00198   CHECK_LEAKS();
00199   return ret;
00200 }
00201 
00210 void *dict_remove_specific(DICTIONARY *d, void *key, void *value) {
00211   void *ret = NULL;
00212   int index = -1, i, n;
00213 
00214   if(!d) return ret;
00215   for(i=0, n=d->size; i<n; i++) {
00216     if((d->compar(key, d->key[i]) == 1) &&
00217        (d->compar(value, d->value[i]) == 1)) {
00218 
00219       /* remember the correct index and return value */
00220       index = i;
00221       ret = d->value[index];
00222 
00223       /* free the key */
00224       if (d->keyfree)
00225         d->keyfree(d->key[index]);
00226       break;
00227     }
00228   }
00229   if(index >= 0) {
00230     /* shift the remaining contents up */
00231     for(i=index+1, n=d->size; i<n; i++) {
00232       d->key[i-1] = d->key[i];
00233       d->value[i-1] = d->value[i];
00234     }
00235     d->size--;
00236   }
00237   return ret;
00238 }
00239 
00247 void **dict_remove_all(DICTIONARY *d, void *key, int *num_removed) {
00248   int index, i, n, num_found = 0;
00249   void **_values = NULL;
00250 
00251   if(!d) {
00252     if (num_removed) {
00253       *num_removed = num_found;
00254     }
00255     return _values;
00256   }
00257 
00258   index = dict_index_for_key(d, key);
00259   while(index >= 0) {
00260     num_found++;
00261 
00262     /* Allocate space for and remember the return value */
00263     _values = (void *)realloc(_values, sizeof(void*) * num_found);
00264     _values[num_found-1] = d->value[index];
00265 
00266     /* Free the key */
00267     d->keyfree(d->key[index]);
00268 
00269     /* shift the remaining contents up */
00270     for(i=index+1, n=d->size; i<n; i++) {
00271       d->key[i-1] = d->key[i];
00272       d->value[i-1] = d->value[i];
00273     }
00274     d->size--;
00275     index = dict_index_for_key(d, key);
00276   }
00277   if (num_removed)
00278     *num_removed = num_found;
00279   return _values;
00280 }
00281 
00285 void dict_free(DICTIONARY *d) {
00286   if(!d) return;
00287   free(d->key);
00288   free(d->value);
00289   free(d);
00290 }
00291 

Generated on Wed May 23 17:20:10 2007 using doxygen 1.5.2