From db175362668c5858f0721fcdbaa15ef71819d68c Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Jun 2011 09:49:43 -0400 Subject: [PATCH] Expressions - Filter processing short-circuits if there is no filter. - Variant code was not only incomplete, but very broken. It should not have been used. It still doesn't handle dates and durations. - Converted all logical and relational Variant operators to return Boolean values. - Stack size is now checked for every operator. - All operators implemented (without any advanced special case handling) except %, ~ and !~. - Added lazy DOM expansion at the last possible moment. - Implemented Expression::create_variant to create appropriate Variant instances based on categorized and inferred type. - Removed Variant math functions. No point. - Debug code left in place for now. --- src/Expression.cpp | 259 +++++++++++++++++++++++++----------- src/Expression.h | 2 + src/Variant.cpp | 321 ++++++++++++++++++++++----------------------- src/Variant.h | 51 ++++--- 4 files changed, 363 insertions(+), 270 deletions(-) diff --git a/src/Expression.cpp b/src/Expression.cpp index 311361852..68e2aad39 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -44,17 +44,20 @@ extern Context context; Expression::Expression (Arguments& arguments) : _args (arguments) { - _args.dump ("Expression::Expression"); + if (_args.size ()) + { + _args.dump ("Expression::Expression"); - expand_sequence (); - implicit_and (); - expand_tag (); - expand_pattern (); - expand_attr (); - expand_attmod (); - expand_word (); - expand_tokens (); - postfix (); + expand_sequence (); + implicit_and (); + expand_tag (); + expand_pattern (); + expand_attr (); + expand_attmod (); + expand_word (); + expand_tokens (); + postfix (); + } } //////////////////////////////////////////////////////////////////////////////// @@ -71,123 +74,204 @@ bool Expression::eval (Task& task) // There are elements in the filter, so the expression must be evaluated // against each task. - std::vector > value_stack; + std::vector value_stack; // TODO Build an on-demand regex cache. - std::vector >::iterator arg; + std::vector >::const_iterator arg; for (arg = _args.begin (); arg != _args.end (); ++arg) { if (arg->second == "op") { + std::cout << "# operator " << arg->first << "\n"; + // Handle the unary operator first. if (arg->first == "!") { + // Are there sufficient arguments? if (value_stack.size () < 1) throw std::string ("Error: Insufficient operands for '!' operator."); - std::string right_type = value_stack.back ().second; - Variant right (value_stack.back ().first); + Variant right (value_stack.back ()); + if (right.raw_type () == "lvalue") + { + right = Variant (context.dom.get (right.raw (), task)); + right.raw (value_stack.back ().raw ()); + right.raw_type (value_stack.back ().raw_type ()); + } value_stack.pop_back (); - right = ! right; - value_stack.push_back (std::make_pair (right, "")); - continue; // This only occurs here. + std::cout << "# " << " ! " << right.dump () << "\n"; + bool result = !right; + right = Variant (result); + right.raw_type ("bool"); + + std::cout << "# --> " << right.dump () << "\n"; + value_stack.push_back (right); + + // This only occurs here, because the unary operators are handled, and + // now the binary operators will be processed. + continue; } + // Are there sufficient arguments? if (value_stack.size () < 2) throw std::string ("Error: Insufficient operands for '") + arg->first + "' operator."; - // Pop the binary operands first. - std::string right_type = value_stack.back ().second; - Variant right (value_stack.back ().first); + // rvalue (string, rx, int, number, dom ...). + Variant right (value_stack.back ()); + if (right.raw_type () == "lvalue") + { + right = Variant (context.dom.get (right.raw (), task)); + right.raw (value_stack.back ().raw ()); + right.raw_type (value_stack.back ().raw_type ()); + } value_stack.pop_back (); - std::string left_type = value_stack.back ().second; - Variant left (value_stack.back ().first); + // lvalue (dom). + Variant left (value_stack.back ()); + if (left.raw_type () == "lvalue") + { + left = Variant (context.dom.get (left.raw (), task)); + left.raw (value_stack.back ().raw ()); + left.raw_type (value_stack.back ().raw_type ()); + } value_stack.pop_back (); - // Now hte binary operators. + // Now the binary operators. if (arg->first == "and") { - left = left && right; - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# " << left.dump () << " and " << right.dump () << "\n"; + bool result = (left && right); + left = Variant (result); + left.raw_type ("bool"); + + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else if (arg->first == "xor") { - left = (left && !right) || (!left && right); - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# " << left.dump () << " xor " << right.dump () << "\n"; + bool left_bool = left.boolean (); + bool right_bool = right.boolean (); + bool result = (left_bool && !right_bool) || (!left_bool && right_bool); + left = Variant (result); + left.raw_type ("bool"); + + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else if (arg->first == "or") { - left = left || right; - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# " << left.dump () << " or " << right.dump () << "\n"; + bool result = (left || right); + left = Variant (result); + left.raw_type ("bool"); + + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else if (arg->first == "<=") { - left = left <= right; - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# " << left.dump () << " <= " << right.dump () << "\n"; + bool result = (left <= right); + left = Variant (result); + left.raw_type ("bool"); + + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else if (arg->first == ">=") { - left = left >= right; - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# " << left.dump () << " >= " << right.dump () << "\n"; + bool result = (left >= right); + left = Variant (result); + left.raw_type ("bool"); + + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else if (arg->first == "!~") { - // TODO -/* - if left == "description" then it really means description or annotations or project. - if left == "tags" then it just means tags. -*/ + // TODO Copy "~". } else if (arg->first == "!=") { - left = left != right; - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# " << left.dump () << " != " << right.dump () << "\n"; + bool result = (left != right); + left = Variant (result); + left.raw_type ("bool"); + + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else if (arg->first == "=") { -context.debug ("eval left=" + left.format ()); -context.debug ("eval right=" + right.format ()); + std::cout << "# " << left.dump () << " = " << right.dump () << "\n"; + bool result = (left == right); + left = Variant (result); + left.raw_type ("bool"); - left = left == right; - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else if (arg->first == ">") { - left = left > right; - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# " << left.dump () << " > " << right.dump () << "\n"; + bool result = (left > right); + left = Variant (result); + left.raw_type ("bool"); + + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else if (arg->first == "~") { - // TODO We need to compare right against description, all annotations and project. - // TODO Does that mean we need the original lvalue intact, and not a DOM subst? -/* - if left == "description" then it really means description or annotations or project. - if left == "tags" then it just means tags. -*/ + // Matches against description are really against either description, + // annotations or project. + if (left.raw () == "description") + { + if (right.raw_type () == "rx") + { + throw std::string ("rx not supported"); + } + else + { + } + } + + // Matches against non-description fields are treated as-is. + else + { + if (right.raw_type () == "rx") + { + throw std::string ("rx not supported"); + } + else + { + } + } } else if (arg->first == "*") { left = left * right; - value_stack.push_back (std::make_pair (left, "")); + value_stack.push_back (left); } else if (arg->first == "/") { left = left / right; - value_stack.push_back (std::make_pair (left, "")); + value_stack.push_back (left); } else if (arg->first == "%") @@ -198,19 +282,24 @@ context.debug ("eval right=" + right.format ()); else if (arg->first == "+") { left = left + right; - value_stack.push_back (std::make_pair (left, "")); + value_stack.push_back (left); } else if (arg->first == "-") { left = left - right; - value_stack.push_back (std::make_pair (left, "")); + value_stack.push_back (left); } else if (arg->first == "<") { - left = left < right; - value_stack.push_back (std::make_pair (left, "")); + std::cout << "# " << left.dump () << " < " << right.dump () << "\n"; + bool result = (left < right); + left = Variant (result); + left.raw_type ("bool"); + + std::cout << "# --> " << left.dump () << "\n"; + value_stack.push_back (left); } else @@ -220,28 +309,14 @@ context.debug ("eval right=" + right.format ()); // It's not an operator, it's either and lvalue or some form of rvalue. else { - if (arg->second == "lvalue") - value_stack.push_back (std::make_pair (Variant (context.dom.get (arg->first, task)), "")); - - else if (arg->second == "int") - value_stack.push_back (std::make_pair (Variant ((int) strtol (arg->first.c_str (), NULL, 10)), "")); - - else if (arg->second == "number") - value_stack.push_back (std::make_pair (Variant (strtod (arg->first.c_str (), NULL)), "")); - - else if (arg->second == "rvalue" || - arg->second == "string" || - arg->second == "rx") - value_stack.push_back (std::make_pair (Variant (unquoteText (arg->first)), "")); - - else - throw std::string ("Error: Expression::eval unrecognized operand '") + + "'."; + Variant operand; + create_variant (operand, arg->first, arg->second); + value_stack.push_back (operand); } } // Coerce stack element to boolean. - Variant result (value_stack.back ().first); - //context.debug ("eval result=" + result.format ()); + Variant result (value_stack.back ()); value_stack.pop_back (); bool pass_fail = result.boolean (); @@ -252,6 +327,38 @@ context.debug ("eval right=" + right.format ()); return pass_fail; } +//////////////////////////////////////////////////////////////////////////////// +void Expression::create_variant ( + Variant& variant, + const std::string& value, + const std::string& type) +{ + std::cout << "# operand '" << value << "' as " << type << "\n"; + + // DOM references are not resolved until the operator is processed. This + // preserves the original name, which helps determine how to apply the + // operator. + if (type == "lvalue") + variant = Variant (value); + + else if (type == "int") + variant = Variant ((int) strtol (value.c_str (), NULL, 10)); + + else if (type == "number") + variant = Variant (strtod (value.c_str (), NULL)); + + else if (type == "rvalue" || + type == "string" || + type == "rx") + variant = Variant (unquoteText (value)); + + else + throw std::string ("Unrecognized operand '") + + "'."; + + variant.raw (value); + variant.raw_type (type); +} + //////////////////////////////////////////////////////////////////////////////// // Convert: 1,3-5,00000000-0000-0000-0000-000000000000 // diff --git a/src/Expression.h b/src/Expression.h index 4f0f0131c..56767ad5a 100644 --- a/src/Expression.h +++ b/src/Expression.h @@ -32,6 +32,7 @@ #include #include #include +#include class Expression { @@ -51,6 +52,7 @@ private: void expand_tokens (); void postfix (); + void create_variant (Variant&, const std::string&, const std::string&); bool is_new_style (); private: diff --git a/src/Variant.cpp b/src/Variant.cpp index 7317b39fb..2d581f58a 100644 --- a/src/Variant.cpp +++ b/src/Variant.cpp @@ -32,15 +32,19 @@ #include //////////////////////////////////////////////////////////////////////////////// -Variant::Variant () : - mType (v_unknown) +Variant::Variant () +: mType (v_unknown) +, mRaw ("") +, mRawType ("") { } //////////////////////////////////////////////////////////////////////////////// Variant::Variant (const Variant& other) { - mType = other.mType; + mType = other.mType; + mRaw = other.mRaw; + mRawType = other.mRawType; // Explicitly copy only the relevant type. This saves memory. switch (mType) @@ -98,188 +102,217 @@ Variant::Variant (const Duration& input) } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator&& (const Variant& other) +// For copying. +Variant& Variant::operator= (const Variant& other) +{ + if (this != &other) + { + mType = other.mType; + mBool = other.mBool; + mInteger = other.mInteger; + mDouble = other.mDouble; + mString = other.mString; + mDate = other.mDate; + mDuration = other.mDuration; + mRaw = other.mRaw; + mRawType = other.mRawType; + } + + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Variant::operator&& (Variant& other) { cast (v_boolean); - Variant copy (other); - copy.cast (v_boolean); - mBool = (mBool && copy.mBool) ? true : false; - return *this; + other.cast (v_boolean); + return mBool && other.mBool; } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator|| (const Variant& other) +bool Variant::operator|| (Variant& other) { cast (v_boolean); - Variant copy (other); - copy.cast (v_boolean); - mBool = (mBool || copy.mBool) ? true : false; - return *this; + other.cast (v_boolean); + return mBool || other.mBool; } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator<= (const Variant& other) +bool Variant::operator<= (Variant& other) { + promote (*this, other); + bool result; + switch (mType) { case v_boolean: - mBool = false; // TODO Makes no sense. + throw std::string ("Cannot perform relative comparison on bool types"); break; case v_integer: - mBool = mInteger <= other.mInteger ? true : false; + result = mInteger <= other.mInteger ? true : false; break; case v_double: - mBool = mDouble <= other.mDouble ? true : false; + result = mDouble <= other.mDouble ? true : false; break; case v_string: { int collating = strcmp (mString.c_str (), other.mString.c_str ()); - mBool = collating <= 0 ? true : false; + result = collating <= 0 ? true : false; } break; case v_date: - mBool = mDate <= other.mDate ? true : false; + result = mDate <= other.mDate ? true : false; break; case v_duration: - mBool = (time_t)mDuration <= (time_t)other.mDuration ? true : false; + result = (time_t)mDuration <= (time_t)other.mDuration ? true : false; break; case v_unknown: + throw std::string ("Cannot perform relative comparison on unknown types"); break; } - mType = v_boolean; - return *this; + return result; } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator>= (const Variant& other) +bool Variant::operator>= (Variant& other) { + promote (*this, other); + bool result; + switch (mType) { case v_boolean: - mBool = false; // TODO Makes no sense. + throw std::string ("Cannot perform relative comparison on bool types"); break; case v_integer: - mBool = mInteger >= other.mInteger ? true : false; + result = mInteger >= other.mInteger ? true : false; break; case v_double: - mBool = mDouble >= other.mDouble ? true : false; + result = mDouble >= other.mDouble ? true : false; break; case v_string: { int collating = strcmp (mString.c_str (), other.mString.c_str ()); - mBool = collating >= 0 ? true : false; + result = collating >= 0 ? true : false; } break; case v_date: - mBool = mDate >= other.mDate ? true : false; + result = mDate >= other.mDate ? true : false; break; case v_duration: - mBool = (time_t)mDuration >= (time_t)other.mDuration ? true : false; + result = (time_t)mDuration >= (time_t)other.mDuration ? true : false; break; case v_unknown: + throw std::string ("Cannot perform relative comparison on unknown types"); break; } - mType = v_boolean; - return *this; + return result; } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator== (const Variant& other) +bool Variant::operator== (Variant& other) { + promote (*this, other); + bool result; + switch (mType) { case v_boolean: - mBool = mBool == other.mBool ? true : false; + result = mBool == other.mBool ? true : false; break; case v_integer: - mBool = mInteger == other.mInteger ? true : false; + result = mInteger == other.mInteger ? true : false; break; case v_double: - mBool = mDouble == other.mDouble ? true : false; + result = mDouble == other.mDouble ? true : false; break; case v_string: { int collating = strcmp (mString.c_str (), other.mString.c_str ()); - mBool = collating == 0 ? true : false; + result = collating == 0 ? true : false; } break; case v_date: - mBool = mDate == other.mDate ? true : false; + result = mDate == other.mDate ? true : false; break; case v_duration: - mBool = mDuration == other.mDuration ? true : false; + result = mDuration == other.mDuration ? true : false; break; case v_unknown: + throw std::string ("Cannot perform relative comparison on unknown types"); break; } - mType = v_boolean; - return *this; + return result; } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator!= (const Variant& other) +bool Variant::operator!= (Variant& other) { + promote (*this, other); + bool result; + switch (mType) { case v_boolean: - mBool = mBool != other.mBool ? true : false; + result = mBool != other.mBool ? true : false; break; case v_integer: - mBool = mInteger != other.mInteger ? true : false; + result = mInteger != other.mInteger ? true : false; break; case v_double: - mBool = mDouble != other.mDouble ? true : false; + result = mDouble != other.mDouble ? true : false; break; case v_string: { int collating = strcmp (mString.c_str (), other.mString.c_str ()); - mBool = collating != 0 ? true : false; + result = collating != 0 ? true : false; } break; case v_date: - mBool = mDate != other.mDate ? true : false; + result = mDate != other.mDate ? true : false; break; case v_duration: - mBool = mDuration != other.mDuration ? true : false; + result = mDuration != other.mDuration ? true : false; break; case v_unknown: + throw std::string ("Cannot perform relative comparison on unknown types"); break; } - mType = v_boolean; - return *this; + return result; } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator^ (const Variant& other) +Variant& Variant::operator^ (Variant& other) { + // TODO This is all wrong! switch (mType) { case v_boolean: @@ -307,6 +340,7 @@ Variant& Variant::operator^ (const Variant& other) break; case v_unknown: + throw std::string ("Cannot perform exponentiation on unknown types"); break; } @@ -314,16 +348,18 @@ Variant& Variant::operator^ (const Variant& other) } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator! () +bool Variant::operator! () { cast (v_boolean); mBool = ! mBool; - return *this; + return mBool; } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator- (const Variant& other) +Variant& Variant::operator- (Variant& other) { + promote (*this, other); + switch (mType) { case v_boolean: @@ -352,6 +388,7 @@ Variant& Variant::operator- (const Variant& other) break; case v_unknown: + throw std::string ("Cannot perform subtraction on unknown types"); break; } @@ -359,8 +396,10 @@ Variant& Variant::operator- (const Variant& other) } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator+ (const Variant& other) +Variant& Variant::operator+ (Variant& other) { + promote (*this, other); + switch (mType) { case v_boolean: @@ -390,6 +429,7 @@ Variant& Variant::operator+ (const Variant& other) break; case v_unknown: + throw std::string ("Cannot perform addition on unknown types"); break; } @@ -397,8 +437,10 @@ Variant& Variant::operator+ (const Variant& other) } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator* (const Variant& other) +Variant& Variant::operator* (Variant& other) { + promote (*this, other); + switch (mType) { case v_boolean: @@ -426,6 +468,7 @@ Variant& Variant::operator* (const Variant& other) break; case v_unknown: + throw std::string ("Cannot perform multiplication on unknown types"); break; } @@ -433,8 +476,10 @@ Variant& Variant::operator* (const Variant& other) } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator/ (const Variant& other) +Variant& Variant::operator/ (Variant& other) { + promote (*this, other); + switch (mType) { case v_boolean: @@ -462,6 +507,7 @@ Variant& Variant::operator/ (const Variant& other) break; case v_unknown: + throw std::string ("Cannot perform division on unknown types"); break; } @@ -469,8 +515,11 @@ Variant& Variant::operator/ (const Variant& other) } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator< (const Variant& other) +bool Variant::operator< (Variant& other) { + promote (*this, other); + bool result; + switch (mType) { case v_boolean: @@ -478,39 +527,42 @@ Variant& Variant::operator< (const Variant& other) break; case v_integer: - mBool = mInteger < other.mInteger ? true : false; + result = mInteger < other.mInteger ? true : false; break; case v_double: - mBool = mDouble < other.mDouble ? true : false; + result = mDouble < other.mDouble ? true : false; break; case v_string: { int collating = strcmp (mString.c_str (), other.mString.c_str ()); - mBool = collating < 0 ? true : false; + result = collating < 0 ? true : false; } break; case v_date: - mBool = mDate < other.mDate ? true : false; + result = mDate < other.mDate ? true : false; break; case v_duration: - mBool = mDuration < other.mDuration ? true : false; + result = mDuration < other.mDuration ? true : false; break; case v_unknown: + throw std::string ("Cannot perform relative comparisons on unknown types"); break; } - mType = v_boolean; - return *this; + return result; } //////////////////////////////////////////////////////////////////////////////// -Variant& Variant::operator> (const Variant& other) +bool Variant::operator> (Variant& other) { + promote (*this, other); + bool result; + switch (mType) { case v_boolean: @@ -518,129 +570,34 @@ Variant& Variant::operator> (const Variant& other) break; case v_integer: - mBool = mInteger > other.mInteger ? true : false; + result = mInteger > other.mInteger ? true : false; break; case v_double: - mBool = mDouble > other.mDouble ? true : false; + result = mDouble > other.mDouble ? true : false; break; case v_string: { int collating = strcmp (mString.c_str (), other.mString.c_str ()); - mBool = collating > 0 ? true : false; + result = collating > 0 ? true : false; } break; case v_date: - mBool = mDate > other.mDate ? true : false; + result = mDate > other.mDate ? true : false; break; case v_duration: - mBool = mDuration > other.mDuration ? true : false; + result = mDuration > other.mDuration ? true : false; break; case v_unknown: + throw std::string ("Cannot perform relative comparisons on unknown types"); break; } - mType = v_boolean; - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::sqrt () -{ - cast (v_double); - if (mDouble < 0.0) - throw std::string ("Cannot take the square root of a negative number."); - mDouble = ::sqrt (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::sin () -{ - cast (v_double); - mDouble = ::sin (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::cos () -{ - cast (v_double); - mDouble = ::cos (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::tan () -{ - cast (v_double); - mDouble = ::tan (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::asin () -{ - cast (v_double); - mDouble = ::asin (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::acos () -{ - cast (v_double); - mDouble = ::acos (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::atan () -{ - cast (v_double); - mDouble = ::atan (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::log () -{ - cast (v_double); - mDouble = ::log10 (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::exp () -{ - cast (v_double); - mDouble = ::exp (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::exp10 () -{ - cast (v_double); - mDouble = ::pow (10.0, mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::ln () -{ - cast (v_double); - mDouble = ::sqrt (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::sign () -{ - cast (v_double); - if (mDouble == 0.0) - throw std::string ("Divide by zero."); - mDouble /= fabs (mDouble); -} - -//////////////////////////////////////////////////////////////////////////////// -void Variant::abs () -{ - cast (v_double); - mDouble = ::fabs (mDouble); + return result; } //////////////////////////////////////////////////////////////////////////////// @@ -820,6 +777,30 @@ Variant::variant_type Variant::type () return mType; } +//////////////////////////////////////////////////////////////////////////////// +void Variant::raw (const std::string& input) +{ + mRaw = input; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string Variant::raw () +{ + return mRaw; +} + +//////////////////////////////////////////////////////////////////////////////// +void Variant::raw_type (const std::string& input) +{ + mRawType = input; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string Variant::raw_type () +{ + return mRawType; +} + //////////////////////////////////////////////////////////////////////////////// void Variant::promote (Variant& lhs, Variant& rhs) { @@ -861,3 +842,9 @@ bool Variant::boolean () } //////////////////////////////////////////////////////////////////////////////// +std::string Variant::dump () +{ + return format () + "/" + raw () + "/" + raw_type (); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Variant.h b/src/Variant.h index 70fc616f8..7af520e9c 100644 --- a/src/Variant.h +++ b/src/Variant.h @@ -55,42 +55,36 @@ public: Variant (const std::string&); Variant (const Date&); Variant (const Duration&); + Variant& operator= (const Variant&); - Variant& operator&& (const Variant& other); - Variant& operator|| (const Variant& other); - Variant& operator<= (const Variant& other); - Variant& operator>= (const Variant& other); - Variant& operator== (const Variant& other); - Variant& operator!= (const Variant& other); - Variant& operator^ (const Variant& other); - Variant& operator! (); - Variant& operator- (const Variant& other); - Variant& operator+ (const Variant& other); - Variant& operator* (const Variant& other); - Variant& operator/ (const Variant& other); - Variant& operator< (const Variant& other); - Variant& operator> (const Variant& other); + bool operator&& (Variant& other); + bool operator|| (Variant& other); - void sqrt (); - void sin (); - void cos (); - void tan (); - void asin (); - void acos (); - void atan (); - void log (); - void exp (); - void exp10 (); - void ln (); - void sign (); - void abs (); + bool operator<= (Variant& other); + bool operator>= (Variant& other); + bool operator== (Variant& other); + bool operator< (Variant& other); + bool operator> (Variant& other); + bool operator!= (Variant& other); + bool operator! (); + + Variant& operator^ (Variant& other); + Variant& operator- (Variant& other); + Variant& operator+ (Variant& other); + Variant& operator* (Variant& other); + Variant& operator/ (Variant& other); void input (const std::string&); std::string format (); void cast (const variant_type); variant_type type (); + void raw (const std::string&); + std::string raw (); + void raw_type (const std::string&); + std::string raw_type (); void promote (Variant&, Variant&); bool boolean (); + std::string dump (); private: variant_type mType; @@ -101,6 +95,9 @@ private: std::string mString; Date mDate; Duration mDuration; + + std::string mRaw; + std::string mRawType; }; #endif