summaryrefslogtreecommitdiff
path: root/src/mongo/bson/bsonobj_comparator_interface.h
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2016-08-12 15:58:56 -0400
committerDavid Storch <david.storch@10gen.com>2016-08-18 11:14:17 -0400
commit26543060c852aac22f26143a04bf7789ec8fec53 (patch)
treedf3ae49e5c4745058be29b7ec8a8e4b528b50a9a /src/mongo/bson/bsonobj_comparator_interface.h
parent13fa28982d008568f7620d73ddec0c61fad7cbc8 (diff)
downloadmongo-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.h195
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