//////////////////////////////////////////////////////////////////////////////// /// @brief Infrastructure for RangeInfo /// /// @file arangod/Aql/RangeInfo.h /// /// DISCLAIMER /// /// Copyright 2010-2014 triagens GmbH, Cologne, Germany /// /// 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. /// /// Copyright holder is triAGENS GmbH, Cologne, Germany /// /// @author not James /// @author Copyright 2014, triagens GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// #ifndef ARANGODB_AQL_RANGE_INFO_H #define ARANGODB_AQL_RANGE_INFO_H 1 #include "Basics/Common.h" #include "Aql/AstNode.h" #include "Basics/JsonHelper.h" #include "Basics/json-utilities.h" class VocShaper; namespace triagens { namespace aql { // ----------------------------------------------------------------------------- // --SECTION-- class RangeInfoBound // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief struct to keep an upper or lower bound named _bound and a bool /// _include which indicates if the _bound is included or not. This can /// hold a constant value (NODE_TYPE_VALUE) or a subexpression, which is /// indicated by the boolean flag _isConstant. The whole thing can be /// not _defined, which counts as _isConstant. /// We have the following invariants: /// (! _defined) ==> _isConstant //////////////////////////////////////////////////////////////////////////////// struct RangeInfoBound { // ----------------------------------------------------------------------------- // --SECTION-- constructors / destructors // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief constructors //////////////////////////////////////////////////////////////////////////////// RangeInfoBound (AstNode const* bound, bool include) : _bound(), _include(include), _defined(false), _expressionAst(nullptr) { if (bound->type == NODE_TYPE_VALUE) { _bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, bound->toJsonValue(TRI_UNKNOWN_MEM_ZONE)); _isConstant = true; } else { _bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, bound->toJson(TRI_UNKNOWN_MEM_ZONE, true)); _isConstant = false; _expressionAst = bound; } _defined = true; } RangeInfoBound (triagens::basics::Json const& json) : _bound(), _include(basics::JsonHelper::checkAndGetBooleanValue(json.json(), "include")), _isConstant(basics::JsonHelper::checkAndGetBooleanValue(json.json(), "isConstant")), _defined(false), _expressionAst(nullptr) { triagens::basics::Json bound = json.get("bound"); if (! bound.isEmpty()) { _bound = bound; _defined = true; } } RangeInfoBound (bool include, bool isConstant, triagens::basics::Json& json) : _bound(), _include(include), _isConstant(isConstant), _defined(false), _expressionAst(nullptr) { if (! json.isEmpty()) { _bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, json.steal()); _defined = true; } } RangeInfoBound () : _bound(), _include(false), _isConstant(false), _defined(false), _expressionAst(nullptr) { } RangeInfoBound (RangeInfoBound const& copy) : _bound(copy._bound.copy()), _include(copy._include), _isConstant(copy._isConstant), _defined(copy._defined), _expressionAst(nullptr) { } //////////////////////////////////////////////////////////////////////////////// /// @brief destructor //////////////////////////////////////////////////////////////////////////////// ~RangeInfoBound () {} //////////////////////////////////////////////////////////////////////////////// /// @brief delete assignment //////////////////////////////////////////////////////////////////////////////// RangeInfoBound& operator= (RangeInfoBound const& copy) = delete; // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief explicit assign //////////////////////////////////////////////////////////////////////////////// void assign (basics::Json const& json) { _defined = false; // keep it undefined in case of an exception triagens::basics::Json bound = json.get("bound"); if (! bound.isEmpty()) { _bound = bound; _defined = true; } _include = basics::JsonHelper::checkAndGetBooleanValue( json.json(), "include"); _isConstant = basics::JsonHelper::checkAndGetBooleanValue( json.json(), "isConstant"); _expressionAst = nullptr; } void assign (AstNode const* bound, bool include) { _defined = false; // keep it undefined in case of an exception _include = include; if (bound->type == NODE_TYPE_VALUE) { _bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, bound->toJsonValue(TRI_UNKNOWN_MEM_ZONE)); _isConstant = true; _expressionAst = nullptr; } else { _bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, bound->toJson(TRI_UNKNOWN_MEM_ZONE, true)); _isConstant = false; _expressionAst = bound; } _defined = true; } void assign (RangeInfoBound const& copy) { _bound = copy._bound.copy(); _include = copy._include; _isConstant = copy._isConstant; _defined = copy._defined; _expressionAst = copy._expressionAst; } //////////////////////////////////////////////////////////////////////////////// /// @brief toJson //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json toJson() const { triagens::basics::Json item(basics::Json::Object, 3); if (! _bound.isEmpty()) { item("bound", _bound.copy()); } item("include", triagens::basics::Json(_include)) ("isConstant", triagens::basics::Json(!_defined || _isConstant)); return item; } //////////////////////////////////////////////////////////////////////////////// /// @brief toIndexOperator, doesn't work with unbounded above and below /// RangeInfos and only for constant values //////////////////////////////////////////////////////////////////////////////// TRI_index_operator_t* toIndexOperator (bool high, triagens::basics::Json parameters, VocShaper* shaper) const { TRI_ASSERT(_isConstant); TRI_index_operator_type_e op; if (high) { if (_include) { op = TRI_LE_INDEX_OPERATOR; } else { op = TRI_LT_INDEX_OPERATOR; } } else { if (_include) { op = TRI_GE_INDEX_OPERATOR; } else { op = TRI_GT_INDEX_OPERATOR; } } parameters.add(_bound.copy()); size_t nr = parameters.size(); return TRI_CreateIndexOperator(op, nullptr, nullptr, parameters.steal(), shaper, nr); } //////////////////////////////////////////////////////////////////////////////// /// @brief andCombineLowerBounds, changes the bound in *this and replaces /// it by the stronger bound of *this and that, interpreting both as lower /// bounds. //////////////////////////////////////////////////////////////////////////////// void andCombineLowerBounds (RangeInfoBound const& that); //////////////////////////////////////////////////////////////////////////////// /// @brief andCombineUpperBounds, changes the bound in *this and replaces /// it by the stronger bound of *this and that, interpreting both as upper /// bounds. //////////////////////////////////////////////////////////////////////////////// void andCombineUpperBounds (RangeInfoBound const& that); //////////////////////////////////////////////////////////////////////////////// /// @brief getter for bound //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json const& bound () const { return _bound; } //////////////////////////////////////////////////////////////////////////////// /// @brief getter for inclusion //////////////////////////////////////////////////////////////////////////////// bool inclusive () const { return _include; } //////////////////////////////////////////////////////////////////////////////// /// @brief setter for inclusion //////////////////////////////////////////////////////////////////////////////// void setInclude (bool value) { _include = value; } //////////////////////////////////////////////////////////////////////////////// /// @brief getter for isConstant //////////////////////////////////////////////////////////////////////////////// bool isConstant () const { return ! _defined || _isConstant; } //////////////////////////////////////////////////////////////////////////////// /// @brief getter for isDefined //////////////////////////////////////////////////////////////////////////////// bool isDefined () const { return _defined; } //////////////////////////////////////////////////////////////////////////////// /// @brief getExpressionAst, looks up or computes (if necessary) an AST /// for the variable bound, return nullptr for a constant bound, the new /// (if needed) nodes are registered with the ast //////////////////////////////////////////////////////////////////////////////// AstNode const* getExpressionAst (Ast*) const; // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- private: //////////////////////////////////////////////////////////////////////////////// /// @brief _bound as Json, this is either for constant values /// (_isConstant==true) or for JSON-serialised subexpressions /// (_isConstant==false). //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json _bound; //////////////////////////////////////////////////////////////////////////////// /// @brief _include, flag indicating whether or not bound is included //////////////////////////////////////////////////////////////////////////////// bool _include; //////////////////////////////////////////////////////////////////////////////// /// @brief _isConstant, this is true if the bound is a constant value //////////////////////////////////////////////////////////////////////////////// bool _isConstant; //////////////////////////////////////////////////////////////////////////////// /// @brief _defined, if this is true if the bound is defined //////////////////////////////////////////////////////////////////////////////// bool _defined; //////////////////////////////////////////////////////////////////////////////// /// @brief _expressionAst, this remembers the AST for the expression /// in the variable case, for constant expressions this is always a nullptr. /// If the bound is made from Json, then _expressionAst is initially set /// to nullptr and only later computed by getExpressionAst and then /// cached. Note that the memory management is done by an object of type /// Ast outside of this class. Therefore the destructor does not delete /// the pointer here. //////////////////////////////////////////////////////////////////////////////// AstNode mutable const* _expressionAst; }; // ----------------------------------------------------------------------------- // --SECTION-- struct RangeInfo // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief struct to keep a list of RangeInfoBounds for _lows and one for ///_highs, as well as constant _lowConst and _highConst. All constant bounds /// will be combined into _lowConst and _highConst respectively, they /// can also be not _defined. All bounds in _lows and _highs are defined /// and not constant. The flag _defined is only false if the whole RangeInfo /// is not defined (default constructor). /// This struct keeps _valid and _equality up to date at all times. /// _valid is false iff the range is known to be empty. _equality is /// true iff upper and lower bounds were given as (list of) identical /// pairs. Note that _equality can be set and yet we only notice that /// the RangeInfo is empty at runtime, if more than one equality was given! //////////////////////////////////////////////////////////////////////////////// struct RangeInfo { //////////////////////////////////////////////////////////////////////////////// /// @brief constructors //////////////////////////////////////////////////////////////////////////////// RangeInfo (std::string const& var, std::string const& attr, RangeInfoBound const& low, RangeInfoBound const& high, bool equality) : _var(var), _attr(attr), _valid(true), _defined(true), _equality(equality) { if (low.isConstant()) { _lowConst.assign(low); } else { _lows.emplace_back(low); } if (high.isConstant()) { _highConst.assign(high); } else { _highs.emplace_back(high); } // Maybe the range is known to be invalid right away? if (_lowConst.isDefined() && _lowConst.isConstant() && _highConst.isDefined() && _highConst.isConstant()) { int cmp = TRI_CompareValuesJson(_lowConst.bound().json(), _highConst.bound().json(), true); if (cmp == 1) { _valid = false; } else if (cmp == 0) { if (_lowConst.inclusive() && _highConst.inclusive()) { _equality = true; } else { _valid = false; } } } } RangeInfo (std::string const& var, std::string const& attr, RangeInfoBound const& bound) : _var(var), _attr(attr), _valid(true), _defined(true), _equality(true) { // must be an equality here! TRI_ASSERT(bound.inclusive()); if (bound.isConstant()) { _lowConst.assign(bound); _highConst.assign(bound); } else { _lows.emplace_back(bound); _highs.emplace_back(bound); } } RangeInfo (std::string const& var, std::string const& attr) : _var(var), _attr(attr), _valid(true), _defined(true), _equality(false) { } RangeInfo () : _valid(false), _defined(false), _equality(false) { } RangeInfo (basics::Json const& json); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor //////////////////////////////////////////////////////////////////////////////// ~RangeInfo () { } //////////////////////////////////////////////////////////////////////////////// /// @brief delete assignment operator //////////////////////////////////////////////////////////////////////////////// RangeInfo& operator= (RangeInfo const& copy) = delete; // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief toJson //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json toJson () const; //////////////////////////////////////////////////////////////////////////////// /// @brief toString //////////////////////////////////////////////////////////////////////////////// std::string toString () const { return this->toJson().toString(); } //////////////////////////////////////////////////////////////////////////////// /// @brief is1ValueRangeInfo //////////////////////////////////////////////////////////////////////////////// // is the range a unique value (i.e. something like x<=1 and x>=1), // note again that with variable bounds it can turn out only at // runTime that two or more expressions actually contradict each other. // In this case this method will return true nevertheless. bool is1ValueRangeInfo () const { if (! _defined || ! _valid) { return false; } return _equality; } //////////////////////////////////////////////////////////////////////////////// /// @brief isDefined, getter for _defined //////////////////////////////////////////////////////////////////////////////// bool isDefined () const { return _defined; } //////////////////////////////////////////////////////////////////////////////// /// @brief isValid, getter for _valid //////////////////////////////////////////////////////////////////////////////// bool isValid () const { return _valid; } //////////////////////////////////////////////////////////////////////////////// /// @brief invalidate //////////////////////////////////////////////////////////////////////////////// void invalidate () { _valid = false; } //////////////////////////////////////////////////////////////////////////////// /// @brief isConstant //////////////////////////////////////////////////////////////////////////////// bool isConstant () const { if (! _defined) { return false; } if (! _valid) { return true; } return _lows.size() == 0 && _highs.size() == 0; } //////////////////////////////////////////////////////////////////////////////// /// @brief fuse, fuse two ranges, must be for the same variable and attribute //////////////////////////////////////////////////////////////////////////////// void fuse (RangeInfo const& that); // ----------------------------------------------------------------------------- // --SECTION-- public variables // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief _var, the AQL variable name //////////////////////////////////////////////////////////////////////////////// std::string _var; //////////////////////////////////////////////////////////////////////////////// /// @brief _attr, the attribute access in the variable, can have dots meaning /// deep access //////////////////////////////////////////////////////////////////////////////// std::string _attr; //////////////////////////////////////////////////////////////////////////////// /// @brief _lows, all non-constant lower bounds //////////////////////////////////////////////////////////////////////////////// std::list _lows; //////////////////////////////////////////////////////////////////////////////// /// @brief _lowConst, all constant lower bounds combined, or not _defined //////////////////////////////////////////////////////////////////////////////// RangeInfoBound _lowConst; //////////////////////////////////////////////////////////////////////////////// /// @brief _highs, all non-constant upper bounds //////////////////////////////////////////////////////////////////////////////// std::list _highs; //////////////////////////////////////////////////////////////////////////////// /// @brief _highConst, all constant upper bounds combined, or not _defined //////////////////////////////////////////////////////////////////////////////// RangeInfoBound _highConst; //////////////////////////////////////////////////////////////////////////////// /// @brief revokeEquality, this is used when we withdraw a variable bound, /// in that case we can no longer trust the _equality bit, no big harm is /// done, except that we no longer know that the range is only at most a /// single value //////////////////////////////////////////////////////////////////////////////// void revokeEquality () { _equality = false; } //////////////////////////////////////////////////////////////////////////////// /// @brief clone //////////////////////////////////////////////////////////////////////////////// RangeInfo clone () const { RangeInfo copy(_var, _attr); copy._lowConst.assign(_lowConst); copy._highConst.assign(_highConst); for (auto const& x : _lows) { copy._lows.emplace_back(x); } for (auto const& x : _highs) { copy._highs.emplace_back(x); } copy._valid = _valid; copy._defined = _defined; copy._equality = _equality; return copy; } // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- private: //////////////////////////////////////////////////////////////////////////////// /// @brief _valid, this is set to true iff the range is known to be non-empty //////////////////////////////////////////////////////////////////////////////// bool _valid; //////////////////////////////////////////////////////////////////////////////// /// @brief _defined, this is set iff the range is defined //////////////////////////////////////////////////////////////////////////////// bool _defined; //////////////////////////////////////////////////////////////////////////////// /// @brief _equality, range is known to be an equality //////////////////////////////////////////////////////////////////////////////// bool _equality; }; // ----------------------------------------------------------------------------- // --SECTION-- class RangeInfoMap // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief class to keep RangeInfos associated to variable and attribute names. //////////////////////////////////////////////////////////////////////////////// class RangeInfoMap { public: RangeInfoMap (RangeInfoMap const& copy) = delete; RangeInfoMap& operator= (RangeInfoMap const& copy) = delete; //////////////////////////////////////////////////////////////////////////////// /// @brief default constructor //////////////////////////////////////////////////////////////////////////////// RangeInfoMap () : _ranges() { } //////////////////////////////////////////////////////////////////////////////// /// @brief construct RangeInfoMap containing single RangeInfo created from the /// args //////////////////////////////////////////////////////////////////////////////// RangeInfoMap (std::string const& var, std::string const& name, RangeInfoBound const& low, RangeInfoBound const& high, bool equality); RangeInfoMap (RangeInfo const&); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor //////////////////////////////////////////////////////////////////////////////// ~RangeInfoMap() { } // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief find, find all the range infos for variable , /// ownership is not transferred //////////////////////////////////////////////////////////////////////////////// std::unordered_map const* find (std::string const& var) const { auto it = _ranges.find(var); if (it == _ranges.end()) { return nullptr; } return &((*it).second); } //////////////////////////////////////////////////////////////////////////////// /// @brief find, find all the range infos for variable , /// ownership is not transferred //////////////////////////////////////////////////////////////////////////////// std::unordered_map* find (std::string const& var) { auto it = _ranges.find(var); if (it == _ranges.end()) { return nullptr; } return &((*it).second); } //////////////////////////////////////////////////////////////////////////////// /// @brief find, find all the range info for variable and attribute /// ownership is not transferred //////////////////////////////////////////////////////////////////////////////// RangeInfo* find (std::string const& var, std::string const& attr) { auto map = find(var); if (map == nullptr) { return nullptr; } auto it = map->find(attr); if (it == map->end()) { return nullptr; } return &((*it).second); } //////////////////////////////////////////////////////////////////////////////// /// @brief insert, insert if it's not already there and otherwise /// intersection with existing range, for variable values we keep them all. /// The equality flag should be set if and only if the caller knows that the /// lower and upper bound are equal, this is particularly important if the /// bounds are variable and can only be computed at runtime. //////////////////////////////////////////////////////////////////////////////// void insert (std::string const& var, std::string const& name, RangeInfoBound const& low, RangeInfoBound const& high, bool equality); //////////////////////////////////////////////////////////////////////////////// /// @brief insert an equality //////////////////////////////////////////////////////////////////////////////// void insert (std::string const& var, std::string const& name, RangeInfoBound const& bound); //////////////////////////////////////////////////////////////////////////////// /// @brief insert, directly using a RangeInfo structure //////////////////////////////////////////////////////////////////////////////// void insert (RangeInfo const& range); //////////////////////////////////////////////////////////////////////////////// /// @brief erase //////////////////////////////////////////////////////////////////////////////// void erase (RangeInfo*); //////////////////////////////////////////////////////////////////////////////// /// @brief size, the number of range infos stored //////////////////////////////////////////////////////////////////////////////// size_t size () const { return _ranges.size(); } //////////////////////////////////////////////////////////////////////////////// /// @brief empty, the number of range infos stored //////////////////////////////////////////////////////////////////////////////// bool empty () const { return _ranges.empty(); } //////////////////////////////////////////////////////////////////////////////// /// @brief toString, via Json //////////////////////////////////////////////////////////////////////////////// std::string toString() const { return this->toJson().toString(); } //////////////////////////////////////////////////////////////////////////////// /// @brief toJson //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json toJson() const { triagens::basics::Json list(triagens::basics::Json::Array); for (auto const& x : _ranges) { for (auto const& y : x.second) { triagens::basics::Json item(triagens::basics::Json::Object); item("variable", triagens::basics::Json(x.first)) ("attribute name", triagens::basics::Json(y.first)) ("range info", y.second.toJson()); list(item); } } return list; } //////////////////////////////////////////////////////////////////////////////// /// @brief clone //////////////////////////////////////////////////////////////////////////////// RangeInfoMap* clone () const; //////////////////////////////////////////////////////////////////////////////// /// @brief eraseEmptyOrUndefined remove all empty or undefined RangeInfos for /// the variable in the RIM //////////////////////////////////////////////////////////////////////////////// void eraseEmptyOrUndefined (std::string const&); //////////////////////////////////////////////////////////////////////////////// /// @brief isValid: are all the range infos for the variable valid? //////////////////////////////////////////////////////////////////////////////// bool isValid (std::string const&) const; //////////////////////////////////////////////////////////////////////////////// /// @brief attributes: insert attributes of the variable into set //////////////////////////////////////////////////////////////////////////////// void attributes (std::unordered_set& set, std::string const& var) const; //////////////////////////////////////////////////////////////////////////////// /// @brief return the names of variables contained in the RangeInfoMap //////////////////////////////////////////////////////////////////////////////// std::unordered_set variables() const; //////////////////////////////////////////////////////////////////////////////// /// @brief private data /// TODO: make iterators for this i.e. method for begin and end, so that this /// can be private //////////////////////////////////////////////////////////////////////////////// std::unordered_map> _ranges; }; // ----------------------------------------------------------------------------- // --SECTION-- class RangeInfoMapVec // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief class to keep a vector of rangeInfoMapVec associated to variable and /// attribute names, which will be or-combined //////////////////////////////////////////////////////////////////////////////// class RangeInfoMapVec { public: RangeInfoMapVec (RangeInfoMapVec const& copy) = delete; RangeInfoMapVec& operator= (RangeInfoMapVec const& copy) = delete; //////////////////////////////////////////////////////////////////////////////// /// @brief default constructor //////////////////////////////////////////////////////////////////////////////// RangeInfoMapVec () : _rangeInfoMapVec() { } //////////////////////////////////////////////////////////////////////////////// /// @brief constructor: construct RangeInfoMapVec containing a single /// RangeInfoMap containing a single RangeInfo. //////////////////////////////////////////////////////////////////////////////// explicit RangeInfoMapVec (RangeInfoMap* rim); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor //////////////////////////////////////////////////////////////////////////////// ~RangeInfoMapVec(); // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief toString, via Json //////////////////////////////////////////////////////////////////////////////// std::string toString() const { return this->toJson().toString(); } //////////////////////////////////////////////////////////////////////////////// /// @brief toJson //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json toJson() const { size_t const n = _rangeInfoMapVec.size(); triagens::basics::Json result(triagens::basics::Json::Array, n); for (size_t i = 0; i < n; i++) { result(_rangeInfoMapVec[i]->toJson()); } return result; } //////////////////////////////////////////////////////////////////////////////// /// @brief operator[] //////////////////////////////////////////////////////////////////////////////// RangeInfoMap* operator[] (size_t pos) { return _rangeInfoMapVec[pos]; } //////////////////////////////////////////////////////////////////////////////// /// @brief size: the number of RangeInfoMaps in the vector //////////////////////////////////////////////////////////////////////////////// size_t size () const { return _rangeInfoMapVec.size(); } //////////////////////////////////////////////////////////////////////////////// /// @brief empty: is the vector of RangeInfoMaps empty //////////////////////////////////////////////////////////////////////////////// bool empty () const { return _rangeInfoMapVec.empty(); } //////////////////////////////////////////////////////////////////////////////// /// @brief reserve space in vector //////////////////////////////////////////////////////////////////////////////// void reserve (size_t); //////////////////////////////////////////////////////////////////////////////// /// @brief emplace_back: emplace_back RangeInfoMap in vector //////////////////////////////////////////////////////////////////////////////// void emplace_back (RangeInfoMap*); //////////////////////////////////////////////////////////////////////////////// /// @brief eraseEmptyOrUndefined remove all empty or undefined RangeInfos for /// the variable in every RangeInfoMap in the vector //////////////////////////////////////////////////////////////////////////////// void eraseEmptyOrUndefined (std::string const& var); //////////////////////////////////////////////////////////////////////////////// /// @brief find: this is the same as _rangeInfoMapVec[pos]->find(var), i.e. find /// the map of RangeInfos for the variable . //////////////////////////////////////////////////////////////////////////////// std::unordered_map* find (std::string const& var, size_t pos) const; //////////////////////////////////////////////////////////////////////////////// /// @brief differenceRangeInfo: returns the difference of the constant parts of /// the given RangeInfo and the union of the RangeInfos (for the same var and /// attr) in the vector. Potentially modifies both the argument and the /// RangeInfos in the vector. //////////////////////////////////////////////////////////////////////////////// void differenceRangeInfo (RangeInfo&); //////////////////////////////////////////////////////////////////////////////// /// @brief isMapped: is the input variable in every RIM in the vector //////////////////////////////////////////////////////////////////////////////// bool isMapped (std::string const&) const; //////////////////////////////////////////////////////////////////////////////// /// @brief validPositions: returns a vector of the positions in the RIM vector /// that contain valid RangeInfoMap for the variable named var //////////////////////////////////////////////////////////////////////////////// std::vector validPositions (std::string const& var) const; //////////////////////////////////////////////////////////////////////////////// /// @brief attributes: returns a vector of the names of the attributes for the /// variable var stored in the RIM vector (i.e. stored in some RIM in the /// vector). //////////////////////////////////////////////////////////////////////////////// std::unordered_set attributes (std::string const& var) const; //////////////////////////////////////////////////////////////////////////////// /// @brief private data //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- private: std::vector _rangeInfoMapVec; }; //////////////////////////////////////////////////////////////////////////////// /// @brief andCombineRangeInfoMaps: insert every RangeInfo in the right argument /// in a new copy of the left argument //////////////////////////////////////////////////////////////////////////////// RangeInfoMap* andCombineRangeInfoMaps (RangeInfoMap*, RangeInfoMap const*); //////////////////////////////////////////////////////////////////////////////// /// @brief orCombineRangeInfoMapVecs: return a new RangeInfoMapVec appending /// those RIMs in the right arg (which are not identical to an existing RIM) in /// a copy of the left arg. /// /// The return RIMV is new unless one of the arguments is empty. //////////////////////////////////////////////////////////////////////////////// RangeInfoMapVec* orCombineRangeInfoMapVecs (RangeInfoMapVec*, RangeInfoMapVec*); //////////////////////////////////////////////////////////////////////////////// /// @brief andCombineRangeInfoMapVecs: return a new RangeInfoMapVec by /// distributing the AND into the ORs in a condition like: /// (OR condition) AND (OR condition). /// /// The return RIMV is new unless one of the arguments is empty. //////////////////////////////////////////////////////////////////////////////// RangeInfoMapVec* andCombineRangeInfoMapVecs (RangeInfoMapVec*, RangeInfoMapVec*); //////////////////////////////////////////////////////////////////////////////// /// @brief andCombineRangeInfoMapVecs: same as before, but will return the /// mapvec even if one side is a nullptr //////////////////////////////////////////////////////////////////////////////// RangeInfoMapVec* andCombineRangeInfoMapVecsIgnoreEmpty (RangeInfoMapVec*, RangeInfoMapVec*); //////////////////////////////////////////////////////////////////////////////// /// @brief IndexOrCondition, type for vector of vector of RangeInfo. The meaning /// is: the outer vector means an implicit "OR" between the entries. Each /// entry is a vector whose entries correspond to the attributes of the /// index. They are a RangeInfo specifying the condition for that attribute. /// Note that in the variable range bound case one RangeInfo can contain /// multiple conditions which are implicitly "AND"ed. //////////////////////////////////////////////////////////////////////////////// typedef std::vector IndexAndCondition; typedef std::vector IndexOrCondition; //////////////////////////////////////////////////////////////////////////////// /// @brief differenceRangeInfos: returns the difference of the constant parts of /// the given RangeInfos. /// /// Modifies either lhs or rhs in place, so that the constant parts of lhs /// and rhs are disjoint, and the union of the modified lhs and rhs equals the /// union of the originals. //////////////////////////////////////////////////////////////////////////////// void differenceRangeInfos (RangeInfo&, RangeInfo&); //////////////////////////////////////////////////////////////////////////////// // @brief areDisjointRangeInfos: returns true if the constant parts of lhs and // rhs are disjoint and false otherwise. // Only for range infos with the same variable and attribute //////////////////////////////////////////////////////////////////////////////// bool areDisjointRangeInfos (RangeInfo const&, RangeInfo const&); //////////////////////////////////////////////////////////////////////////////// /// @brief areDisjointIndexAndConditions: returns true if the arguments describe /// disjoint sets. //////////////////////////////////////////////////////////////////////////////// bool areDisjointIndexAndConditions (IndexAndCondition const&, IndexAndCondition const&); //////////////////////////////////////////////////////////////////////////////// /// @brief isContainedIndexAndConditions: returns true if the first argument is /// contained in the second, and false otherwise. //////////////////////////////////////////////////////////////////////////////// bool isContainedIndexAndConditions (IndexAndCondition const&, IndexAndCondition const&); //////////////////////////////////////////////////////////////////////////////// /// @brief differenceIndexAnd: modifies and1 and and2 in place /// so that the intersection of the sets they describe is empty and their union /// is the same as if the function was never called. //////////////////////////////////////////////////////////////////////////////// void differenceIndexAnd (IndexAndCondition&, IndexAndCondition&); //////////////////////////////////////////////////////////////////////////////// /// @brief isContainedIndexAndConditions: returns true if the first argument is /// contained in the second, and false otherwise. //////////////////////////////////////////////////////////////////////////////// void removeOverlapsIndexOr (IndexOrCondition&); } } #endif // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" // End: