
/******************************************************************************
* MODULE     : hashmap.gen.h
* DESCRIPTION: fixed size hashmaps with reference counting
* 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.
******************************************************************************/

#include <tree.gen.h>
#include <list.gen.h>

#module hashmap (T,U)
#import tree
#define test<T,U>

struct hashentry<T,U> {
  T key;
  U im;
  hashentry<T,U> () { }
  hashentry<T,U> (T key2, U im2);
  operator tree ();
};

#import list (hashentry<T,U>)

class hashmap<T,U>;
class hashmap_rep<T,U>: concrete_struct {
  int size;                 // size of hashmap (nr of entries)
  int n;                    // nr of keys (a power of two)
  int max;                  // mean number of entries per key
  U   init;                 // default entry
  list<hashentry<T,U>>* a;  // the array of entries

public:
  inline hashmap_rep<T,U>(U init2, int n2=1, int max2=1):
    size(0), n(n2), max(max2), init(init2), a(new list<hashentry<T,U>>[n]) {}
  inline ~hashmap_rep<T,U> () { delete[] a; }
  void resize (int n);
  void reset (T x);
  void generate (void (*routine) (T));
  bool contains (T x);
  bool empty ();
  U    bracket_ro (T x);
  U&   bracket_rw (T x);
  void join (hashmap<T,U> H);

  friend class hashmap<T,U>;
  friend class rel_hashmap<T,U>;
  friend class rel_hashmap_rep<T,U>;
  friend class hashmap_iterator_rep<T,U>;
  friend inline int N (hashmap<T,U> h);
  friend ostream& operator << (ostream& out, hashmap<T,U> h);

#ifdef test<string,tree>
  void write_back (T x, hashmap<T,U> base);
  void pre_patch (hashmap<T,U> patch, hashmap<T,U> base);
  void post_patch (hashmap<T,U> patch, hashmap<T,U> base);
  friend hashmap<T,U> copy (hashmap<T,U> h);
  friend hashmap<T,U> changes (hashmap<T,U> patch, hashmap<T,U> base);
  friend hashmap<T,U> invert (hashmap<T,U> patch, hashmap<T,U> base);
  friend class edit_env_rep;
#endif
#if defined(test<string,tree>) || defined (test<string,path>)
  friend bool operator == (hashmap<T,U> h1, hashmap<T,U> h2);
  friend bool operator != (hashmap<T,U> h1, hashmap<T,U> h2);
#endif
};

class hashmap<T,U> {
#import concrete (hashmap<T,U>, hashmap_rep<T,U>)
#ifdef init<U>
  inline hashmap<T,U> (U init=init<U>, int n=1, int max=1):
    rep (new hashmap_rep<T,U>(init, n, max)) {}
#else
  inline hashmap<T,U> (U init, int n=1, int max=1):
    rep (new hashmap_rep<T,U>(init, n, max)) {}
#endif
#ifdef test<string,tree>
  hashmap<T,U> (U init, tree t);
#endif
  inline U  operator [] (T x) { return rep->bracket_ro (x); }
  inline U& operator () (T x) { return rep->bracket_rw (x); }
  operator tree ();
};
#import code_concrete (hashmap<T,U>, hashmap_rep<T,U>)

extern inline int N (hashmap<T,U> h) { return h->size; }

/* should be in data.gen.h */
#ifdef test<string,int>
extern hashmap<string,int> CONSTRUCTOR_CODE;
#endif

#ifndef STANDARD_HASHES
#define STANDARD_HASHES
inline int hash (int i) { return i; }
inline int hash (pointer ptr) { return (int) ptr; }
#endif

#undef test<T,U>
#endmodule // hashmap (T,U)
