#include "variable.h" #include #include typedef Bu::ExceptionBase VariableException; Variable::Variable() : eType( tNull ), iValue( 0 ) { } Variable::Variable( const Variable &src ) : eType( tNull ), iValue( 0 ) { (*this) = src; } Variable::Variable( Type eType ) : eType( eType ), iValue( 0 ) { initType(); } Variable::Variable( int64_t iValue ) : eType( tInt ), iValue( iValue ) { } Variable::Variable( double fValue ) : eType( tFloat ), fValue( fValue ) { } Variable::Variable( bool bValue ) : eType( tBool ), bValue( bValue ) { } Variable::Variable( const Bu::String &sValue ) : eType( tString ), iValue( 0 ) { this->sValue = new Bu::String( sValue ); } Variable::~Variable() { deinitType(); } Variable Variable::newSituationName( const Bu::String &s ) { Variable v( tSituation ); (*v.sValue) = s; return v; } Variable Variable::to( Type e ) const { if( e == eType ) return *this; switch( eType ) { case tNull: switch( e ) { case tNull: break; case tBool: break; case tInt: break; case tFloat: break; case tString: return Variable("(null)"); case tList: break; case tDictionary: break; } break; case tBool: switch( e ) { case tNull: break; case tBool: break; case tInt: break; case tFloat: break; case tString: return bValue?Variable("true"):Variable("false"); case tList: break; case tDictionary: break; } break; case tInt: switch( e ) { case tNull: break; case tBool: break; case tInt: break; case tFloat: return Variable( (double)iValue ); case tString: return Variable( Bu::String("%1").arg( iValue ) ); case tList: break; case tDictionary: break; } break; case tFloat: switch( e ) { case tNull: break; case tBool: break; case tInt: return Variable( (int64_t)fValue ); case tFloat: break; case tString: return Variable( Bu::String("%1").arg( fValue ) ); case tList: break; case tDictionary: break; } break; case tString: switch( e ) { case tNull: break; case tBool: break; case tInt: return Variable( strtoll(sValue->getStr(), NULL, 10 ) ); case tFloat: return Variable( strtod(sValue->getStr(), NULL ) ); case tString: break; case tList: break; case tDictionary: break; } break; case tList: switch( e ) { case tNull: break; case tBool: break; case tInt: break; case tFloat: break; case tString: break; case tList: break; case tDictionary: break; } break; case tDictionary: switch( e ) { case tNull: break; case tBool: break; case tInt: break; case tFloat: break; case tString: break; case tList: break; case tDictionary: break; } break; } throw VariableException("Could not convert from %d to %d.\n", eType, e ); } Variable &Variable::operator=( const Variable &rhs ) { deinitType(); eType = rhs.eType; initType(); switch( eType ) { case tNull: break; case tBool: bValue = rhs.bValue; break; case tInt: iValue = rhs.iValue; break; case tFloat: fValue = rhs.fValue; break; case tString: case tSituation: (*sValue) = *rhs.sValue; break; case tList: (*lValue) = *rhs.lValue; break; case tDictionary: (*hValue) = *rhs.hValue; break; } } Variable &Variable::operator+=( const Variable &rhs ) { switch( eType ) { case tNull: throw VariableException("You cannot add nulls."); case tBool: throw VariableException("You cannot add bools."); case tInt: switch( rhs.eType ) { case tInt: iValue += rhs.iValue; break; case tFloat: { double dTmp = iValue; eType = tFloat; fValue = dTmp + rhs.fValue; } break; default: throw VariableException("Int += invalid..."); } break; case tFloat: switch( rhs.eType ) { case tInt: fValue += rhs.iValue; break; case tFloat: fValue += rhs.fValue; break; default: throw VariableException("Int += invalid..."); } break; case tString: (*sValue).append( *(rhs.to( tString ).sValue) ); break; case tSituation: throw VariableException("You cannot add situations."); break; } return *this; } /* Variable &Variable::operator-=( const Variable &rhs ); Variable &Variable::operator*=( const Variable &rhs ); Variable &Variable::operator/=( const Variable &rhs ); */ Variable Variable::operator+( const Variable &rhs ) const { if( eType != rhs.eType ) { throw VariableException("Adding between dissimilar types is not yet supported."); } else { switch( eType ) { case tNull: throw VariableException("You cannot add nulls."); case tBool: throw VariableException("You cannot add booleans."); case tInt: return Variable( iValue + rhs.iValue ); case tFloat: return Variable( fValue + rhs.fValue ); case tString: return Variable( *sValue + *rhs.sValue ); case tList: { Variable vRet( tList ); vRet.lValue->append( *lValue ); vRet.lValue->append( *rhs.lValue ); return vRet; } case tDictionary: throw VariableException("You cannot add dictionaries."); break; case tSituation: throw VariableException("You cannot add situations."); } } } /* Variable Variable::operator-( const Variable &rhs ) const; Variable Variable::operator*( const Variable &rhs ) const; Variable Variable::operator/( const Variable &rhs ) const; */ bool Variable::operator==( const Variable &rhs ) const { if( eType != rhs.eType ) return false; switch( eType ) { case tNull: return true; case tBool: return bValue == rhs.bValue; case tInt: return iValue == rhs.iValue; case tFloat: return fValue == rhs.fValue; case tString: case tSituation: return (*sValue) == (*rhs.sValue); case tList: return (*lValue) == (*rhs.lValue); case tDictionary: return (*hValue) == (*rhs.hValue); } } bool Variable::operator!=( const Variable &rhs ) const { return !(*this == rhs); } /* Variable &Variable::operator>( const Variable &rhs ); Variable &Variable::operator<( const Variable &rhs ); Variable &Variable::operator>=( const Variable &rhs ); Variable &Variable::operator<=( const Variable &rhs ); */ void Variable::initType() { iValue = 0; switch( eType ) { case tString: case tSituation: sValue = new Bu::String(); break; case tList: lValue = new VList(); break; case tDictionary: hValue = new VHash(); break; } } void Variable::deinitType() { switch( eType ) { case tString: case tSituation: delete sValue; break; case tList: delete lValue; break; case tDictionary: delete hValue; break; } iValue = 0; } template<> uint32_t Bu::__calcHashCode( const Variable &k ) { switch( k.getType() ) { case Variable::tNull: return 0; case Variable::tInt: return k.iValue; case Variable::tFloat: return k.fValue; case Variable::tString: case Variable::tSituation: return Bu::__calcHashCode( *k.sValue ); case Variable::tList: throw VariableException("You cannot use a list as a key in a dictionary."); case Variable::tDictionary: throw VariableException("You cannot use a dictionary as a key in a dictionary."); } } template<> bool Bu::__cmpHashKeys( const Variable &a, const Variable &b ) { return a == b; } Bu::Formatter &operator<<( Bu::Formatter &f, const Variable &v ) { switch( v.eType ) { case Variable::tNull: return f << "(null)"; case Variable::tBool: return f << v.bValue; case Variable::tInt: return f << v.iValue; case Variable::tFloat: return f << v.fValue; case Variable::tString: return f << '"' << *v.sValue << '"'; case Variable::tSituation: return f << "<<" << *v.sValue << ">>"; case Variable::tList: return f << *v.lValue; case Variable::tDictionary: return f << *v.hValue; } return f << "ERROR"; }