/* Assoc.H: associative arrays */

#ifndef _ASSOC_H_
#define _ASSOC_H_

#include "Array.H"

template<class keyT, class valueT>
class assoc {
public:
  keyT default_key;
  valueT default_value;
  int size;

protected:
  struct key_value_pair {
    keyT k;
    valueT v;
    key_value_pair() 			{ }
    key_value_pair(keyT kk, valueT vv) 	{ k = kk; v = vv; }

    friend ostream& operator<<(ostream& s, struct key_value_pair& a) { return s << a.k << " \t----> " << a.v; }
  };
  array<key_value_pair> table;

  void init(int len)
  {
    if (len > 0) table.init(len, 0); size=table.size;
  }

public:
  assoc(int len =0) { init(len); }

  // adds the key if not found (with default value) and returns a reference to the 
  // value. Finds the most recently added item with this key if the key occurs 
  // more than once.
  valueT& operator[](keyT kk)
  {
    // search back to front: find most recently added items first
    for (int i=table.size-1; i>=0; i--)
      if (table[i].k == kk)
	return table[i].v;		// found
    
    table.append(key_value_pair(kk, default_value));	// not found
    size = table.size;
    return table[table.size-1].v;
  }

  valueT& operator[](int i) 
  {
    return table[i].v;
  }

  keyT& key(int i) 
  {
    return table[i].k;
  }

  // returns the index of the value if found and -1 if not. Does not
  // add the key to the table.
  int operator() (keyT kk)
  {
    for (int i=table.size-1; i>=0; i--)
      if (table[i].k == kk)
	return i;		// found
    return -1;			// not found
  }

  // adds the key-value pair and returns the index in the table
  int add(keyT kk, const valueT& vv)
  {
    table.append(key_value_pair(kk, vv));
    size = table.size;
    return table.size-1;
  }
};

#endif /*_ASSOC_H_*/
