summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/bson/mutable/const_element-inl.h4
-rw-r--r--src/mongo/bson/mutable/const_element.h1
-rw-r--r--src/mongo/bson/mutable/document.cpp9
-rw-r--r--src/mongo/bson/mutable/element.h5
-rw-r--r--src/mongo/bson/mutable/mutable_bson_test.cpp38
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