Build a subobject without recopying the contents
This commit is contained in:
22
db/jsobj.h
22
db/jsobj.h
@@ -807,13 +807,17 @@ namespace mongo {
|
||||
/**
|
||||
utility for creating a BSONObj
|
||||
*/
|
||||
class BSONObjBuilder {
|
||||
class BSONObjBuilder : boost::noncopyable {
|
||||
public:
|
||||
/** @param initsize this is just a hint as to the final size of the object */
|
||||
BSONObjBuilder(int initsize=512) : b(initsize), s_( this ) {
|
||||
BSONObjBuilder(int initsize=512) : b(buf_), buf_(initsize), offset_( 0 ), s_( this ) {
|
||||
b.skip(4); /*leave room for size field*/
|
||||
}
|
||||
|
||||
BSONObjBuilder( BufBuilder &baseBuilder ) : b( baseBuilder ), offset_( baseBuilder.len() ), s_( this ) {
|
||||
b.skip( 4 );
|
||||
}
|
||||
|
||||
/** add all the fields from the object specified to this object */
|
||||
BSONObjBuilder& appendElements(BSONObj x);
|
||||
|
||||
@@ -837,6 +841,12 @@ namespace mongo {
|
||||
b.append((void *) subObj.objdata(), subObj.objsize());
|
||||
}
|
||||
|
||||
BufBuilder &subobjStart(const char *fieldName) {
|
||||
b.append((char) Object);
|
||||
b.append(fieldName);
|
||||
return b;
|
||||
}
|
||||
|
||||
/** add a subobject as a member with type Array. Thus arr object should have "0", "1", ...
|
||||
style fields in it.
|
||||
*/
|
||||
@@ -1099,12 +1109,14 @@ namespace mongo {
|
||||
char* _done() {
|
||||
s_.endField();
|
||||
b.append((char) EOO);
|
||||
char *data = b.buf();
|
||||
*((int*)data) = b.len();
|
||||
char *data = b.buf() + offset_;
|
||||
*((int*)data) = b.len() - offset_;
|
||||
return data;
|
||||
}
|
||||
|
||||
BufBuilder b;
|
||||
BufBuilder &b;
|
||||
BufBuilder buf_;
|
||||
int offset_;
|
||||
BSONObjBuilderValueStream s_;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,16 @@
|
||||
#include "dbtests.h"
|
||||
|
||||
namespace JsobjTests {
|
||||
class BufBuilderBasic {
|
||||
public:
|
||||
void run() {
|
||||
BufBuilder b( 0 );
|
||||
b.append( "foo" );
|
||||
ASSERT_EQUALS( 4, b.len() );
|
||||
ASSERT( strcmp( "foo", b.buf() ) == 0 );
|
||||
}
|
||||
};
|
||||
|
||||
class BSONElementBasic {
|
||||
public:
|
||||
void run() {
|
||||
@@ -571,9 +581,26 @@ namespace JsobjTests {
|
||||
|
||||
} // namespace ValueStreamTests
|
||||
|
||||
class SubObjectBuilder {
|
||||
public:
|
||||
void run() {
|
||||
BSONObjBuilder b1;
|
||||
b1.append( "a", "bcd" );
|
||||
BSONObjBuilder b2( b1.subobjStart( "foo" ) );
|
||||
b2.append( "ggg", 44.0 );
|
||||
b2.done();
|
||||
b1.append( "f", 10.0 );
|
||||
BSONObj ret = b1.done();
|
||||
out() << "ret: " << ret << endl;
|
||||
ASSERT( ret.valid() );
|
||||
ASSERT( ret.woCompare( fromjson( "{a:'bcd',foo:{ggg:44},f:10}" ) ) == 0 );
|
||||
}
|
||||
};
|
||||
|
||||
class All : public UnitTest::Suite {
|
||||
public:
|
||||
All() {
|
||||
add< BufBuilderBasic >();
|
||||
add< BSONElementBasic >();
|
||||
add< BSONObjTests::Create >();
|
||||
add< BSONObjTests::WoCompareBasic >();
|
||||
@@ -626,6 +653,7 @@ namespace JsobjTests {
|
||||
add< ValueStreamTests::LabelDoubleShares >();
|
||||
add< ValueStreamTests::LabelMulti >();
|
||||
add< ValueStreamTests::Unallowed >();
|
||||
add< SubObjectBuilder >();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,8 +27,12 @@ namespace mongo {
|
||||
class BufBuilder {
|
||||
public:
|
||||
BufBuilder(int initsize = 512) : size(initsize) {
|
||||
data = (char *) malloc(size);
|
||||
assert(data);
|
||||
if ( size > 0 ) {
|
||||
data = (char *) malloc(size);
|
||||
assert(data);
|
||||
} else {
|
||||
data = 0;
|
||||
}
|
||||
l = 0;
|
||||
}
|
||||
~BufBuilder() {
|
||||
@@ -88,7 +92,7 @@ namespace mongo {
|
||||
append( (void *)str.c_str(), str.length() + 1 );
|
||||
}
|
||||
|
||||
int len() {
|
||||
int len() const {
|
||||
return l;
|
||||
}
|
||||
|
||||
@@ -99,6 +103,8 @@ namespace mongo {
|
||||
l += by;
|
||||
if ( l > size ) {
|
||||
int a = size * 2;
|
||||
if ( a == 0 )
|
||||
a = 512;
|
||||
if ( l > a )
|
||||
a = l + 16 * 1024;
|
||||
assert( a < 64 * 1024 * 1024 );
|
||||
|
||||
Reference in New Issue
Block a user