source: dict.c @ e146cd7

release-1.8release-1.9
Last change on this file since e146cd7 was 4c7c21f, checked in by David Benjamin <davidben@mit.edu>, 11 years ago
owl_dict_create also never fails And like everywhere else, we weren't checking the return values most of the time anyway.
  • Property mode set to 100644
File size: 3.3 KB
RevLine 
[7d4fbcd]1/* Dictionary data abstraction. 
2 * Maps from strings to pointers.
3 * Stores as a sorted list of key/value pairs.
4 * O(n) on inserts and deletes.
[7cd5878]5 * O(log n) on searches
[7d4fbcd]6 */
7
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
[1aee7d9]11#include "owl.h"
12
[7d4fbcd]13
14#define INITSIZE 30
[0f15f12]15#define GROWBY 3 / 2
[7d4fbcd]16
[4c7c21f]17void owl_dict_create(owl_dict *d) {
[7d4fbcd]18  d->size=0;
[96828e4]19  d->els=g_new(owl_dict_el, INITSIZE);
[7d4fbcd]20  d->avail=INITSIZE;
21}
22
[636b137]23int owl_dict_get_size(const owl_dict *d) {
[7d4fbcd]24  return(d->size);
25}
26
27/* Finds the position of an element with key k, or of the element where
28 * this element would logically go, and stores the index in pos.
29 * Returns 1 if found, else 0. */
[636b137]30int _owl_dict_find_pos(const owl_dict *d, const char *k, int *pos) {
[2b37be2]31  int lo = 0, hi = d->size;
[7cd5878]32  while (lo < hi) {
[2b37be2]33    int mid = (lo + hi)/2; /* lo goes up and we can't hit hi, so no +1 */
34    int cmp = strcmp(k, d->els[mid].k);
35    if (cmp < 0) {
[7cd5878]36      hi = mid;
[2b37be2]37    } else if (cmp > 0) {
[7cd5878]38      lo = mid+1;
[2b37be2]39    } else {
40      *pos = mid;
41      return 1;
[7cd5878]42    }
[7d4fbcd]43  }
[7cd5878]44  *pos = lo;
[2b37be2]45  return 0;
[7d4fbcd]46}
47
48/* returns the value corresponding to key k */
[636b137]49void *owl_dict_find_element(const owl_dict *d, const char *k) {
[7d4fbcd]50  int found, pos;
51  found = _owl_dict_find_pos(d, k, &pos);
52  if (!found) {
53    return(NULL);
54  }
55  return(d->els[pos].v);
56}
57
[f25df21]58/* Appends dictionary keys to a list.  Duplicates the keys,
[7d4fbcd]59 * so they will need to be freed by the caller. */
[351c535]60void owl_dict_get_keys(const owl_dict *d, owl_list *l) {
[7d4fbcd]61  int i;
62  for (i=0; i<d->size; i++) {
[fda61d3]63    owl_list_append_element(l, g_strdup(d->els[i].k));
[7d4fbcd]64  }
65}
66
[a1074de]67void owl_dict_noop_delete(void *x)
68{
[7d4fbcd]69  return;
70}
71
72/* Returns 0 on success.  Will copy the key but make
73   a reference to the value.  Will clobber an existing
[a1074de]74   entry with the same key iff delete_on_replace!=NULL,
75   and will run delete_on_replace on the old element.
[7d4fbcd]76   Will return -2 if replace=NULL and match was found.
77*/
[a1074de]78int owl_dict_insert_element(owl_dict *d, const char *k, void *v, void (*delete_on_replace)(void *old))
79{
[7d4fbcd]80  int pos, found;
81  found = _owl_dict_find_pos(d, k, &pos);
[a1074de]82  if (found && delete_on_replace) {
83    delete_on_replace(d->els[pos].v);
[7d4fbcd]84    d->els[pos].v = v;
85    return(0);
[a1074de]86  } else if (found && !delete_on_replace) {
[7d4fbcd]87    return(-2);
88  } else {
[0f15f12]89    if (d->size + 1 > d->avail) {
90      int avail = MAX(d->avail * GROWBY, d->size + 1);
[35b6eb9]91      d->els = g_renew(owl_dict_el, d->els, avail);
[0f15f12]92      d->avail = avail;
[7d4fbcd]93      if (d->els==NULL) return(-1);
94    }
95    if (pos!=d->size) {
96      /* shift forward to leave us a slot */
[4d86e06]97      memmove(d->els+pos+1, d->els+pos, 
[7d4fbcd]98              sizeof(owl_dict_el)*(d->size-pos));
99    }
100    d->size++;
[fda61d3]101    d->els[pos].k = g_strdup(k);
[7d4fbcd]102    d->els[pos].v = v;   
103    return(0);
104  }
105}
106
107/* Doesn't free the value of the element, but does
108 * return it so the caller can free it. */
[e19eb97]109void *owl_dict_remove_element(owl_dict *d, const char *k) {
[7d4fbcd]110  int i;
111  int pos, found;
112  void *v;
113  found = _owl_dict_find_pos(d, k, &pos);
114  if (!found) return(NULL);
[ddbbcffa]115  g_free(d->els[pos].k);
[7d4fbcd]116  v = d->els[pos].v;
117  for (i=pos; i<d->size-1; i++) {
118    d->els[i]=d->els[i+1];
119  }
120  d->size--;
121  return(v);
122}
123
124/* elefree should free the value as well */
[bf7aa1d]125void owl_dict_cleanup(owl_dict *d, void (*elefree)(void *))
126{
[7d4fbcd]127  int i;
128
129  for (i=0; i<d->size; i++) {
[ddbbcffa]130    g_free(d->els[i].k);
[7d4fbcd]131    if (elefree) (elefree)(d->els[i].v);
132  }
[ddbbcffa]133  if (d->els) g_free(d->els);
[7d4fbcd]134}
135
Note: See TracBrowser for help on using the repository browser.