/*
 $Id: dict.cc,v 1.1.1.1 1996/10/02 10:35:40 roitzsch Exp $
 (C)opyright 1996 by Konrad-Zuse-Center, Berlin
 All rights reserved.
 Part of the Kaskade distribution
*/

#include <string.h>

#include "dict.h"


#ifndef MINn1n2
  #define MINn1n2
  #define MIN(n1,n2)  ((n1)<(n2)) ? (n1):(n2)
#endif


//-------------------------------------------------------------------------

Dict:: Dict() 		: key(1,DefaultDictSize), val(1,DefaultDictSize)  { }
Dict:: Dict(int h)      : key(1,h), val(1,h) { }

Dict:: ~Dict()
{
    for (int i=key.l; i<=key.h; ++i)  { delete key[i]; delete val[i]; }
}
//-------------------------------------------------------------------------

void Dict:: push(const char* const s, const char* const value)
{
    char* newkey = new char[strlen(s)+1];
    char* newval = new char[strlen(value)+1];
    strcpy (newkey,s);
    strcpy (newval,value);
    key.push(newkey);
    val.push(newval);
}
//-------------------------------------------------------------------------

void Dict:: changeValue(const char* const s, const char* const value)
{
    int index;

    getKeyIndex(s, &index);

    cout << "\n  Command overwritten:  " 
	    << key.v[index] << " = " << val.v[index] << "\n\t\t\t"
	    << s << " = " << value << "\t <-- used value"; 
	    
    delete key[index];
    delete val[index];

    char* newkey = new char[strlen(s)+1];
    char* newval = new char[strlen(value)+1];
    strcpy (newkey,s);
    strcpy (newval,value);
    key[index]=newkey;
    val[index]=newval;
}
//-------------------------------------------------------------------------

int Dict:: inDict(const char* const akey)
{
    int i, n, n1, n2;
    
    n1 = strlen(akey);
    
    for (i=key.h; i>=key.l; --i)
    {
	n2 = strlen(key[i]);
	n  = MIN(n1,n2);
	if (!strncmp(akey, key[i], n)) return 1;	// key found
    }
    return 0;
}
//-------------------------------------------------------------------------

int Dict:: getVal(const char* const akey, char* xval)
{
    int i, n, n1, n2;

    n1 = strlen(akey);
    for (i=key.h; i>=key.l; --i)
    {
	n2 = strlen(key[i]);
	n  = MIN(n1,n2);
	if (!strncmp(akey, key[i], n)) 
	{
	    strcpy(xval, val[i]);
	    return 1;
	}
    }
    return 0;
}
//-------------------------------------------------------------------------

int Dict:: getVal(const char* const akey, int* xval)
{
    int i, n, n1, n2;

    n1 = strlen(akey);
    for (i=key.h; i>=key.l; --i)
    {
	n2 = strlen(key[i]);
	n  = MIN(n1,n2);
	if (!strncmp(akey, key[i], n)) 
	{
	    *xval = atoi(val[i]);
	    return 1;
	}
    }
    return 0;
}
//-------------------------------------------------------------------------

int Dict:: getVal(const char* const akey, double* xval)
{
    int i, n, n1, n2;

    n1 = strlen(akey);
    for (i=key.h; i>=key.l; --i)
    {
	n2 = strlen(key[i]);
	n  = MIN(n1,n2);
	if (!strncmp(akey, key[i], n)) { *xval = atof(val[i]); return 1; }
    }
    return 0;
}
//-------------------------------------------------------------------------

int Dict:: getVal(const char* const akey, float* xval)
{
    int i, n, n1, n2;

    n1 = strlen(akey);
    for (i=key.h; i>=key.l; --i)
    {
	n2 = strlen(key[i]);
	n  = MIN(n1,n2);
	if (!strncmp(akey, key[i], n)) { *xval = atof(val[i]); return 1; }
    }
    return 0;
}
//-------------------------------------------------------------------------

int Dict:: getKeyIndex(const char* const akey, int* index)
{
    int i, n, n1, n2;

    n1 = strlen(akey);
    
    for (i=key.h; i>=key.l; --i)
    {
	n2 = strlen(key[i]);
	n  = MIN(n1,n2);
	if (!strncmp(akey, key[i], n))  { *index = i; return 1; }
    }
    return 0;
}
//-------------------------------------------------------------------------

void Dict:: ambiguityCheck()
{
    int i, k, n1, n2, n;

    for (i=1; i<key.h; ++i)
    {
	n1 = strlen(key.v[i]);

	for (k=1; k<=key.h; ++k)
	{
	    if (k==i) continue;

	    n2 = strlen(key.v[k]);
	    n  = MIN(n1,n2);
	    if (!strncmp(key.v[k], key.v[i], n))
	    {
		cout << "\n\n*** Dict: ambiguous keys: '" << key.v[k]
		     << "' '" << key.v[i] << "'\n";
		cout.flush(); abort();
	    }
	}
    }
    cout << "\n";
}
//-------------------------------------------------------------------------

//void Dict:: ambiguousKey(const char* const akey)
//{
    // cout << "\n--- Dict: ambiguous keyword " << akey 
    // << "\n\t\t\t - last ocurrence considered to be valid\n";
//}
//-------------------------------------------------------------------------

ostream& operator<< (ostream& os, Dict& dict)
{ 
    //return os << "keys:  " << dict.key << "values:  " << dict.val;
    for (int i=dict.key.l; i<=dict.key.h; ++i)
    {
	os << (dict.key).v[i] << " \t";
	os << (dict.val).v[i] << "\n";
    }
    return os;
}
