// expression_array.h /** * Copyright (C) 2013 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ #pragma once #include #include "mongo/base/status.h" #include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonmisc.h" #include "mongo/db/matcher/expression.h" #include "mongo/db/matcher/expression_leaf.h" namespace mongo { /** * ALL and ELEM_MATCH inherit from this. */ class ArrayMatchingMatchExpression : public MatchExpression { public: ArrayMatchingMatchExpression( MatchType matchType ) : MatchExpression( matchType ){} virtual ~ArrayMatchingMatchExpression(){} Status initPath( const StringData& path ); virtual bool matches( const MatchableDocument* doc, MatchDetails* details ) const; /** * @param e - has to be an array. calls matchesArray with e as an array */ virtual bool matchesSingleElement( const BSONElement& e ) const; virtual bool matchesArray( const BSONObj& anArray, MatchDetails* details ) const = 0; bool equivalent( const MatchExpression* other ) const; const StringData path() const { return _path; } private: StringData _path; ElementPath _elementPath; }; class ElemMatchObjectMatchExpression : public ArrayMatchingMatchExpression { public: ElemMatchObjectMatchExpression() : ArrayMatchingMatchExpression( ELEM_MATCH_OBJECT ){} Status init( const StringData& path, MatchExpression* sub ); bool matchesArray( const BSONObj& anArray, MatchDetails* details ) const; virtual ElemMatchObjectMatchExpression* shallowClone() const { ElemMatchObjectMatchExpression* e = new ElemMatchObjectMatchExpression(); e->init(path(), _sub->shallowClone()); if ( getTag() ) { e->setTag(getTag()->clone()); } return e; } virtual void debugString( StringBuilder& debug, int level ) const; virtual size_t numChildren() const { return 1; } virtual MatchExpression* getChild( size_t i ) const { return _sub.get(); } private: boost::scoped_ptr _sub; }; class ElemMatchValueMatchExpression : public ArrayMatchingMatchExpression { public: ElemMatchValueMatchExpression() : ArrayMatchingMatchExpression( ELEM_MATCH_VALUE ){} virtual ~ElemMatchValueMatchExpression(); Status init( const StringData& path ); Status init( const StringData& path, MatchExpression* sub ); void add( MatchExpression* sub ); bool matchesArray( const BSONObj& anArray, MatchDetails* details ) const; virtual ElemMatchValueMatchExpression* shallowClone() const { ElemMatchValueMatchExpression* e = new ElemMatchValueMatchExpression(); e->init(path()); for (size_t i = 0; i < _subs.size(); ++i) { e->add(_subs[i]->shallowClone()); } if ( getTag() ) { e->setTag(getTag()->clone()); } return e; } virtual void debugString( StringBuilder& debug, int level ) const; virtual size_t numChildren() const { return _subs.size(); } virtual MatchExpression* getChild( size_t i ) const { return _subs[i]; } private: bool _arrayElementMatchesAll( const BSONElement& e ) const; std::vector _subs; }; class SizeMatchExpression : public ArrayMatchingMatchExpression { public: SizeMatchExpression() : ArrayMatchingMatchExpression( SIZE ){} Status init( const StringData& path, int size ); virtual SizeMatchExpression* shallowClone() const { SizeMatchExpression* e = new SizeMatchExpression(); e->init(path(), _size); if ( getTag() ) { e->setTag(getTag()->clone()); } return e; } virtual bool matchesArray( const BSONObj& anArray, MatchDetails* details ) const; virtual void debugString( StringBuilder& debug, int level ) const; virtual bool equivalent( const MatchExpression* other ) const; int getData() const { return _size; } private: int _size; // >= 0 real, < 0, nothing will match }; /** * i'm suprised this isn't a regular AllMatchExpression */ class AllElemMatchOp : public MatchExpression { public: AllElemMatchOp() : MatchExpression( ALL ){} virtual ~AllElemMatchOp(); Status init( const StringData& path ); void add( ArrayMatchingMatchExpression* expr ); virtual MatchExpression* shallowClone() const { AllElemMatchOp* e = new AllElemMatchOp(); e->init(path()); for (size_t i = 0; i < _list.size(); ++i) { e->add(reinterpret_cast( _list[i]->shallowClone())); } if ( getTag() ) { e->setTag(getTag()->clone()); } return e; } virtual bool matches( const MatchableDocument* doc, MatchDetails* details ) const; /** * @param e has to be an array */ virtual bool matchesSingleElement( const BSONElement& e ) const; virtual void debugString( StringBuilder& debug, int level ) const; virtual bool equivalent( const MatchExpression* other ) const; virtual size_t numChildren() const { return _list.size(); } virtual MatchExpression* getChild( size_t i ) const { return _list[i]; } virtual std::vector* getChildVector() { return &_list; } const StringData path() const { return _path; } private: bool _allMatch( const BSONObj& anArray ) const; StringData _path; ElementPath _elementPath; std::vector _list; }; }