Build a subobject without recopying the contents

This commit is contained in:
Aaron
2009-03-25 18:24:22 -04:00
parent 2506307e43
commit e5a43008fd
3 changed files with 54 additions and 8 deletions

View File

@@ -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_;
};

View File

@@ -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 >();
}
};

View File

@@ -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 );