// Pspell implementation header file.
// Applications that just use the pspell library should not include 
// these files as they are subject to change.
// Pspell Modules MUST include some of the implementation files and
// spell checkers MAY include some of these files.
// If ANY of the implementation files are included you also should
// link with libaspell-impl to protect you from changes in these
// files.

// Copyright 2000 by Kevin Atkinson under the terms of the LGPL

#ifndef PSPELL_STRING_MAP_IMPL__HH
#define PSPELL_STRING_MAP_IMPL__HH

#include "string_map.h"

class PspellStringMapImplNode {
public:
  PspellStringPair      data;
  PspellStringMapImplNode * next;
  PspellStringMapImplNode() : next(0) {}
  PspellStringMapImplNode(const PspellStringMapImplNode &);
  ~PspellStringMapImplNode();
private:
  PspellStringMapImplNode & operator=(const PspellStringMapImplNode &);
};

typedef PspellStringMapImplNode * PspellStringMapImplNodePtr;

class PspellStringMapImpl : public PspellStringMap {
public:
  PspellStringMapImpl();
  PspellStringMapImpl(const PspellStringMapImpl &);
  PspellStringMapImpl & operator= (const PspellStringMapImpl &);
  ~PspellStringMapImpl();

  PspellStringMap * clone() const {
    return new PspellStringMapImpl(*this);
  }
  void assign(const PspellStringMap * other) {
    *this = *(const PspellStringMapImpl *)(other);
  }

  PspellStringPairEmulation * elements() const;

  // insert a new element.   Will NOT overright an existing entry.
  // returns false if the element already exists.
  bool insert(const char * key, const char * value) {
    return insert(key, value, false);
  }
  bool add(const char * key) {
    return insert(key, 0, false);
  }
  // insert a new element. WILL overight an exitsing entry
  // always returns true
  bool replace(const char * key, const char * value) {
    return insert(key, value, true);
  }

  // removes an element.  Returnes true if the element existed.
  bool remove(const char * key) ;

  void clear();

  // looks up an element.  Returns null if the element did not exist.
  // returns an empty string if the element exists but has a null value
  // otherwise returns the value
  const char * lookup(const char * key) const;
  
  bool have(const char * key) const {return lookup(key) != 0;}

  unsigned int size() const {return size_;}
  bool empty() const {return size_ == 0;}

private:
  void resize(const unsigned int *);

  // inserts an element the last paramerts conters if an
  // existing element will be overwritten.
  bool insert(const char * key, const char * value, bool);

  // clears the hash table, does NOT delete the old one
  void clear_table(const unsigned int * size);

  void copy(const PspellStringMapImpl &);

  // destroys the hash table, assumes it exists
  void destroy();

  PspellStringMapImplNode * * find(const char *);
  unsigned int size_;
  PspellStringMapImplNodePtr * data;
  const unsigned int * buckets;
};

#endif
