
#ifndef __CINT_H__
#define __CINT_H__

#include "exception.h"
#include "cstring.h"

// definition of arithmetic operator ( + - * )
#define INT_ARITH_OP(op) \
	CInt &operator op##=(const CInt &p_Obj) { \
		m_iVal op##= p_Obj.m_iVal; \
		m_bSet = true; \
		return *this; \
	} \
	CInt &operator op##=(const int p_iVal) { \
		m_iVal op##= p_iVal; \
		m_bSet = true; \
		return *this; \
	} \
	CInt operator op(const CInt &p_Obj) { \
		return CInt(m_iVal op p_Obj.m_iVal); \
	} \
	CInt operator op(const int p_iVal) { \
		return CInt(m_iVal op p_iVal); \
	} \
	friend CInt operator op(const int p_iVal, const CInt &p_Obj) { \
		return CInt(p_iVal op p_Obj.m_iVal); \
	}


// definition of arithmetic operator 2(/ *)
#define INT_ARITH_OP2(op) \
	CInt &operator op##=(const CInt &p_Obj) \
	{ \
		if (p_Obj.m_iVal == 0) { \
			throw CException("operator" #op " : Divided by zero Exception"); \
		} \
		m_iVal op##= p_Obj.m_iVal; \
		m_bSet = true; \
		return *this; \
	} \
	CInt &operator op##=(const int p_iVal) \
	{ \
		if (p_iVal == 0) { \
			throw CException("operator" #op " : Divided by zero Exception"); \
		} \
		m_iVal op##= p_iVal; \
		m_bSet = true; \
		return *this; \
	} \
	CInt operator op(const CInt &p_Obj) \
	{ \
		if (p_Obj.m_iVal == 0) { \
			throw CException("operator" #op " : Divided by zero Exception"); \
		} \
		return CInt((int)(m_iVal op p_Obj.m_iVal)); \
	} \
	CInt operator op(const int p_iVal) \
	{ \
		if (p_iVal == 0) { \
			throw CException("operator" #op " : Divided by zero Exception"); \
		} \
		return CInt((int)(m_iVal op p_iVal)); \
	} \
	friend CInt operator op(const int p_iVal, const CInt &p_Obj) \
	{ \
		if (p_Obj.m_iVal == 0) { \
			throw CException("operator" #op " : Divided by zero Exception"); \
		} \
		return CInt(p_iVal op p_Obj.m_iVal); \
	}


// definition of comparison operator
#define INT_COMP_OPERATOR(op) \
	bool operator op(const CInt &p_Obj) const { \
		return (m_iVal op p_Obj.m_iVal) ? true : false; \
	} \
	bool operator op(const int p_iVal) const { \
		return (m_iVal op p_iVal) ? true : false; \
	} \
	friend bool operator op(const int p_iVal, const CInt &p_Obj) { \
		return (p_iVal op p_Obj.m_iVal) ? true : false; \
	}


class V2_CLASS_API CInt
{
private:
	int m_iVal;
	bool m_bSet;

public:
	CInt() {
		m_iVal = 0;
		m_bSet = false;
	}

	CInt(const int p_iVal) {
		m_iVal = p_iVal;
		m_bSet = true;
	}

	CInt(const CInt &p_Obj) {
		m_iVal = p_Obj.m_iVal;
		m_bSet = p_Obj.m_bSet;
	}

	~CInt() {
		m_iVal = 0;
		m_bSet = false;
	}

	void Init() {
		m_iVal = 0;
		m_bSet = false;
	}

	void SetNull() {
		Init();
	}

	bool IsValid() const {
		return m_bSet;
	}

	int ToInt() const {
		return m_iVal;
	}
	double ToDbl() const {
		return (double) m_iVal;
	}

	CString ToFmtStr(bool p_bComma=true) const;

	operator int() const {
		return m_iVal;
	}
	
	CString Repr(void) const {
		return m_bSet ? CFormat("<CInt: %d>", m_iVal) : CString("<CInt: unset>");
	}
	
	// assign
	CInt &operator=(const CInt &p_Obj) {
		m_iVal = p_Obj.m_iVal;
		m_bSet = p_Obj.m_bSet;
		return *this;
	}

	CInt &operator=(const int p_iVal) {
		m_iVal = p_iVal;
		m_bSet = true;
		return *this;
	}
	// unary
	CInt operator+(void) {
		return *this;
	}
	CInt operator-(void) {
		m_iVal *= -1;
		return *this;
	}

	// arithmetic operators
	INT_ARITH_OP(+);	// plus
	INT_ARITH_OP(-);	// minus
	INT_ARITH_OP(*);	// multiply
	INT_ARITH_OP2(/);	// divide
	INT_ARITH_OP2(%);	// modulus

	// compare
	INT_COMP_OPERATOR(==);
	INT_COMP_OPERATOR(!=);
	INT_COMP_OPERATOR(>);
	INT_COMP_OPERATOR(>=);
	INT_COMP_OPERATOR(<);
	INT_COMP_OPERATOR(<=);
};




#endif	// __CINT_H__

