diff options
author | David Storch <david.storch@10gen.com> | 2016-08-12 15:58:56 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2016-08-18 11:14:17 -0400 |
commit | 26543060c852aac22f26143a04bf7789ec8fec53 (patch) | |
tree | df3ae49e5c4745058be29b7ec8a8e4b528b50a9a /src/mongo/bson/bsonobj_comparator_interface.h | |
parent | 13fa28982d008568f7620d73ddec0c61fad7cbc8 (diff) | |
download | mongo-26543060c852aac22f26143a04bf7789ec8fec53.tar.gz |
SERVER-24508 BSONObj::ComparatorInterface
BSONObj instances should now be compared via the comparator
interface's evaluate() method. This preferred over using
BSONObj::woCompare() directly. If the comparison doesn't
require any database semantics (e.g. there is no collation),
there is a global instance of the SimpleBSONObjComparator
which should be used for BSONObj comparisons. If the
comparison requires special semantics, then callers must
instantiate their own comparator object.
Diffstat (limited to 'src/mongo/bson/bsonobj_comparator_interface.h')
-rw-r--r-- | src/mongo/bson/bsonobj_comparator_interface.h | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/mongo/bson/bsonobj_comparator_interface.h b/src/mongo/bson/bsonobj_comparator_interface.h new file mode 100644 index 00000000000..56fa736dab0 --- /dev/null +++ b/src/mongo/bson/bsonobj_comparator_interface.h @@ -0,0 +1,195 @@ +/** + * Copyright (C) 2016 MongoDB 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 <http://www.gnu.org/licenses/>. + * + * 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 <map> +#include <set> +#include <unordered_map> +#include <unordered_set> + +#include "mongo/base/disallow_copying.h" +#include "mongo/bson/bsonobj.h" +#include "mongo/util/assert_util.h" + +namespace mongo { + +/** + * A BSONObj::ComparatorInterface is an abstract class for comparing BSONObj objects. Usage for + * comparing two BSON objects, 'lhs' and 'rhs', where 'comparator' is an instance of a class + * implementing this interface, is as shown below: + * + * bool lessThan = comparator.evaluate(lhs < rhs); + * bool lessThanOrEqual = comparator.evaluate(lhs <= rhs); + * bool equal = comparator.evaluate(lhs == rhs); + * bool greaterThanOrEqual = comparator.evaluate(lhs >= rhs); + * bool greaterThan = comparator.evaluate(lhs > rhs); + * bool notEqual = comparator.evaluate(lhs != rhs); + * + * Can also be used to obtain function objects compatible for use with standard library algorithms + * such as std::sort, and to construct STL sets and maps which respect this comparator. + * + * All methods are thread-safe. + */ +class BSONObj::ComparatorInterface { + MONGO_DISALLOW_COPYING(ComparatorInterface); + +public: + /** + * Functor compatible for use with ordered STL containers. + */ + class LessThan { + public: + explicit LessThan(const ComparatorInterface* comparator) : _comparator(comparator) {} + + bool operator()(const BSONObj& lhs, const BSONObj& rhs) const { + return _comparator->compare(lhs, rhs) < 0; + } + + private: + const ComparatorInterface* _comparator; + }; + + /** + * Functor compatible for use with unordered STL containers. + */ + class EqualTo { + public: + explicit EqualTo(const ComparatorInterface* comparator) : _comparator(comparator) {} + + bool operator()(const BSONObj& lhs, const BSONObj& rhs) const { + return _comparator->compare(lhs, rhs) == 0; + } + + private: + const ComparatorInterface* _comparator; + }; + + using BSONObjSet = std::set<BSONObj, BSONObj::ComparatorInterface::LessThan>; + + // TODO SERVER-23990: Make the BSONObj hash collation-aware. + using BSONObjUnorderedSet = + std::unordered_set<BSONObj, BSONObj::Hasher, BSONObj::ComparatorInterface::EqualTo>; + + template <typename T> + using BSONObjMap = std::map<BSONObj, T, BSONObj::ComparatorInterface::LessThan>; + + // TODO SERVER-23990: Make the BSONObj hash collation-aware. + template <typename T> + using BSONObjIndexedMap = + std::unordered_map<BSONObj, T, BSONObj::Hasher, BSONObj::ComparatorInterface::EqualTo>; + + virtual ~ComparatorInterface() = default; + + /** + * Compares two BSONObj objects. Returns <0, 0, >0 if 'lhs' < 'rhs', 'lhs' == 'rhs', or 'lhs' > + * 'rhs' respectively. + */ + virtual int compare(const BSONObj& lhs, const BSONObj& rhs) const = 0; + + /** + * Evaluates a deferred comparison object generated by invocation of one of the BSONObj operator + * overloads for relops. + */ + bool evaluate(BSONObj::DeferredComparison deferredComparison) const { + int cmp = compare(deferredComparison.lhs, deferredComparison.rhs); + switch (deferredComparison.type) { + case BSONObj::DeferredComparison::Type::kLT: + return cmp < 0; + case BSONObj::DeferredComparison::Type::kLTE: + return cmp <= 0; + case BSONObj::DeferredComparison::Type::kEQ: + return cmp == 0; + case BSONObj::DeferredComparison::Type::kGT: + return cmp > 0; + case BSONObj::DeferredComparison::Type::kGTE: + return cmp >= 0; + case BSONObj::DeferredComparison::Type::kNE: + return cmp != 0; + } + + MONGO_UNREACHABLE; + } + + /** + * Returns a function object which computes whether one BSONObj is less than another under this + * comparator. This comparator must outlive the returned function object. + */ + LessThan makeLessThan() const { + return LessThan(this); + } + + /** + * Returns a function object which computes whether one BSONObj is equal to another under this + * comparator. This comparator must outlive the returned function object. + */ + EqualTo makeEqualTo() const { + return EqualTo(this); + } + + /** + * Construct an empty BSONObjSet whose ordering is given by this comparator. This comparator + * must outlive the returned set. + */ + BSONObjSet makeOrderedBSONObjSet() const { + return BSONObjSet(LessThan(this)); + } + + /** + * Construct an empty BSONObjUnorderedSet whose equivalence classes are given by this + * comparator. This comparator must outlive the returned set. + */ + BSONObjUnorderedSet makeUnorderedBSONObjSet() const { + // TODO SERVER-23990: Make the BSONObj hash collation-aware. + return BSONObjUnorderedSet(0, BSONObj::Hasher(), EqualTo(this)); + } + + /** + * Construct an empty ordered map from BSONObj to type T whose ordering is given by this + * comparator. This comparator must outlive the returned map. + */ + template <typename T> + BSONObjMap<T> makeOrderedBSONObjMap() const { + return BSONObjMap<T>(LessThan(this)); + } + + /** + * Construct an empty unordered map from BSONObj to type T whose ordering is given by this + * comparator. This comparator must outlive the returned map. + */ + template <typename T> + BSONObjIndexedMap<T> makeBSONObjIndexedMap() const { + // TODO SERVER-23990: Make the BSONObj hash collation-aware. + return BSONObjIndexedMap<T>(0, BSONObj::Hasher(), EqualTo(this)); + } + +protected: + constexpr ComparatorInterface() = default; +}; + +} // namespace mongo |