mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00

- A variant now contains a source reference, which indicates where it came from. This is used to determine whether 'H' is a priority or just a word.
1722 lines
60 KiB
C++
1722 lines
60 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright 2013 - 2014, Paul Beckingham, Federico Hernandez.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
//
|
|
// http://www.opensource.org/licenses/mit-license.php
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <cmake.h>
|
|
#include <sstream>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <Variant.h>
|
|
#include <ISO8601.h>
|
|
#include <Date.h>
|
|
#include <Duration.h>
|
|
#include <RX.h>
|
|
#include <text.h>
|
|
|
|
std::string Variant::dateFormat = "";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::Variant ()
|
|
: _type (type_unknown)
|
|
, _bool (false)
|
|
, _integer (0)
|
|
, _real (0.0)
|
|
, _string ("")
|
|
, _date (0)
|
|
, _duration (0)
|
|
, _source ("")
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::Variant (const Variant& other)
|
|
: _type (type_unknown)
|
|
, _bool (false)
|
|
, _integer (0)
|
|
, _real (0.0)
|
|
, _string ("")
|
|
, _date (0)
|
|
, _duration (0)
|
|
, _source ("")
|
|
{
|
|
*this = other;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::Variant (const bool value)
|
|
: _type (Variant::type_boolean)
|
|
, _bool (value)
|
|
, _integer (0)
|
|
, _real (0.0)
|
|
, _string ("")
|
|
, _date (0)
|
|
, _duration (0)
|
|
, _source ("")
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::Variant (const int value)
|
|
: _type (Variant::type_integer)
|
|
, _bool (false)
|
|
, _integer (value)
|
|
, _real (0.0)
|
|
, _string ("")
|
|
, _date (0)
|
|
, _duration (0)
|
|
, _source ("")
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::Variant (const double value)
|
|
: _type (Variant::type_real)
|
|
, _bool (false)
|
|
, _integer (0)
|
|
, _real (value)
|
|
, _string ("")
|
|
, _date (0)
|
|
, _duration (0)
|
|
, _source ("")
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::Variant (const std::string& value)
|
|
: _type (Variant::type_string)
|
|
, _bool (false)
|
|
, _integer (0)
|
|
, _real (0.0)
|
|
, _string (value)
|
|
, _date (0)
|
|
, _duration (0)
|
|
, _source ("")
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::Variant (const char* value)
|
|
: _type (Variant::type_string)
|
|
, _bool (false)
|
|
, _integer (0)
|
|
, _real (0.0)
|
|
, _string (std::string (value))
|
|
, _date (0)
|
|
, _duration (0)
|
|
, _source ("")
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::Variant (const time_t value, const enum type new_type /*=type_date*/)
|
|
: _type (new_type)
|
|
, _bool (false)
|
|
, _integer (0)
|
|
, _real (0.0)
|
|
, _string ("")
|
|
, _date (0)
|
|
, _duration (0)
|
|
, _source ("")
|
|
{
|
|
switch (new_type)
|
|
{
|
|
case type_date: _date = value; break;
|
|
case type_duration: _duration = value; break;
|
|
default:
|
|
throw std::string ("Cannot instantiate this type with a time_t value.");
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::~Variant ()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void Variant::source (const std::string& input)
|
|
{
|
|
_source = input;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
std::string Variant::source () const
|
|
{
|
|
return _source;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant& Variant::operator= (const Variant& other)
|
|
{
|
|
if (this != &other)
|
|
{
|
|
_type = other._type;
|
|
_bool = other._bool;
|
|
_integer = other._integer;
|
|
_real = other._real;
|
|
_string = other._string;
|
|
_date = other._date;
|
|
_duration = other._duration;
|
|
_source = other._source;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator&& (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
left.cast (type_boolean);
|
|
right.cast (type_boolean);
|
|
|
|
return left._bool && right._bool;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator|| (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
left.cast (type_boolean);
|
|
right.cast (type_boolean);
|
|
|
|
return left._bool || right._bool;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator_xor (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
left.cast (type_boolean);
|
|
right.cast (type_boolean);
|
|
|
|
return (left._bool && !right._bool) ||
|
|
(!left._bool && right._bool);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator< (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
switch (left._type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot compare unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: return !left._bool && right._bool;
|
|
case type_integer: left.cast (type_integer); return left._integer < right._integer;
|
|
case type_real: left.cast (type_real); return left._real < right._real;
|
|
case type_string: left.cast (type_string); return left._string < right._string;
|
|
case type_date: left.cast (type_date); return left._date < right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration < right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_integer); return left._integer < right._integer;
|
|
case type_integer: return left._integer < right._integer;
|
|
case type_real: left.cast (type_real); return left._real < right._real;
|
|
case type_string: left.cast (type_string); return left._string < right._string;
|
|
case type_date: left.cast (type_date); return left._date < right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration < right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_real); return left._real < right._real;
|
|
case type_integer: right.cast (type_real); return left._real < right._real;
|
|
case type_real: return left._real < right._real;
|
|
case type_string: left.cast (type_string); return left._string < right._string;
|
|
case type_date: left.cast (type_date); return left._date < right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration < right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_string); return left._string < right._string;
|
|
case type_integer: right.cast (type_string); return left._string < right._string;
|
|
case type_real: right.cast (type_string); return left._string < right._string;
|
|
case type_string: return left._string < right._string;
|
|
case type_date: left.cast (type_date); return left._date < right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration < right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_date:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_date); return left._date < right._date;
|
|
case type_integer: right.cast (type_date); return left._date < right._date;
|
|
case type_real: right.cast (type_date); return left._date < right._date;
|
|
case type_string: right.cast (type_date); return left._date < right._date;
|
|
case type_date: return left._date < right._date;
|
|
case type_duration: return left._date < right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_duration); return left._duration < right._duration;
|
|
case type_integer: right.cast (type_duration); return left._duration < right._duration;
|
|
case type_real: right.cast (type_duration); return left._duration < right._duration;
|
|
case type_string: right.cast (type_duration); return left._duration < right._duration;
|
|
case type_date: return left._duration < right._date;
|
|
case type_duration: return left._duration < right._duration;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator<= (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
switch (left._type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot compare unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: return !left._bool || right._bool;
|
|
case type_integer: left.cast (type_integer); return left._integer <= right._integer;
|
|
case type_real: left.cast (type_real); return left._real <= right._real;
|
|
case type_string: left.cast (type_string); return left._string <= right._string;
|
|
case type_date: left.cast (type_date); return left._date <= right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration <= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_integer); return left._integer <= right._integer;
|
|
case type_integer: return left._integer <= right._integer;
|
|
case type_real: left.cast (type_real); return left._real <= right._real;
|
|
case type_string: left.cast (type_string); return left._string <= right._string;
|
|
case type_date: left.cast (type_date); return left._date <= right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration <= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_real); return left._real <= right._real;
|
|
case type_integer: right.cast (type_real); return left._real <= right._real;
|
|
case type_real: return left._real <= right._real;
|
|
case type_string: left.cast (type_string); return left._string <= right._string;
|
|
case type_date: left.cast (type_date); return left._date <= right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration <= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_string); return left._string <= right._string;
|
|
case type_integer: right.cast (type_string); return left._string <= right._string;
|
|
case type_real: right.cast (type_string); return left._string <= right._string;
|
|
case type_string: return left._string <= right._string;
|
|
case type_date: left.cast (type_date); return left._date <= right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration <= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_date:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_date); return left._date <= right._date;
|
|
case type_integer: right.cast (type_date); return left._date <= right._date;
|
|
case type_real: right.cast (type_date); return left._date <= right._date;
|
|
case type_string: right.cast (type_date); return left._date <= right._date;
|
|
case type_date: return left._date <= right._date;
|
|
case type_duration: return left._date <= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_duration); return left._duration <= right._duration;
|
|
case type_integer: right.cast (type_duration); return left._duration <= right._duration;
|
|
case type_real: right.cast (type_duration); return left._duration <= right._duration;
|
|
case type_string: right.cast (type_duration); return left._duration <= right._duration;
|
|
case type_date: return left._duration <= right._date;
|
|
case type_duration: return left._duration <= right._duration;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator> (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
switch (left._type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot compare unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: return !left._bool && right._bool;
|
|
case type_integer: left.cast (type_integer); return left._integer > right._integer;
|
|
case type_real: left.cast (type_real); return left._real > right._real;
|
|
case type_string: left.cast (type_string); return left._string > right._string;
|
|
case type_date: left.cast (type_date); return left._date > right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration > right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_integer); return left._integer > right._integer;
|
|
case type_integer: return left._integer > right._integer;
|
|
case type_real: left.cast (type_real); return left._real > right._real;
|
|
case type_string: left.cast (type_string); return left._string > right._string;
|
|
case type_date: left.cast (type_date); return left._date > right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration > right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_real); return left._real > right._real;
|
|
case type_integer: right.cast (type_real); return left._real > right._real;
|
|
case type_real: return left._real > right._real;
|
|
case type_string: left.cast (type_string); return left._string > right._string;
|
|
case type_date: left.cast (type_date); return left._date > right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration > right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_string); return left._string > right._string;
|
|
case type_integer: right.cast (type_string); return left._string > right._string;
|
|
case type_real: right.cast (type_string); return left._string > right._string;
|
|
case type_string: return left._string > right._string;
|
|
case type_date: left.cast (type_date); return left._date > right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration > right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_date:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_date); return left._date > right._date;
|
|
case type_integer: right.cast (type_date); return left._date > right._date;
|
|
case type_real: right.cast (type_date); return left._date > right._date;
|
|
case type_string: right.cast (type_date); return left._date > right._date;
|
|
case type_date: return left._date > right._date;
|
|
case type_duration: return left._date > right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_duration); return left._duration > right._duration;
|
|
case type_integer: right.cast (type_duration); return left._duration > right._duration;
|
|
case type_real: right.cast (type_duration); return left._duration > right._duration;
|
|
case type_string: right.cast (type_duration); return left._duration > right._duration;
|
|
case type_date: return left._duration > right._date;
|
|
case type_duration: return left._duration > right._duration;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator>= (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
switch (left._type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot compare unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: return left._bool || !right._bool;
|
|
case type_integer: left.cast (type_integer); return left._integer >= right._integer;
|
|
case type_real: left.cast (type_real); return left._real >= right._real;
|
|
case type_string: left.cast (type_string); return left._string >= right._string;
|
|
case type_date: left.cast (type_date); return left._date >= right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration >= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_integer); return left._integer >= right._integer;
|
|
case type_integer: return left._integer >= right._integer;
|
|
case type_real: left.cast (type_real); return left._real >= right._real;
|
|
case type_string: left.cast (type_string); return left._string >= right._string;
|
|
case type_date: left.cast (type_date); return left._date >= right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration >= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_real); return left._real >= right._real;
|
|
case type_integer: right.cast (type_real); return left._real >= right._real;
|
|
case type_real: return left._real >= right._real;
|
|
case type_string: left.cast (type_string); return left._string >= right._string;
|
|
case type_date: left.cast (type_date); return left._date >= right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration >= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_string); return left._string >= right._string;
|
|
case type_integer: right.cast (type_string); return left._string >= right._string;
|
|
case type_real: right.cast (type_string); return left._string >= right._string;
|
|
case type_string: return left._string >= right._string;
|
|
case type_date: left.cast (type_date); return left._date >= right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration >= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_date:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_date); return left._date >= right._date;
|
|
case type_integer: right.cast (type_date); return left._date >= right._date;
|
|
case type_real: right.cast (type_date); return left._date >= right._date;
|
|
case type_string: right.cast (type_date); return left._date >= right._date;
|
|
case type_date: return left._date >= right._date;
|
|
case type_duration: return left._date >= right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot compare unknown type");
|
|
case type_boolean: right.cast (type_duration); return left._duration >= right._duration;
|
|
case type_integer: right.cast (type_duration); return left._duration >= right._duration;
|
|
case type_real: right.cast (type_duration); return left._duration >= right._duration;
|
|
case type_string: right.cast (type_duration); return left._duration >= right._duration;
|
|
case type_date: return left._duration >= right._date;
|
|
case type_duration: return left._duration >= right._duration;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator== (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
switch (left._type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot equate unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: return left._bool == right._bool;
|
|
case type_integer: left.cast (type_integer); return left._integer == right._integer;
|
|
case type_real: left.cast (type_real); return left._real == right._real;
|
|
case type_string: left.cast (type_string); return left._string == right._string;
|
|
case type_date: left.cast (type_date); return left._date == right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_integer); return left._integer == right._integer;
|
|
case type_integer: return left._integer == right._integer;
|
|
case type_real: left.cast (type_real); return left._real == right._real;
|
|
case type_string: left.cast (type_string); return left._string == right._string;
|
|
case type_date: left.cast (type_date); return left._date == right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_real); return left._real == right._real;
|
|
case type_integer: right.cast (type_real); return left._real == right._real;
|
|
case type_real: return left._real == right._real;
|
|
case type_string: left.cast (type_string); return left._string == right._string;
|
|
case type_date: left.cast (type_date); return left._date == right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_string); return left._string == right._string;
|
|
case type_integer: right.cast (type_string); return left._string == right._string;
|
|
case type_real: right.cast (type_string); return left._string == right._string;
|
|
case type_string: return left._string == right._string;
|
|
case type_date: left.cast (type_date); return left._date == right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_date:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_date); return left._date == right._date;
|
|
case type_integer: right.cast (type_date); return left._date == right._date;
|
|
case type_real: right.cast (type_date); return left._date == right._date;
|
|
case type_string: right.cast (type_date); return left._date == right._date;
|
|
case type_date: return left._date == right._date;
|
|
case type_duration: return left._date == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_duration); return left._duration == right._duration;
|
|
case type_integer: right.cast (type_duration); return left._duration == right._duration;
|
|
case type_real: right.cast (type_duration); return left._duration == right._duration;
|
|
case type_string: right.cast (type_duration); return left._duration == right._duration;
|
|
case type_date: return left._duration == right._date;
|
|
case type_duration: return left._duration == right._duration;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator!= (const Variant& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator_match (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
left.cast (type_string);
|
|
right.cast (type_string);
|
|
|
|
RX r (right._string, true);
|
|
return r.match (left._string);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator_nomatch (const Variant& other) const
|
|
{
|
|
return ! operator_match (other);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Partial match is mostly a clone of operator==, but with some overrides:
|
|
//
|
|
// date <partial> date --> same day check
|
|
// string <partial> string --> leftmost
|
|
//
|
|
bool Variant::operator_partial (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
Variant right (other);
|
|
|
|
switch (left._type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot equate unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: return left._bool == right._bool;
|
|
case type_integer: left.cast (type_integer); return left._integer == right._integer;
|
|
case type_real: left.cast (type_real); return left._real == right._real;
|
|
case type_string: left.cast (type_string); return left._string == right._string;
|
|
// TODO Implement same-day comparison.
|
|
case type_date: left.cast (type_date); return left._date == right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_integer); return left._integer == right._integer;
|
|
case type_integer: return left._integer == right._integer;
|
|
case type_real: left.cast (type_real); return left._real == right._real;
|
|
case type_string: left.cast (type_string); return left._string == right._string;
|
|
// TODO Implement same-day comparison.
|
|
case type_date: left.cast (type_date); return left._date == right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_real); return left._real == right._real;
|
|
case type_integer: right.cast (type_real); return left._real == right._real;
|
|
case type_real: return left._real == right._real;
|
|
case type_string: left.cast (type_string); return left._string == right._string;
|
|
// TODO Implement same-day comparison.
|
|
case type_date: left.cast (type_date); return left._date == right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_string); return left._string == right._string;
|
|
case type_integer: right.cast (type_string); return left._string == right._string;
|
|
case type_real: right.cast (type_string); return left._string == right._string;
|
|
case type_string:
|
|
{
|
|
int left_length = left._string.length ();
|
|
if (left_length == 0)
|
|
return false;
|
|
|
|
int right_length = right._string.length ();
|
|
if (right_length == 0)
|
|
return false;
|
|
|
|
if (left_length < right_length)
|
|
return false;
|
|
|
|
return left._string.substr (0, right_length) == right._string;
|
|
}
|
|
// TODO Implement same-day comparison.
|
|
case type_date: left.cast (type_date); return left._date == right._date;
|
|
case type_duration: left.cast (type_duration); return left._duration == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_date:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
// TODO Implement same-day comparison.
|
|
case type_boolean: right.cast (type_date); return left._date == right._date;
|
|
// TODO Implement same-day comparison.
|
|
case type_integer: right.cast (type_date); return left._date == right._date;
|
|
// TODO Implement same-day comparison.
|
|
case type_real: right.cast (type_date); return left._date == right._date;
|
|
// TODO Implement same-day comparison.
|
|
case type_string: right.cast (type_date); return left._date == right._date;
|
|
// TODO Implement same-day comparison.
|
|
case type_date: return left._date == right._date;
|
|
// TODO Implement same-day comparison.
|
|
case type_duration: return left._date == right._duration;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot equate unknown type");
|
|
case type_boolean: right.cast (type_duration); return left._duration == right._duration;
|
|
case type_integer: right.cast (type_duration); return left._duration == right._duration;
|
|
case type_real: right.cast (type_duration); return left._duration == right._duration;
|
|
case type_string: right.cast (type_duration); return left._duration == right._duration;
|
|
// TODO Implement same-day comparison.
|
|
case type_date: return left._duration == right._date;
|
|
// TODO Implement same-day comparison.
|
|
case type_duration: return left._duration == right._duration;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator_hastag (const Variant& other) const
|
|
{
|
|
Variant left (*this); // tags
|
|
Variant right (other); // tag
|
|
|
|
left.cast (type_string);
|
|
right.cast (type_string);
|
|
|
|
std::vector <std::string> individual;
|
|
split (individual, left._string, ',');
|
|
|
|
std::vector <std::string>::iterator i;
|
|
for (i = individual.begin (); i != individual.end (); ++i)
|
|
if (*i == right._string)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator_notag (const Variant& other) const
|
|
{
|
|
return ! operator_hastag (other);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::operator! () const
|
|
{
|
|
Variant left (*this);
|
|
left.cast (type_boolean);
|
|
return ! left._bool;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant& Variant::operator^= (const Variant& other)
|
|
{
|
|
switch (_type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot exponentiate unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
throw std::string ("Cannot exponentiate Boolean values");
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (other._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot exponentiate unknown type");
|
|
case type_boolean: throw std::string ("Cannot exponentiate Booleans");
|
|
case type_integer: _integer = (int) pow (static_cast<double>(_integer), static_cast<double>(other._integer)); break;
|
|
case type_real: throw std::string ("Cannot exponentiate to a non-integer power");
|
|
case type_string: throw std::string ("Cannot exponentiate strings");
|
|
case type_date: throw std::string ("Cannot exponentiate dates");
|
|
case type_duration: throw std::string ("Cannot exponentiate durations");
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (other._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot exponentiate unknown type");
|
|
case type_boolean: throw std::string ("Cannot exponentiate Booleans");
|
|
case type_integer: _real = pow (_real, static_cast<double>(other._integer)); break;
|
|
case type_real: throw std::string ("Cannot exponentiate to a non-integer power");
|
|
case type_string: throw std::string ("Cannot exponentiate strings");
|
|
case type_date: throw std::string ("Cannot exponentiate dates");
|
|
case type_duration: throw std::string ("Cannot exponentiate durations");
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
throw std::string ("Cannot perform exponentiation on string values");
|
|
break;
|
|
|
|
case type_date:
|
|
throw std::string ("Cannot perform exponentiation on date values");
|
|
break;
|
|
|
|
case type_duration:
|
|
throw std::string ("Cannot perform exponentiation on duration values");
|
|
break;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant Variant::operator^ (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
left ^= other;
|
|
return left;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant& Variant::operator-= (const Variant& other)
|
|
{
|
|
Variant right (other);
|
|
|
|
switch (_type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot subtract unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
throw std::string ("Cannot subtract from a Boolean value");
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot subtract unknown type");
|
|
case type_boolean: right.cast (type_integer); _integer -= right._integer; break;
|
|
case type_integer: _integer -= right._integer; break;
|
|
case type_real: cast (type_real); _real -= right._real; break;
|
|
case type_string: throw std::string ("Cannot subtract strings");
|
|
case type_date: cast (type_date); _date -= right._date; break;
|
|
case type_duration: cast (type_duration); _duration -= right._duration; break;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot subtract unknown type");
|
|
case type_boolean: right.cast (type_real); _real -= right._real; break;
|
|
case type_integer: right.cast (type_real); _real -= right._real; break;
|
|
case type_real: _real -= right._real; break;
|
|
case type_string: throw std::string ("Cannot subtract strings");
|
|
case type_date: right.cast (type_real); _real -= right._real; break;
|
|
case type_duration: right.cast (type_real); _real -= right._real; break;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
throw std::string ("Cannot subtract strings");
|
|
break;
|
|
|
|
case type_date:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot subtract unknown type");
|
|
case type_boolean: right.cast (type_integer); _date -= right._integer; break;
|
|
case type_integer: _date -= right._integer; break;
|
|
case type_real: _date -= (int) right._real; break;
|
|
case type_string: throw std::string ("Cannot subtract strings");
|
|
case type_date: cast (type_duration); _duration -= right._date; break;
|
|
case type_duration: _date -= right._duration; break;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot subtract unknown type");
|
|
case type_boolean: right.cast (type_integer); _duration -= right._integer; break;
|
|
case type_integer: _duration -= right._integer; break;
|
|
case type_real: _duration -= (int) right._real; break;
|
|
case type_string: throw std::string ("Cannot subtract strings");
|
|
case type_date: throw std::string ("Cannot subtract a date");
|
|
case type_duration: _duration -= right._duration; break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant Variant::operator- (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
left -= other;
|
|
return left;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant& Variant::operator+= (const Variant& other)
|
|
{
|
|
Variant right (other);
|
|
|
|
switch (_type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot add unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot add unknown type");
|
|
case type_boolean: throw std::string ("Cannot add two Boolean values");
|
|
case type_integer: cast (type_integer); _integer += right._integer; break;
|
|
case type_real: cast (type_real); _real += right._real; break;
|
|
case type_string: cast (type_string); _string += right._string; break;
|
|
case type_date: cast (type_date); _date += right._date; break;
|
|
case type_duration: cast (type_duration); _duration += right._duration; break;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot add unknown type");
|
|
case type_boolean: right.cast (type_integer); _integer += right._integer; break;
|
|
case type_integer: _integer += right._integer; break;
|
|
case type_real: cast (type_real); _real += right._real; break;
|
|
case type_string: cast (type_string); _string += right._string; break;
|
|
case type_date: cast (type_date); _date += right._date; break;
|
|
case type_duration: cast (type_duration); _duration += right._duration; break;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot add unknown type");
|
|
case type_boolean: right.cast (type_real); _real += right._real; break;
|
|
case type_integer: right.cast (type_real); _real += right._real; break;
|
|
case type_real: _real += right._real; break;
|
|
case type_string: cast (type_string); _string += right._string; break;
|
|
case type_date:
|
|
_type = type_date;
|
|
_date = (unsigned) (int) _real + right._date;
|
|
break;
|
|
case type_duration:
|
|
_type = type_duration;
|
|
_duration = (unsigned) (int) _real + right._duration;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
_string += (std::string) right;
|
|
break;
|
|
|
|
case type_date:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot add unknown type");
|
|
case type_boolean: right.cast (type_date); _date += right._date; break;
|
|
case type_integer: _date += right._integer; break;
|
|
case type_real: _date += (int) right._real; break;
|
|
case type_string: cast (type_string); _string += right._string; break;
|
|
case type_date: throw std::string ("Cannot add two date values");
|
|
case type_duration: _date += right._duration; break;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot add unknown type");
|
|
case type_boolean: right.cast (type_duration); _duration += right._duration; break;
|
|
case type_integer: _duration += right._integer; break;
|
|
case type_real: _duration += (int) right._real; break;
|
|
case type_string: cast (type_string); _string += right._string; break;
|
|
case type_date: cast (type_date); _date += right._date; break;
|
|
case type_duration: _duration += right._duration; break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant Variant::operator+ (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
left += other;
|
|
return left;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant& Variant::operator*= (const Variant& other)
|
|
{
|
|
Variant right (other);
|
|
|
|
switch (_type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot multiply unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot multiply unknown type");
|
|
case type_boolean: throw std::string ("Cannot multiply Boolean values");
|
|
case type_integer: cast (type_integer); _integer *= right._integer; break;
|
|
case type_real: cast (type_real); _real *= right._real; break;
|
|
case type_string: _string = (_bool ? right._string : ""); _type = type_string; break;
|
|
case type_date: throw std::string ("Cannot multiply date values");
|
|
case type_duration: cast (type_duration); _duration *= right._duration; break;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot multiply unknown type");
|
|
case type_boolean: right.cast (type_integer); _integer *= right._integer; break;
|
|
case type_integer: _integer *= right._integer; break;
|
|
case type_real: cast (type_real); _real *= right._real; break;
|
|
case type_string:
|
|
{
|
|
int limit = _integer;
|
|
// assert (limit < 128);
|
|
_type = type_string;
|
|
_string = "";
|
|
while (limit--)
|
|
_string += right._string;
|
|
}
|
|
break;
|
|
case type_date: throw std::string ("Cannot multiply date values");
|
|
case type_duration: cast (type_duration); _duration *= right._duration; break;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot multiply unknown type");
|
|
case type_boolean: right.cast (type_real); _real *= right._real; break;
|
|
case type_integer: right.cast (type_real); _real *= right._real; break;
|
|
case type_real: _real *= right._real; break;
|
|
case type_string: throw std::string ("Cannot multiply real numbers by strings");
|
|
case type_date: throw std::string ("Cannot multiply real numbers by dates");
|
|
case type_duration:
|
|
_type = type_duration;
|
|
_duration = (time_t) (unsigned) (int) (_real * static_cast<double>(right._duration));
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot multiply unknown type");
|
|
case type_boolean: if (! right._bool) _string = ""; break;
|
|
case type_integer:
|
|
{
|
|
int limit = right._integer - 1;
|
|
// assert (limit < 128);
|
|
std::string fragment = _string;
|
|
while (limit--)
|
|
_string += fragment;
|
|
}
|
|
break;
|
|
case type_real: throw std::string ("Cannot multiply strings by real nubmers");
|
|
case type_string: throw std::string ("Cannot multiply strings by strings");
|
|
case type_date: throw std::string ("Cannot multiply strings by dates");
|
|
case type_duration: throw std::string ("Cannot multiply strings by durations");
|
|
}
|
|
break;
|
|
|
|
case type_date:
|
|
throw std::string ("Cannot multiply date values");
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot multiply unknown type");
|
|
case type_boolean: right.cast (type_duration); _duration *= right._duration; break;
|
|
case type_integer: _duration *= right._integer; break;
|
|
case type_real:
|
|
_duration = (time_t) (unsigned) (int) (static_cast<double>(_duration) * right._real);
|
|
break;
|
|
case type_string: throw std::string ("Cannot multiply durations by strings");
|
|
case type_date: throw std::string ("Cannot multuply durations by dates");
|
|
case type_duration: throw std::string ("Cannot multiply durations by durations");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant Variant::operator* (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
left *= other;
|
|
return left;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant& Variant::operator/= (const Variant& other)
|
|
{
|
|
Variant right (other);
|
|
|
|
switch (_type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot divide unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
throw std::string ("Cannot divide Boolean");
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot divide unknown type");
|
|
case type_boolean: throw std::string ("Cannot divide integer by Boolean");
|
|
case type_integer:
|
|
if (right._integer == 0)
|
|
throw std::string ("Divide by zero");
|
|
_integer /= right._integer;
|
|
break;
|
|
case type_real:
|
|
if (right._real == 0.0)
|
|
throw std::string ("Divide by zero");
|
|
cast (type_real);
|
|
_real /= right._real;
|
|
break;
|
|
case type_string: throw std::string ("Cannot divide integer by string");
|
|
case type_date: throw std::string ("Cannot divide integer by date values");
|
|
case type_duration:
|
|
if (right._duration == 0)
|
|
throw std::string ("Divide by zero");
|
|
_type = type_duration;
|
|
_duration = (time_t) (unsigned) (int) (_integer / right._duration);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot divide unknown type");
|
|
case type_boolean: throw std::string ("Cannot divide real by Boolean");
|
|
case type_integer:
|
|
if (right._integer == 0)
|
|
throw std::string ("Divide by zero");
|
|
_real /= static_cast<double>(right._integer);
|
|
break;
|
|
case type_real:
|
|
if (right._real == 0)
|
|
throw std::string ("Divide by zero");
|
|
_real /= right._real;
|
|
break;
|
|
case type_string: throw std::string ("Cannot divide real numbers by strings");
|
|
case type_date: throw std::string ("Cannot divide real numbers by dates");
|
|
case type_duration:
|
|
if (right._duration == 0)
|
|
throw std::string ("Divide by zero");
|
|
_type = type_duration;
|
|
_duration = (time_t) (unsigned) (int) (_real / right._duration);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
throw std::string ("Cannot divide string values");
|
|
break;
|
|
|
|
case type_date:
|
|
throw std::string ("Cannot divide date values");
|
|
|
|
case type_duration:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot divide unknown type");
|
|
case type_boolean: throw std::string ("Cannot divide duration by Boolean");
|
|
case type_integer:
|
|
if (right._integer == 0)
|
|
throw std::string ("Divide by zero");
|
|
_duration /= right._integer;
|
|
break;
|
|
case type_real:
|
|
if (right._real == 0)
|
|
throw std::string ("Divide by zero");
|
|
_duration = (time_t) (unsigned) (int) (static_cast<double>(_duration) / right._real);
|
|
break;
|
|
case type_string: throw std::string ("Cannot divide durations by strings");
|
|
case type_date: throw std::string ("Cannot divide durations by dates");
|
|
case type_duration: throw std::string ("Cannot divide durations by durations");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant Variant::operator/ (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
left /= other;
|
|
return left;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant& Variant::operator%= (const Variant& other)
|
|
{
|
|
Variant right (other);
|
|
|
|
switch (_type)
|
|
{
|
|
case type_unknown:
|
|
throw std::string ("Cannot modulo unknown type");
|
|
break;
|
|
|
|
case type_boolean:
|
|
throw std::string ("Cannot modulo Boolean");
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot modulo unknown type");
|
|
case type_boolean: throw std::string ("Cannot modulo integer by Boolean");
|
|
case type_integer:
|
|
if (right._integer == 0)
|
|
throw std::string ("Modulo zero");
|
|
_integer %= right._integer;
|
|
break;
|
|
case type_real:
|
|
if (right._real == 0.0)
|
|
throw std::string ("Modulo zero");
|
|
cast (type_real);
|
|
_real = fmod (_real, right._real);
|
|
break;
|
|
case type_string: throw std::string ("Cannot modulo integer by string");
|
|
case type_date: throw std::string ("Cannot modulo integer by date values");
|
|
case type_duration: throw std::string ("Cannot modulo integer by duration values");
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (right._type)
|
|
{
|
|
case type_unknown: throw std::string ("Cannot modulo unknown type");
|
|
case type_boolean: throw std::string ("Cannot modulo real by Boolean");
|
|
case type_integer:
|
|
if (right._integer == 0)
|
|
throw std::string ("Modulo zero");
|
|
_real = fmod (_real, static_cast<double>(right._integer));
|
|
break;
|
|
case type_real:
|
|
if (right._real == 0)
|
|
throw std::string ("Modulo zero");
|
|
_real = fmod (_real, right._real);
|
|
break;
|
|
case type_string: throw std::string ("Cannot modulo real numbers by strings");
|
|
case type_date: throw std::string ("Cannot modulo real numbers by dates");
|
|
case type_duration: throw std::string ("Cannot modulo real by duration values");
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
throw std::string ("Cannot modulo string values");
|
|
|
|
case type_date:
|
|
throw std::string ("Cannot modulo date values");
|
|
|
|
case type_duration:
|
|
throw std::string ("Cannot modulo duration values");
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant Variant::operator% (const Variant& other) const
|
|
{
|
|
Variant left (*this);
|
|
left %= other;
|
|
return left;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Variant::operator std::string () const
|
|
{
|
|
switch (_type)
|
|
{
|
|
case type_boolean:
|
|
return std::string (_bool ? "true" : "false");
|
|
|
|
case type_integer:
|
|
{
|
|
std::stringstream s;
|
|
s << _integer;
|
|
return s.str ();
|
|
}
|
|
|
|
case type_real:
|
|
{
|
|
std::stringstream s;
|
|
s << _real;
|
|
return s.str ();
|
|
}
|
|
|
|
case type_string:
|
|
return _string;
|
|
|
|
case type_date:
|
|
{
|
|
struct tm* t = localtime (&_date);
|
|
|
|
std::stringstream s;
|
|
s.width (4);
|
|
s << t->tm_year + 1900;
|
|
s << '-';
|
|
s.width (2);
|
|
s.fill ('0');
|
|
s << t->tm_mon + 1;
|
|
s << '-';
|
|
s.width (2);
|
|
s.fill ('0');
|
|
s << t->tm_mday;
|
|
s << 'T';
|
|
s.width (2);
|
|
s.fill ('0');
|
|
s << t->tm_hour;
|
|
s << ':';
|
|
s.width (2);
|
|
s.fill ('0');
|
|
s << t->tm_min;
|
|
s << ':';
|
|
s.width (2);
|
|
s.fill ('0');
|
|
s << t->tm_sec;
|
|
return s.str ();
|
|
}
|
|
|
|
case type_duration:
|
|
{
|
|
time_t t = _duration;
|
|
|
|
if (t)
|
|
{
|
|
int seconds = t % 60; t /= 60;
|
|
int minutes = t % 60; t /= 60;
|
|
int hours = t % 24; t /= 24;
|
|
int days = t % 30; t /= 30;
|
|
int months = t % 12; t /= 12;
|
|
int years = t;
|
|
|
|
std::stringstream s;
|
|
s << 'P';
|
|
if (years) s << years << 'Y';
|
|
if (months) s << months << 'M';
|
|
if (days) s << days << 'D';
|
|
|
|
if (hours || minutes || seconds)
|
|
{
|
|
s << 'T';
|
|
if (hours) s << hours << 'H';
|
|
if (minutes) s << minutes << 'M';
|
|
if (seconds) s << seconds << 'S';
|
|
}
|
|
|
|
return s.str ();
|
|
}
|
|
else
|
|
{
|
|
return "P0S";
|
|
}
|
|
}
|
|
|
|
case type_unknown:
|
|
throw std::string ("Cannot render an unknown type.");
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void Variant::sqrt ()
|
|
{
|
|
cast (type_real);
|
|
if (_real < 0.0)
|
|
throw std::string ("Cannot take the square root of a negative number.");
|
|
_real = ::sqrt (_real);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void Variant::cast (const enum type new_type)
|
|
{
|
|
// Short circuit.
|
|
if (_type == new_type)
|
|
return;
|
|
|
|
if (_type == type_unknown || new_type == type_unknown)
|
|
throw std::string ("Cannot coerce data either to or from an unknown type");
|
|
|
|
// From type_boolean
|
|
switch (_type)
|
|
{
|
|
case type_unknown:
|
|
break;
|
|
|
|
case type_boolean:
|
|
switch (new_type)
|
|
{
|
|
case type_unknown: break;
|
|
case type_boolean: break;
|
|
case type_integer: _integer = _bool ? 1 : 0; break;
|
|
case type_real: _real = _bool ? 1.0 : 0.0; break;
|
|
case type_string: _string = _bool ? "true" : "false"; break;
|
|
case type_date: _date = _bool ? 1 : 0; break;
|
|
case type_duration: _duration = _bool ? 1 : 0; break;
|
|
}
|
|
break;
|
|
|
|
case type_integer:
|
|
switch (new_type)
|
|
{
|
|
case type_unknown: break;
|
|
case type_boolean: _bool = _integer == 0 ? false : true; break;
|
|
case type_integer: break;
|
|
case type_real: _real = static_cast<double>(_integer); break;
|
|
case type_string:
|
|
{
|
|
char temp[24];
|
|
sprintf (temp, "%d", _integer);
|
|
_string = temp;
|
|
}
|
|
break;
|
|
case type_date: _date = (time_t) _integer; break;
|
|
case type_duration: _duration = (time_t) _integer; break;
|
|
}
|
|
break;
|
|
|
|
case type_real:
|
|
switch (new_type)
|
|
{
|
|
case type_unknown: break;
|
|
case type_boolean: _bool = _real == 0.0 ? false : true; break;
|
|
case type_integer: _integer = (int) _real; break;
|
|
case type_real: break;
|
|
case type_string:
|
|
{
|
|
char temp[24];
|
|
sprintf (temp, "%g", _real);
|
|
_string = temp;
|
|
}
|
|
break;
|
|
case type_date: _date = (time_t) (int) _real; break;
|
|
case type_duration: _duration = (time_t) (int) _real; break;
|
|
}
|
|
break;
|
|
|
|
case type_string:
|
|
switch (new_type)
|
|
{
|
|
case type_unknown: break;
|
|
case type_boolean:
|
|
_bool = (_string.length () == 0 ||
|
|
_string == "0" ||
|
|
_string == "0.0") ? false : true;
|
|
break;
|
|
case type_integer:
|
|
_integer = (int) strtol (_string.c_str (), NULL, (_string.substr (0, 2) == "0x" ? 16 : 10));
|
|
break;
|
|
case type_real: _real = strtod (_string.c_str (), NULL); break;
|
|
case type_string: break;
|
|
case type_date:
|
|
{
|
|
_date = 0;
|
|
ISO8601d iso;
|
|
std::string::size_type pos = 0;
|
|
if (iso.parse (_string, pos) &&
|
|
pos == _string.length ())
|
|
{
|
|
_date = (time_t) iso;
|
|
}
|
|
// Support legacy date formats.
|
|
else if (dateFormat != "")
|
|
{
|
|
Date d (_string, dateFormat);
|
|
_date = d.toEpoch ();
|
|
}
|
|
}
|
|
break;
|
|
case type_duration:
|
|
{
|
|
_duration = 0;
|
|
ISO8601p iso;
|
|
std::string::size_type pos = 0;
|
|
if (iso.parse (_string, pos) &&
|
|
pos == _string.length ())
|
|
{
|
|
_duration = (time_t) iso;
|
|
}
|
|
else
|
|
{
|
|
Duration dur;
|
|
pos = 0;
|
|
if (dur.parse (_string, pos) &&
|
|
pos == _string.length ())
|
|
{
|
|
_duration = (time_t) dur;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case type_date:
|
|
switch (new_type)
|
|
{
|
|
case type_unknown: break;
|
|
case type_boolean: _bool = _date != 0 ? true : false; break;
|
|
case type_integer: _integer = (int) _date; break;
|
|
case type_real: _real = static_cast<double>(_date); break;
|
|
case type_string: _string = (std::string) *this; break;
|
|
case type_date: break;
|
|
case type_duration: _duration = _date; break;
|
|
}
|
|
break;
|
|
|
|
case type_duration:
|
|
switch (new_type)
|
|
{
|
|
case type_unknown: break;
|
|
case type_boolean: _bool = _duration != 0 ? true : false; break;
|
|
case type_integer: _integer = (int) _duration; break;
|
|
case type_real: _real = static_cast<double>(_duration); break;
|
|
case type_string: _string = (std::string) *this; break;
|
|
case type_date: _date = _duration; break;
|
|
case type_duration: break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
_type = new_type;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
int Variant::type ()
|
|
{
|
|
return _type;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
bool Variant::get_bool () const
|
|
{
|
|
return _bool;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
int Variant::get_integer () const
|
|
{
|
|
return _integer;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
double Variant::get_real () const
|
|
{
|
|
return _real;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
std::string Variant::get_string () const
|
|
{
|
|
return _string;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
time_t Variant::get_date () const
|
|
{
|
|
return _date;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
time_t Variant::get_duration () const
|
|
{
|
|
return _duration;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|