diff options
-rw-r--r-- | src/mongo/bson/mutable/const_element-inl.h | 4 | ||||
-rw-r--r-- | src/mongo/bson/mutable/const_element.h | 1 | ||||
-rw-r--r-- | src/mongo/bson/mutable/document.cpp | 9 | ||||
-rw-r--r-- | src/mongo/bson/mutable/element.h | 5 | ||||
-rw-r--r-- | src/mongo/bson/mutable/mutable_bson_test.cpp | 38 |
5 files changed, 57 insertions, 0 deletions
diff --git a/src/mongo/bson/mutable/const_element-inl.h b/src/mongo/bson/mutable/const_element-inl.h index 034b915f619..1af561a515b 100644 --- a/src/mongo/bson/mutable/const_element-inl.h +++ b/src/mongo/bson/mutable/const_element-inl.h @@ -29,6 +29,10 @@ namespace mutablebson { return _basis.rightChild(); } + inline bool ConstElement::hasChildren() const { + return _basis.hasChildren(); + } + inline ConstElement ConstElement::leftSibling() const { return _basis.leftSibling(); } diff --git a/src/mongo/bson/mutable/const_element.h b/src/mongo/bson/mutable/const_element.h index 593f07304d7..c3b751c43fa 100644 --- a/src/mongo/bson/mutable/const_element.h +++ b/src/mongo/bson/mutable/const_element.h @@ -42,6 +42,7 @@ namespace mutablebson { inline ConstElement leftChild() const; inline ConstElement rightChild() const; + inline bool hasChildren() const; inline ConstElement leftSibling() const; inline ConstElement rightSibling() const; inline ConstElement parent() const; diff --git a/src/mongo/bson/mutable/document.cpp b/src/mongo/bson/mutable/document.cpp index d4b524b81d3..263d4ef579a 100644 --- a/src/mongo/bson/mutable/document.cpp +++ b/src/mongo/bson/mutable/document.cpp @@ -1075,6 +1075,15 @@ namespace mutablebson { return Element(_doc, current); } + bool Element::hasChildren() const { + verify(ok()); + // Capturing Document::Impl by non-const ref exploits the constness loophole + // created by our Impl so that we can let leftChild be lazily evaluated, even for a + // const Element. + Document::Impl& impl = _doc->getImpl(); + return impl.resolveLeftChild(_repIdx) != kInvalidRepIdx; + } + Element Element::leftSibling() const { verify(ok()); diff --git a/src/mongo/bson/mutable/element.h b/src/mongo/bson/mutable/element.h index 30404411c83..8e237284c1d 100644 --- a/src/mongo/bson/mutable/element.h +++ b/src/mongo/bson/mutable/element.h @@ -157,6 +157,11 @@ namespace mutablebson { */ Element rightChild() const; + /** Returns true if this element has children. Always returns false if this Element is + * not an Object or Array. + */ + bool hasChildren() const; + /** Returns either this Element's left sibling, or a non-ok Element if no left sibling * exists. */ diff --git a/src/mongo/bson/mutable/mutable_bson_test.cpp b/src/mongo/bson/mutable/mutable_bson_test.cpp index 34b1977135f..2f1dd67123e 100644 --- a/src/mongo/bson/mutable/mutable_bson_test.cpp +++ b/src/mongo/bson/mutable/mutable_bson_test.cpp @@ -990,5 +990,43 @@ namespace { ASSERT_EQUALS(end, missing); } + TEST(Element, EmptyDocHasNoChildren) { + mmb::Document doc; + ASSERT_FALSE(doc.root().hasChildren()); + } + + TEST(Element, PopulatedDocHasChildren) { + mmb::Document doc; + ASSERT_OK(doc.root().appendInt("a", 1)); + ASSERT_TRUE(doc.root().hasChildren()); + mmb::Element lc = doc.root().leftChild(); + ASSERT_FALSE(lc.hasChildren()); + } + + TEST(Element, LazyEmptyDocHasNoChildren) { + static const char inJson[] = "{}"; + mongo::BSONObj inObj = mongo::fromjson(inJson); + mmb::Document doc(inObj); + ASSERT_FALSE(doc.root().hasChildren()); + } + + TEST(Element, LazySingletonDocHasChildren) { + static const char inJson[] = "{ a : 1 }"; + mongo::BSONObj inObj = mongo::fromjson(inJson); + mmb::Document doc(inObj); + ASSERT_TRUE(doc.root().hasChildren()); + ASSERT_FALSE(doc.root().leftChild().hasChildren()); + } + + TEST(Element, LazyConstDoubletonDocHasChildren) { + static const char inJson[] = "{ a : 1, b : 2 }"; + mongo::BSONObj inObj = mongo::fromjson(inJson); + const mmb::Document doc(inObj); + ASSERT_TRUE(doc.root().hasChildren()); + ASSERT_FALSE(doc.root().leftChild().hasChildren()); + ASSERT_FALSE(doc.root().rightChild().hasChildren()); + ASSERT_FALSE(doc.root().leftChild() == doc.root().rightChild()); + } + } // namespace |