diff options
Diffstat (limited to 'result.h')
-rw-r--r-- | result.h | 558 |
1 files changed, 558 insertions, 0 deletions
diff --git a/result.h b/result.h new file mode 100644 index 0000000..9bb071b --- /dev/null +++ b/result.h @@ -0,0 +1,558 @@ +#ifndef INCLUDE_BLASSIC_RESULT_H +#define INCLUDE_BLASSIC_RESULT_H + +// result.h +// Revision 8-jan-2005 + +#ifdef __BORLANDC__ +#pragma warn -inl +#endif + +#include "blassic.h" + +#include "error.h" + +#include <math.h> + +// Now the aritmetic operations between integers are converted +// to floating point, to avoid truncations on integer overflow. +// Comment the next #define to get the old behaviour. + +#define CONVERTNUMBER + +namespace blassic { + +namespace result { + +inline double round (double n) +{ + double intpart; + double fracpart= modf (n, & intpart); + if (fracpart >= 0.5) + return intpart + 1; + else if (fracpart <= -0.5) + return intpart - 1; + else + return intpart; +} + +inline BlInteger NumberToInteger (BlNumber n) +{ + n= round (n); + if (n > BlIntegerMax || n < BlIntegerMin) + throw ErrOverflow; + return static_cast <BlInteger> (n); +} + +class BlResult { + VarType vartype; + std::string varstr; + union N { + BlNumber varnumber; + BlInteger varinteger; + N () { } + N (BlNumber num) + { + varnumber= num; + } + N (BlInteger inum) + { + varinteger= inum; + } + } n; + void integertonumber () + { + vartype= VarNumber; + n.varnumber= n.varinteger; + } + void numbertointeger () + { + vartype= VarInteger; + //n.varinteger= BlInteger (n.varnumber); + n.varinteger= NumberToInteger (n.varnumber); + } +public: + BlResult () : + vartype (VarUndef) + { } + BlResult (BlNumber num) : + vartype (VarNumber), + n (num) + { } + BlResult (BlInteger inum) : + vartype (VarInteger), + n (inum) + { } + BlResult (const std::string & str) : + vartype (VarString), + varstr (str) + { } + BlResult (const BlResult & br) : + vartype (br.vartype) + { + switch (vartype) + { + case VarString: + varstr= br.varstr; + break; + case VarNumber: + n.varnumber= br.n.varnumber; + break; + case VarInteger: + n.varinteger= br.n.varinteger; + break; + default: + ; + } + } + void assign (BlNumber num) + { + vartype= VarNumber; + n.varnumber= num; + } + void assign (BlInteger inum) + { + vartype= VarInteger; + n.varinteger= inum; + } + void assign (const std::string & str) + { + vartype= VarString; + varstr= str; + } + void operator = (const BlResult & br) + { + vartype= br.vartype; + switch (vartype) + { + case VarString: + varstr= br.varstr; + break; + case VarNumber: + n.varnumber= br.n.varnumber; + break; + case VarInteger: + n.varinteger= br.n.varinteger; + break; + default: + ; + } + } + VarType type () const { return vartype; } + bool is_numeric () const { return is_numeric_type (vartype); } + const std::string & str () const + { + if (vartype != VarString) + throw ErrMismatch; + return varstr; + } + std::string & str () + { + if (vartype != VarString) + throw ErrMismatch; + return varstr; + } + BlNumber number () const + { + switch (vartype) + { + case VarNumber: + return n.varnumber; + case VarInteger: + return n.varinteger; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + } + BlInteger integer () const + { + switch (vartype) + { + case VarNumber: + //return BlInteger (n.varnumber); + return NumberToInteger (n.varnumber); + case VarInteger: + return n.varinteger; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + } + bool tobool () const + { + switch (vartype) + { + case VarNumber: + return n.varnumber != 0.0; + case VarInteger: + return n.varinteger != 0; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + } + BlNumber numberdenom () const + { + switch (vartype) + { + case VarNumber: + if (! n.varnumber) + throw ErrDivZero; + return n.varnumber; + case VarInteger: + if (! n.varinteger) + throw ErrDivZero; + return n.varinteger; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + } + BlInteger integerdenom () const + { + switch (vartype) + { + case VarNumber: + { + BlInteger inum= NumberToInteger (n.varnumber); + if (! inum) + throw ErrDivZero; + return inum; + } + case VarInteger: + if (! n.varinteger) + throw ErrDivZero; + return n.varinteger; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + } + /*BlResult & */ void operator = (const std::string & nstr) + { + vartype= VarString; + varstr= nstr; + //return * this; + } + /*BlResult & */ void operator = (BlNumber num) + { + vartype= VarNumber; + n.varnumber= num; + //varstr.erase (); + //return * this; + } + // Do not define operator = for BlInteger, + // it will be a redefinition for one of + // long, int or short. + /*BlResult & */ void operator = (long inum) + { + vartype= VarInteger; + n.varinteger= inum; + //varstr.erase (); + //return * this; + } + void operator = (unsigned long inum) + { + vartype= VarInteger; + n.varinteger= inum; + } + /*BlResult & */ void operator = (int inum) + { + vartype= VarInteger; + n.varinteger= inum; + //varstr.erase (); + //return * this; + } + /*BlResult & */ void operator = (unsigned int inum) + { + vartype= VarInteger; + n.varinteger= inum; + //varstr.erase (); + //return * this; + } + /*BlResult & */ void operator = (short inum) + { + vartype= VarInteger; + n.varinteger= inum; + } + /*BlResult & */ void operator = (unsigned short inum) + { + vartype= VarInteger; + n.varinteger= inum; + } + #if 0 + /*BlResult & */ void operator = (size_t inum) + { + vartype= VarInteger; + n.varinteger= inum; + //varstr.erase (); + //return * this; + } + #endif + /*BlResult & */ void operator += (const BlResult & br) + { + switch (vartype) + { + case VarString: + varstr+= br.str (); + break; + case VarNumber: + n.varnumber+= br.number (); + break; + case VarInteger: + #ifndef CONVERTNUMBER + switch (br.vartype) + { + case VarInteger: + n.varinteger+= br.integer (); + break; + default: + integertonumber (); + n.varnumber+= br.number (); + } + #else + assign (n.varinteger + br.number () ); + #endif + break; + default: + throw ErrBlassicInternal; + } + //return * this; + } + /*BlResult & */ void operator -= (const BlResult & br) + { + switch (vartype) + { + case VarNumber: + n.varnumber-= br.number (); + break; + case VarInteger: + #ifndef CONVERTNUMBER + switch (br.vartype) + { + case VarInteger: + n.varinteger-= br.integer (); + break; + default: + vartype= VarNumber; + n.varnumber= n.varinteger; + n.varnumber-= br.number (); + } + #else + assign (n.varinteger - br.number () ); + #endif + break; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + //return * this; + } + /*BlResult & */ void operator *= (const BlResult & br) + { + switch (vartype) + { + case VarNumber: + n.varnumber*= br.number (); + break; + case VarInteger: + #ifndef CONVERTNUMBER + switch (br.vartype) + { + case VarInteger: + n.varinteger*= br.integer (); + break; + default: + integertonumber (); + n.varnumber*= br.number (); + } + #else + assign (n.varinteger * br.number () ); + #endif + break; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + //return * this; + } + /*BlResult & */ void operator /= (const BlResult & br) + { + switch (vartype) + { + case VarInteger: + #ifndef CONVERTNUMBER + integertonumber (); + #else + assign (n.varinteger / br.numberdenom () ); + break; + #endif + case VarNumber: + { + BlNumber num= br.number (); + if (num == 0) + throw ErrDivZero; + n.varnumber/= num; + } + break; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + //return * this; + } + /*BlResult & */ void operator %= (const BlResult & br) + { + switch (vartype) + { + case VarInteger: + n.varinteger= n.varinteger % br.integerdenom (); + break; + case VarNumber: + assign (NumberToInteger (n.varnumber) % + br.integerdenom () ); + break; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + //return * this; + } + void integerdivideby (const BlResult & br) + { + switch (vartype) + { + case VarInteger: + n.varinteger/= br.integerdenom (); + break; + case VarNumber: + assign (NumberToInteger (n.varnumber) / + br.integerdenom () ); + break; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + } + BlResult operator - () + { + switch (vartype) + { + case VarNumber: + return BlResult (-n.varnumber); + case VarInteger: + #ifndef CONVERTNUMBER + return BlResult (-n.varinteger); + #else + return BlResult (-number () ); + #endif + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + } + bool operator == (const BlResult & br) + { + switch (vartype) + { + case VarString: + return varstr == br.str (); + case VarNumber: + return n.varnumber == br.number (); + case VarInteger: + switch (br.vartype) + { + case VarInteger: + return n.varinteger == br.n.varinteger; + case VarNumber: + return n.varinteger == br.n.varnumber; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + default: + throw ErrBlassicInternal; + } + } + bool operator != (const BlResult & br) + { + return ! operator == (br); + } + bool operator < (const BlResult & br) + { + switch (vartype) + { + case VarString: + return varstr < br.str (); + case VarNumber: + return n.varnumber < br.number (); + case VarInteger: + switch (br.vartype) + { + case VarInteger: + return n.varinteger < br.n.varinteger; + case VarNumber: + return n.varinteger < br.n.varnumber; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + default: + throw ErrBlassicInternal; + } + } + bool operator <= (const BlResult & br) + { + switch (vartype) + { + case VarString: + return varstr <= br.str (); + case VarNumber: + return n.varnumber <= br.number (); + case VarInteger: + switch (br.vartype) + { + case VarInteger: + return n.varinteger <= br.n.varinteger; + case VarNumber: + return n.varinteger <= br.n.varnumber; + case VarString: + throw ErrMismatch; + default: + throw ErrBlassicInternal; + } + default: + throw ErrBlassicInternal; + } + } + bool operator > (const BlResult & br) + { + return ! operator <= (br); + } + bool operator >= (const BlResult & br) + { + return ! operator < (br); + } +}; + +} // namespace result + +} // namespace blassic + +#endif + +// Fin de result.h |