//
// Note, this is a C++ file
//
#include <stdlib.h>
#include <string.h>
#include <hash_map>		// use STL extension of hash_map
using namespace std;

#include "hash.h"

struct equal_c_str
{
  bool operator()(const char* const& __x, const char* const& __y) const
    { return strcmp (__x, __y) == 0; }
};

typedef std::hash_map<const char*, void*, hash<const char*>, equal_c_str> HashMap;

HashTable* newHashTable ()
{
  HashTable* newTable = new HashTable;
  newTable->parent = NULL;
  newTable->hashTable = new HashMap ();
  return newTable;
}

void deleteHashTable (HashTable *table)
{
  HashMap *hashTablePtr = (HashMap *)(table->hashTable);
  char** keys = (char**)getHashTableKeys (table);
  // free the table itself
  delete hashTablePtr;
  table->hashTable = NULL;
  // free the memory used up by the keys
  for (int i = 0; keys[i] != NULL; ++i)
    free (keys[i]);
}

void* getHashTableEntry (HashTable *table, const char *key)
{
  HashMap &hashTable = *((HashMap *)(table->hashTable));
  HashMap::iterator i = hashTable.find (key);
  if (i == hashTable.end ())
    return NULL;
  return (*i).second;
}

void setHashTableEntry (HashTable *table, const char *key, void* value)
{
  HashMap &hashTable = *((HashMap *)(table->hashTable));
  HashMap::iterator i = hashTable.find (key);
  if (i == hashTable.end ())
    key = strdup (key);
  hashTable[key] = value;
}

void deleteHashTableEntry (HashTable *table, const char *key)
{
  HashMap &hashTable = *((HashMap *)(table->hashTable));
  hashTable.erase (key);
}

const char** getHashTableKeys (HashTable *table)
{
  HashMap &hashTable = *((HashMap *)(table->hashTable));
  int size = hashTable.size ();
  const char** strArray = (const char **)calloc (size + 1, sizeof (char *));
  int j = 0;
  for (HashMap::iterator i = hashTable.begin ();
       i != hashTable.end ();
       ++i, ++j)
    {
      strArray[j] = (*i).first;
    }
  strArray[j] = NULL;
  return strArray;
}
