
/******************************************************************************
* MODULE     : hashmap_extra.gen.cc
* DESCRIPTION: extra routines for hashmap<string,tree>
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
*******************************************************************************
* This software falls under the GNU general public license and comes WITHOUT
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
* If you don't have this file, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/

#module code_hashmap_extra (T,U)
#define H hashentry<T,U>

void
hashmap_rep<T,U>::write_back (T x, hashmap<T,U> base) {
  register int hv= hash(x);
  list<hashentry<T,U>> l (a[hv&(n-1)]);
  while (!nil (l)) {
    if (l->item.key==x) return;
    l= l->next;
  }
  if (size>=n*max) resize (n<<1);
  list<hashentry<T,U>>& rl (a[hv&(n-1)]);
  rl= list<hashentry<T,U>> (H (x, init), rl);
  size ++;

  list<hashentry<T,U>> bl (base->a[hv&(base->n-1)]);
  while (!nil (bl)) {
    if (bl->item.key==x) {
      rl->item.im= bl->item.im;
      return;
    }
    bl= bl->next;
  }
  rl->item.im= base->init;
}

void
hashmap_rep<T,U>::pre_patch (hashmap<T,U> patch, hashmap<T,U> base) {
  int i=0, n=patch->n;
  for (; i<n; i++) {
    list<hashentry<T,U>> l=patch->a[i];
    for (; !nil(l); l=l->next) {
      T x= l->item.key;
      U y= contains (x)? bracket_ro (x): l->item.im;
      if (base[x] == y) reset (x);
      else bracket_rw (x)= y;
    }
  }
}

void
hashmap_rep<T,U>::post_patch (hashmap<T,U> patch, hashmap<T,U> base) {
  int i=0, n=patch->n;
  for (; i<n; i++) {
    list<hashentry<T,U>> l=patch->a[i];
    for (; !nil(l); l=l->next) {
      T x= l->item.key;
      U y= l->item.im;
      if (base[x] == y) reset (x);
      else bracket_rw (x)= y;
    }
  }
}

list<hashentry<T,U>>
copy_list (list<hashentry<T,U>> l) {
  if (nil (l)) return l;
  else return list<hashentry<T,U>> (hashentry<T,U> (l->item.key, l->item.im),
				    copy_list (l->next));
}

hashmap<T,U>
copy (hashmap<T,U> H) {
  int i, n= H->n;
  hashmap<T,U> H2 (H->init, n, H->max);
  H2->size= H->size;
  for (i=0; i<n; i++)
    H2->a[i]= copy_list (H->a[i]);
  return H2;
}

hashmap<T,U>
changes (hashmap<T,U> patch, hashmap<T,U> base) {
  int i;
  hashmap<T,U> H (base->init);
  for (i=0; i<patch->n; i++) {
    list<hashentry<T,U>> l (patch->a[i]);
    while (!nil (l)) {
      if (l->item.im != base [l->item.key]) H (l->item.key)= l->item.im;
      l=l->next;
    }
  }
  return H;
}

hashmap<T,U>
invert (hashmap<T,U> patch, hashmap<T,U> base) {
  int i;
  hashmap<T,U> H (base->init);
  for (i=0; i<patch->n; i++) {
    list<hashentry<T,U>> l (patch->a[i]);
    while (!nil (l)) {
      if (l->item.im != base [l->item.key])
	H (l->item.key)= base [l->item.key];
      l=l->next;
    }
  }
  return H;
}

hashmap<T,U>::hashmap<T,U> (U init, tree t):
  rep (new hashmap_rep<T,U>(init, 1, 1))
{
  int i, n= arity (t);
  for (i=0; i<n; i++)
    if (is_func (t[i], ASSOCIATE, 2))
      rep->bracket_rw (get_label (t[i][0]))= copy (t[i][1]);
}

#undef H
#endmodule // code_hashmap (T,U)
