summaryrefslogtreecommitdiff
path: root/src/mongo/bson
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2015-11-13 13:28:36 -0500
committerDavid Storch <david.storch@10gen.com>2015-11-13 16:41:37 -0500
commit7a99fd808fc4e8960d2981799415617c495a0fda (patch)
tree89fbd9ea94559b27637e9d3d1a09827981622c19 /src/mongo/bson
parentbddbae79b4733dbd392215c38beccab5daa0109c (diff)
downloadmongo-7a99fd808fc4e8960d2981799415617c495a0fda.tar.gz
SERVER-20853 eliminate copies in find and getMore path
Diffstat (limited to 'src/mongo/bson')
-rw-r--r--src/mongo/bson/bsonmisc.cpp5
-rw-r--r--src/mongo/bson/bsonmisc.h5
-rw-r--r--src/mongo/bson/bsonobjbuilder.h17
-rw-r--r--src/mongo/bson/bsonobjbuilder_test.cpp17
4 files changed, 42 insertions, 2 deletions
diff --git a/src/mongo/bson/bsonmisc.cpp b/src/mongo/bson/bsonmisc.cpp
index b106121b590..28e88690b29 100644
--- a/src/mongo/bson/bsonmisc.cpp
+++ b/src/mongo/bson/bsonmisc.cpp
@@ -72,6 +72,11 @@ BSONObjBuilderValueStream::BSONObjBuilderValueStream(BSONObjBuilder* builder) {
_builder = builder;
}
+void BSONObjBuilderValueStream::reset() {
+ _fieldName = StringData();
+ _subobj.reset();
+}
+
BSONObjBuilder& BSONObjBuilderValueStream::operator<<(const BSONElement& e) {
_builder->appendAs(e, _fieldName);
_fieldName = StringData();
diff --git a/src/mongo/bson/bsonmisc.h b/src/mongo/bson/bsonmisc.h
index d1c1894190a..f32319965f1 100644
--- a/src/mongo/bson/bsonmisc.h
+++ b/src/mongo/bson/bsonmisc.h
@@ -253,6 +253,11 @@ public:
return *_builder;
}
+ /**
+ * Restores this object to its empty state.
+ */
+ void reset();
+
private:
StringData _fieldName;
BSONObjBuilder* _builder;
diff --git a/src/mongo/bson/bsonobjbuilder.h b/src/mongo/bson/bsonobjbuilder.h
index 5b744a62120..ed21c7b63e1 100644
--- a/src/mongo/bson/bsonobjbuilder.h
+++ b/src/mongo/bson/bsonobjbuilder.h
@@ -601,6 +601,20 @@ public:
BSONObjBuilder& append(StringData fieldName, const std::map<K, T>& vals);
/**
+ * Resets this BSONObjBulder to an empty state. All previously added fields are lost. If this
+ * BSONObjBuilder is using an externally provided BufBuilder, this method does not affect the
+ * bytes before the start of this object.
+ *
+ * Invalid to call if done() has already been called in order to finalize the BSONObj.
+ */
+ void resetToEmpty() {
+ invariant(!_doneCalled);
+ _s.reset();
+ // Reset the position the next write will go to right after our size reservation.
+ _b.setlen(_offset + sizeof(int));
+ }
+
+ /**
* destructive
* The returned BSONObj will free the buffer when it is finished.
* @return owned BSONObj
@@ -887,10 +901,9 @@ private:
template <class T>
inline BSONObjBuilder& BSONObjBuilder::append(StringData fieldName, const std::vector<T>& vals) {
- BSONObjBuilder arrBuilder;
+ BSONObjBuilder arrBuilder(subarrayStart(fieldName));
for (unsigned int i = 0; i < vals.size(); ++i)
arrBuilder.append(numStr(i), vals[i]);
- appendArray(fieldName, arrBuilder.done());
return *this;
}
diff --git a/src/mongo/bson/bsonobjbuilder_test.cpp b/src/mongo/bson/bsonobjbuilder_test.cpp
index d92d48d6098..fdee41b8ba1 100644
--- a/src/mongo/bson/bsonobjbuilder_test.cpp
+++ b/src/mongo/bson/bsonobjbuilder_test.cpp
@@ -303,4 +303,21 @@ TEST(BSONObjBuilderTest, ResumeBuildingWithNesting) {
<< "dd")) << "a" << BSON("c" << 3)));
}
+TEST(BSONObjBuilderTest, ResetToEmptyResultsInEmptyObj) {
+ BSONObjBuilder bob;
+ bob.append("a", 3);
+ bob.resetToEmpty();
+ ASSERT_EQ(BSONObj(), bob.obj());
+}
+
+TEST(BSONObjBuilderTest, ResetToEmptyForNestedBuilderOnlyResetsInnerObj) {
+ BSONObjBuilder bob;
+ bob.append("a", 3);
+ BSONObjBuilder innerObj(bob.subobjStart("nestedObj"));
+ innerObj.append("b", 4);
+ innerObj.resetToEmpty();
+ innerObj.done();
+ ASSERT_EQ(BSON("a" << 3 << "nestedObj" << BSONObj()), bob.obj());
+}
+
} // unnamed namespace