/*************************************************************** * * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department, * University of Wisconsin-Madison, WI. * * Licensed under the Apache License, Version 2.0 (the "License"); you * may not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ***************************************************************/ #ifndef __CLASSAD_LITERALS_H__ #define __CLASSAD_LITERALS_H__ #include #include #include "exprTree.h" namespace classad { class ErrorLiteral; class UndefinedLiteral; class BooleanLiteral; class IntegerLiteral; class RealLiteral; class ReltimeLiteral; class AbstimeLiteral; class StringLiteral; // abstract base class for the common code in all the // concrete literal sub classes class Literal: public ExprTree { public: virtual NodeKind GetKind (void) const = 0; virtual bool SameAs(const ExprTree *tree) const = 0; virtual const ClassAd *GetParentScope( ) const { return nullptr; } static AbstimeLiteral *MakeAbsTime( abstime_t *now=NULL ); static AbstimeLiteral *MakeAbsTime( std::string timestr); static ReltimeLiteral *MakeRelTime( time_t secs=-1 ); static ReltimeLiteral *MakeRelTime( time_t t1, time_t t2 ); static ReltimeLiteral *MakeRelTime(const std::string &str); static UndefinedLiteral *MakeUndefined(); static ErrorLiteral *MakeError(); static BooleanLiteral *MakeBool(bool val); static IntegerLiteral *MakeInteger(int64_t i); static RealLiteral *MakeReal(double d); static StringLiteral *MakeString(const std::string &str); static StringLiteral *MakeString(const char *); static StringLiteral *MakeString(const char *, size_t size); static Literal *MakeLiteral( const Value& v); static int findOffset(time_t epochsecs); void GetValue(Value& val) const { EvalState dummy; this->_Evaluate(dummy, val); } protected: // no-op for all literals virtual void _SetParentScope(const ClassAd*) {} Literal(): ExprTree() {} }; // An empty instance. Could be a singleton, if we cared enough class ErrorLiteral: public Literal { public: virtual ~ErrorLiteral() {} ErrorLiteral(const ErrorLiteral &) : Literal() {} ErrorLiteral &operator=(const ErrorLiteral &) {return *this;} virtual NodeKind GetKind (void) const { return ERROR_LITERAL; } virtual ExprTree* Copy() const { return new ErrorLiteral();} virtual bool SameAs(const ExprTree *tree) const {return dynamic_cast(tree);} protected: ErrorLiteral() {} // Always evaluates to error virtual bool _Evaluate(EvalState &, Value &v) const { v.SetErrorValue(); return true; }; virtual bool _Flatten(EvalState &state, Value &val, ExprTree*& tree, int*) const { tree = nullptr; return(_Evaluate(state, val)); } virtual bool _Evaluate(EvalState &state, Value &value, ExprTree *&tree) const { _Evaluate(state, value); return ((tree = Copy())); }; friend class Literal; }; class UndefinedLiteral: public Literal { public: virtual ~UndefinedLiteral() {} UndefinedLiteral(const UndefinedLiteral &) : Literal() {} UndefinedLiteral &operator=(const UndefinedLiteral &) {return *this;} virtual NodeKind GetKind (void) const { return UNDEFINED_LITERAL; } virtual ExprTree* Copy() const { return new UndefinedLiteral();} virtual bool SameAs(const ExprTree *tree) const {return dynamic_cast(tree);} protected: UndefinedLiteral() {} // Always evaluates to Undefined virtual bool _Evaluate(EvalState &, Value &v) const { v.SetUndefinedValue(); return true; }; virtual bool _Flatten(EvalState &state, Value &val, ExprTree*& tree, int*) const { tree = nullptr; return(_Evaluate(state, val)); } virtual bool _Evaluate(EvalState &state, Value &value, ExprTree *&tree) const { _Evaluate(state, value); return ((tree = Copy())); }; friend class Literal; }; class BooleanLiteral: public Literal { public: virtual ~BooleanLiteral() {} BooleanLiteral(const BooleanLiteral &rhs) : Literal(), _theBoolean(rhs._theBoolean) {} BooleanLiteral &operator=(const BooleanLiteral &rhs) {_theBoolean = rhs._theBoolean ; return *this;} virtual NodeKind GetKind (void) const { return BOOLEAN_LITERAL; } virtual ExprTree* Copy() const { return new BooleanLiteral(_theBoolean);} virtual bool SameAs(const ExprTree *tree) const { const BooleanLiteral *bl = dynamic_cast(tree); if (bl && (bl->_theBoolean == _theBoolean)) { return true; } return false; } bool getBool() const { return _theBoolean; } protected: BooleanLiteral(bool b): _theBoolean(b) {} virtual void _SetParentScope(const ClassAd*) {} // Always evaluates to true/false virtual bool _Evaluate(EvalState &, Value &v) const { v.SetBooleanValue(_theBoolean); return true; }; virtual bool _Flatten(EvalState &state, Value &val, ExprTree*& tree, int*) const { tree = nullptr; return(_Evaluate(state, val)); } virtual bool _Evaluate(EvalState &state, Value &value, ExprTree *&tree) const { _Evaluate(state, value); return ((tree = Copy())); }; private: bool _theBoolean; friend class Literal; }; class IntegerLiteral: public Literal { public: virtual ~IntegerLiteral() {} IntegerLiteral(const IntegerLiteral &rhs) : Literal(), _theInteger(rhs._theInteger) {} IntegerLiteral &operator=(const IntegerLiteral &rhs) {_theInteger = rhs._theInteger; return *this;} virtual NodeKind GetKind (void) const { return INTEGER_LITERAL; } virtual ExprTree* Copy() const { return new IntegerLiteral(_theInteger);} virtual bool SameAs(const ExprTree *tree) const { const IntegerLiteral *bl = dynamic_cast(tree); if (bl && (bl->_theInteger == _theInteger)) { return true; } return false; } int64_t getInteger() const { return _theInteger; } protected: IntegerLiteral(int64_t i): _theInteger(i) {} // Always evaluates to the integer virtual bool _Evaluate(EvalState &, Value &v) const { v.SetIntegerValue(_theInteger); return true; }; virtual bool _Flatten(EvalState &state, Value &val, ExprTree*& tree, int*) const { tree = nullptr; return(_Evaluate(state, val)); } virtual bool _Evaluate(EvalState &state, Value &value, ExprTree *&tree) const { _Evaluate(state, value); return ((tree = Copy())); }; private: int64_t _theInteger; friend class Literal; }; class RealLiteral: public Literal { public: virtual ~RealLiteral() {} RealLiteral(const RealLiteral &rhs) : Literal(), _theReal(rhs._theReal) {} RealLiteral &operator=(const RealLiteral &rhs) {_theReal = rhs._theReal; return *this;} virtual NodeKind GetKind (void) const { return REAL_LITERAL; } virtual ExprTree* Copy() const { return new RealLiteral(_theReal);} virtual bool SameAs(const ExprTree *tree) const { const RealLiteral *rl = dynamic_cast(tree); // The old code did a strict == here, but avoid warning and NaNsense this way if (rl && (fabs(rl->_theReal - _theReal) <= std::numeric_limits::epsilon())) { return true; } return false; } double getReal() const { return _theReal; } protected: RealLiteral(double d): _theReal(d) {} // Always evaluates to the double virtual bool _Evaluate(EvalState &, Value &v) const { v.SetRealValue(_theReal); return true; }; virtual bool _Flatten(EvalState &state, Value &val, ExprTree*& tree, int*) const { tree = nullptr; return(_Evaluate(state, val)); } virtual bool _Evaluate(EvalState &state, Value &value, ExprTree *&tree) const { _Evaluate(state, value); return ((tree = Copy())); }; private: double _theReal; friend class Literal; }; class ReltimeLiteral: public Literal { public: virtual ~ReltimeLiteral() {} ReltimeLiteral(const ReltimeLiteral &rhs) : Literal(), _theReltime(rhs._theReltime) {} ReltimeLiteral &operator=(const ReltimeLiteral &rhs) {_theReltime = rhs._theReltime; return *this;} virtual NodeKind GetKind (void) const { return RELTIME_LITERAL; } virtual ExprTree* Copy() const { return new ReltimeLiteral(_theReltime);} virtual bool SameAs(const ExprTree *tree) const { const ReltimeLiteral *rl = dynamic_cast(tree); if (rl && (fabs(rl->_theReltime - _theReltime) <= std::numeric_limits::epsilon())) { return true; } return false; } double getReltime() const { return _theReltime; } protected: ReltimeLiteral(double d): _theReltime(d) {} // Always evaluates to the double virtual bool _Evaluate(EvalState &, Value &v) const { v.SetRealValue(_theReltime); return true; }; virtual bool _Flatten(EvalState &state, Value &val, ExprTree*& tree, int*) const { tree = nullptr; return(_Evaluate(state, val)); } virtual bool _Evaluate(EvalState &state, Value &value, ExprTree *&tree) const { _Evaluate(state, value); return ((tree = Copy())); }; private: double _theReltime; friend class Literal; }; class AbstimeLiteral: public Literal { public: virtual ~AbstimeLiteral() {} AbstimeLiteral(const AbstimeLiteral &rhs ) : Literal(), _theAbstime(rhs._theAbstime) {} AbstimeLiteral &operator=(const AbstimeLiteral &rhs) {_theAbstime = rhs._theAbstime; return *this;} virtual NodeKind GetKind (void) const { return ABSTIME_LITERAL; } virtual ExprTree* Copy() const { return new AbstimeLiteral(_theAbstime);} virtual bool SameAs(const ExprTree *tree) const { const AbstimeLiteral *al = dynamic_cast(tree); if (al && (al->_theAbstime.secs == _theAbstime.secs) && (al->_theAbstime.offset == _theAbstime.offset)) { return true; } return false; } abstime_t getAbstime() const { return _theAbstime; } protected: AbstimeLiteral(abstime_t a): _theAbstime(a) {} // Always evaluates to the abstime virtual bool _Evaluate(EvalState &, Value &v) const { v.SetAbsoluteTimeValue(_theAbstime); return true; }; virtual bool _Flatten(EvalState &state, Value &val, ExprTree*& tree, int*) const { tree = nullptr; return(_Evaluate(state, val)); } virtual bool _Evaluate(EvalState &state, Value &value, ExprTree *&tree) const { _Evaluate(state, value); return ((tree = Copy())); }; private: abstime_t _theAbstime; friend class Literal; }; class StringLiteral: public Literal { public: virtual ~StringLiteral() {} StringLiteral(const StringLiteral &rhs) : Literal(), _theString(rhs._theString) {} StringLiteral &operator=(const StringLiteral &rhs) {_theString = rhs._theString; return *this;} const char *getCString() const { return _theString.c_str();; } const std::string &getString() const { return _theString; } virtual NodeKind GetKind (void) const { return STRING_LITERAL; } virtual ExprTree* Copy() const { return new StringLiteral(_theString);} virtual bool SameAs(const ExprTree *tree) const { const StringLiteral *sl = dynamic_cast(tree); if (sl && (sl->_theString == _theString)) { return true; } return false; } protected: StringLiteral(const std::string &s): _theString(s) {} // Always evaluates to the abstime virtual bool _Evaluate(EvalState &, Value &v) const { v.SetStringValue(_theString); return true; }; virtual bool _Flatten(EvalState &state, Value &val, ExprTree*& tree, int*) const { tree = nullptr; return(_Evaluate(state, val)); } virtual bool _Evaluate(EvalState &state, Value &value, ExprTree *&tree) const { _Evaluate(state, value); return ((tree = Copy())); }; private: std::string _theString; friend class Literal; }; typedef std::vector ArgumentList; /* ERROR_VALUE = 1<<0, UNDEFINED_VALUE = 1<<1, BOOLEAN_VALUE = 1<<2, INTEGER_VALUE = 1<<3, REAL_VALUE = 1<<4, RELATIVE_TIME_VALUE = 1<<5, ABSOLUTE_TIME_VALUE = 1<<6, STRING_VALUE = 1<<7, CLASSAD_VALUE = 1<<8, LIST_VALUE = 1<<9, SLIST_VALUE = 1<<10, */ inline BooleanLiteral* Literal::MakeBool(bool val) { return new BooleanLiteral(val); } inline IntegerLiteral* Literal::MakeInteger(int64_t val) { return new IntegerLiteral(val); } inline RealLiteral* Literal::MakeReal(double real) { return new RealLiteral(real); } inline StringLiteral* Literal::MakeString(const std::string & str) { return new StringLiteral(str); } inline StringLiteral* Literal::MakeString(const char* str) { return new StringLiteral(str ? str : ""); } inline StringLiteral* Literal::MakeString(const char* str, size_t cch) { if (str == nullptr) { return new StringLiteral(""); } return new StringLiteral(std::string(str, cch)); } inline ErrorLiteral* Literal::MakeError() { return new ErrorLiteral(); } inline UndefinedLiteral * Literal::MakeUndefined() { return new UndefinedLiteral(); } inline Literal* Literal::MakeLiteral(const Value &v) { switch (v.valueType) { case Value::UNDEFINED_VALUE: return new UndefinedLiteral; break; case Value::ERROR_VALUE: return new ErrorLiteral; break; case Value::STRING_VALUE: { std::string s; std::ignore = v.IsStringValue(s); return new StringLiteral(s); break; } case Value::REAL_VALUE: { double d = 0; std::ignore = v.IsRealValue(d); return new RealLiteral(d); break; } case Value::INTEGER_VALUE: { int64_t i = 0; std::ignore = v.IsIntegerValue(i); return new IntegerLiteral(i); break; } case Value::BOOLEAN_VALUE: { bool b = true; std::ignore = v.IsBooleanValue(b); return new BooleanLiteral(b); break; } case Value::ABSOLUTE_TIME_VALUE: { classad::abstime_t atime {}; std::ignore = v.IsAbsoluteTimeValue(atime); return new AbstimeLiteral(atime); break; } case Value::RELATIVE_TIME_VALUE: { time_t seconds = 0; std::ignore = v.IsRelativeTimeValue(seconds); return new ReltimeLiteral(double(seconds)); break; } default: return nullptr; } return nullptr; } } // classad #endif//__CLASSAD_LITERALS_H__