/***************************************************************************
 *   Copyright (C) 2003 by Dan Muller                                      *
 *   dan at verliba dot cz                                                        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
#ifndef CCONFIGITEMBASE_H
#define CCONFIGITEMBASE_H

#include <string>
#include <iostream>

using namespace std;
#ifndef _WIN32
#define __int64 long long
#endif

namespace nConfig
{
/*
typedef enum
{
	eIT_VOID, // unspecified
	eIT_NTSTR, // null terminated string
	eIT_INT,
	eIT_UINT, // unsigned int
	eIT_LONG,
	eIT_ULONG,
	eIT_LLONG, // long long
	eIT_ULLONG,
	eIT_AR_BYTE, // array of bytes
	eIT_STRING  // std::string
}tItemType;

*/
/**
a base class for all kinds of config items, used by cConfigBase

@author Daniel Muller
*/
class cConfigItemBase
{
	friend class mConfigBase;
public:
	/** constructors */
	cConfigItemBase(void *addr=0, void *base=0) :
		mAddr(addr),
		mBase(base)
	{};

	/** setting value */
	template <class TYPE> cConfigItemBase &operator=(const TYPE &i){*(TYPE*)Address() = i; return *this;};
	/** cast operator */
	template <class TYPE> operator TYPE(){return *(TYPE*)mAddr;}

	/** input /output */
	virtual std::istream &ReadFromStream(std::istream &)=0;
	virtual std::ostream &WriteToStream (std::ostream &)=0;
	friend std::istream &operator >> (std::istream &is, cConfigItemBase &ci){return ci.ReadFromStream(is);}
	friend std::ostream &operator << (std::ostream &os, cConfigItemBase &ci){return ci.WriteToStream (os);}

	/** conversion of a string to a value */
	virtual void ConvertFrom(const std::string &) = 0;
	virtual void ConvertTo(std::string &) = 0;
	void *mAddr;
	string mName;
	char mBuf[32];

protected:

public:
	bool &AsBool(){ return *(bool*)mAddr; }
	char &AsChar(){ return *(char*)mAddr; }
	int  &AsInt (){ return *(int *)mAddr; }
	unsigned &AsUnsigned (){ return *(unsigned*)mAddr; }
	unsigned char &AsUnsignedChar (){ return *(unsigned char*)mAddr; }
	long &AsLong (){ return *(long*)mAddr; }
	unsigned long &AsUnsignedLong (){ return *(unsigned long*)mAddr; }
	__int64 &AsLongLong (){ return *(__int64*)mAddr; }
	double &AsDouble (){ return *(double*)mAddr; }
	char * &AsPChar (){ return *(char **)mAddr; }
	char const* &AsConstPChar (){ return *(char const**)mAddr; }
	string &AsString (){ return *(string*)mAddr; }
	virtual void *Address(){return mAddr;}
	void *mBase;
};

/**
  * a Typed template for a config Item, provides all the methods for convetiong with string, affecting values, ans streaming
*/
template <class TYPE> class cConfigItemBaseT : public cConfigItemBase
{
public:
	// constructor
	cConfigItemBaseT(TYPE &var): cConfigItemBase((void*)&var, 0){}

#ifdef NOEXPLICIT_TEMPLATES
	TYPE & Data(){return *(TYPE*)mAddr;}
#endif

	// methods
	virtual std::istream &ReadFromStream(std::istream& is);
#ifdef NOEXPLICIT_TEMPLATES
	virtual std::ostream &WriteToStream (std::ostream& os){ return os << (this->Data()); }
	virtual TYPE *Address(){return (TYPE*)cConfigItemBase::Address();}
#else
	virtual std::ostream &WriteToStream (std::ostream& os);
#endif
	virtual void ConvertFrom(const std::string &str);
	virtual void ConvertTo(std::string &str);
#ifdef NOEXPLICIT_TEMPLATES
	cConfigItemBaseT<TYPE> &operator=(const TYPE &i){*(TYPE*)Address() = i; return *this;};
#else
	cConfigItemBaseT<TYPE> &operator=(TYPE const &i);
#endif
};

#ifndef NOEXPLICIT_TEMPLATES
cConfigItemBaseT<bool> &cConfigItemBaseT<bool>::operator=(const bool &i);
cConfigItemBaseT<char> &cConfigItemBaseT<char>::operator=(const char &i);
cConfigItemBaseT<int> &cConfigItemBaseT<int>::operator=(const int &i);
cConfigItemBaseT<unsigned> &cConfigItemBaseT<unsigned>::operator=(const unsigned &i);
cConfigItemBaseT<unsigned char> &cConfigItemBaseT<unsigned char>::operator=(const unsigned char &i);
cConfigItemBaseT<unsigned long> &cConfigItemBaseT<unsigned long>::operator=(const unsigned long &i);
cConfigItemBaseT<long> &cConfigItemBaseT<long>::operator=(const long &i);
cConfigItemBaseT<__int64> &cConfigItemBaseT<__int64>::operator=(const __int64 &i);
cConfigItemBaseT<double> &cConfigItemBaseT<double>::operator=(const double &i);
cConfigItemBaseT<const char *> &cConfigItemBaseT<const char *>::operator=(const char * const &i);
cConfigItemBaseT<char*> &cConfigItemBaseT<char*>::operator=(char* const &i);
cConfigItemBaseT<string> &cConfigItemBaseT<string>::operator=(const string &i);
#endif

};

#endif
