text: #include "dict.h"
  
  
  /* dictionary initialization code used in both DictCreate and grow */
  TablaHash _tablahash_crear(int size, FuncionHash fun, FuncionIgualdad igualdad)
  {
      TablaHash d;
      int i;
  
      d = malloc(sizeof(*d));
  
      assert(d != 0);
  
      d->size = size;
      d->n = 0;
      d->table = malloc(sizeof(struct elt *) * d->size);
  
      assert(d->table != 0);
  
      for(i = 0; i < d->size; i++) d->table[i] = 0;
  
      return d;
  }
  
  TablaHash tablahash_crear(FuncionHash fun, FuncionIgualdad igualdad)
  {
      return _tablahash_crear(INITIAL_SIZE, fun, igualdad);
  }
  
  void tablahash_destruir(TablaHash d)
  {
      int i;
      struct elt *e;
      struct elt *next;
  
      for(i = 0; i < d->size; i++) {
          for(e = d->table[i]; e != 0; e = next) {
              next = e->next;
  
              free(e->key);
              free(e->value);
              free(e);
          }
      }
  
      free(d->table);
      free(d);
  }
  
  // static unsigned long hash_function(const char *s)
  // {
  //     unsigned const char *us;
  //     unsigned long h;
  
  //     h = 0;
  
  //     for(us = (unsigned const char *) s; *us; us++) {
  //         h = h * MULTIPLIER + *us;
  //     }
  
  //     return h;
  // }
  
  static void _tablahash_crecer(TablaHash d)
  {
      TablaHash d2;            /* new dictionary we'll create */
      struct tablaHash swap;   /* temporary structure for brain transplant */
      int i;
      struct elt *e;
  
      d2 = internalDictCreate(d->size * GROWTH_FACTOR);
  
      for(i = 0; i < d->size; i++) {
          for(e = d->table[i]; e != 0; e = e->next) {
              /* note: this recopies everything */
              /* a more efficient implementation would
               * patch out the strdups inside DictInsert
               * to avoid this problem */
              DictInsert(d2, e->key, e->value);
          }
      }
  
      /* the hideous part */
      /* We'll swap the guts of d and d2 */
      /* then call DictDestroy on d2 */
      swap = *d;
      *d = *d2;
      *d2 = swap;
  
      DictDestroy(d2);
  }
  
  /* insert a new key-value pair into an existing dictionary */
  void tablahash_insertar(TablaHash d, const char *key, void *value)
  {
      struct elt *e;
      unsigned long h;
  
      assert(key);
      assert(value);
  
      e = malloc(sizeof(*e));
  
      assert(e);
  
      e->key = strdup(key);
      e->value = strdup(value);
  
      h = hash_function(key) % d->size;
  
      e->next = d->table[h];
      d->table[h] = e;
  
      d->n++;
  
      /* grow table if there is not enough room */
      if(d->n >= d->size * MAX_LOAD_FACTOR) {
          _tablahash_crecer(d);
      }
  }
  
  /* return the most recently inserted value associated with a key */
  /* or 0 if no matching key is present */
  void * tablahash_buscar(TablaHash d, const char *key)
  {
      struct elt *e;
  
      for(e = d->table[hash_function(key) % d->size]; e != 0; e = e->next) {
          if(!strcmp(e->key, key)) {
              /* got it */
              return e->value;
          }
      }
  
      return 0;
  }
  
  /* delete the most recently inserted record with the given key */
  /* if there is no such record, has no effect */
  void tablahash_eliminar(TablaHash d, const char *key)
  {
      struct elt **prev;          /* what to change when elt is deleted */
      struct elt *e;              /* what to delete */
  
      for(prev = &(d->table[hash_function(key) % d->size]); 
          *prev != 0; 
          prev = &((*prev)->next)) {
          if(!strcmp((*prev)->key, key)) {
              /* got it */
              e = *prev;
              *prev = e->next;
  
              free(e->key);
              free(e->value);
              free(e);
  
              return;
          }
      }
  }