diff --git a/db/jsobj.h b/db/jsobj.h index f3399655c63..32e69f448d8 100644 --- a/db/jsobj.h +++ b/db/jsobj.h @@ -841,6 +841,8 @@ namespace mongo { b.append((void *) subObj.objdata(), subObj.objsize()); } + /** add header for a new subobject and return bufbuilder for writing to + the subobject's body */ BufBuilder &subobjStart(const char *fieldName) { b.append((char) Object); b.append(fieldName); @@ -856,6 +858,14 @@ namespace mongo { b.append((void *) subObj.objdata(), subObj.objsize()); } + /** add header for a new subarray and return bufbuilder for writing to + the subarray's body */ + BufBuilder &subarrayStart(const char *fieldName) { + b.append((char) Array); + b.append(fieldName); + return b; + } + /** Append a boolean element */ void appendBool(const char *fieldName, int val) { b.append((char) Bool); @@ -1051,6 +1061,7 @@ namespace mongo { /** The returned BSONObj will free the buffer when it is finished. */ BSONObj obj() { + massert( "builder does not own memory", owned() ); int l; return BSONObj(decouple(l), true); } @@ -1098,6 +1109,10 @@ namespace mongo { return s_ << l; } + bool owned() const { + return &b == &buf_; + } + private: // Append the provided arr object as an array. void marshalArray( const char *fieldName, const BSONObj &arr ) { diff --git a/db/json.cpp b/db/json.cpp index b32d3c69844..4aa50349ed2 100644 --- a/db/json.cpp +++ b/db/json.cpp @@ -32,14 +32,33 @@ namespace mongo { const char *fieldName() { return fieldNames.back().c_str(); } - void push() { + bool empty() const { + return builders.size() == 0; + } + void init() { boost::shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); builders.push_back( b ); fieldNames.push_back( "" ); indexes.push_back( 0 ); } + void pushObject( const char *fieldName ) { + boost::shared_ptr< BSONObjBuilder > b( new BSONObjBuilder( builders.back()->subobjStart( fieldName ) ) ); + builders.push_back( b ); + fieldNames.push_back( "" ); + indexes.push_back( 0 ); + } + void pushArray( const char *fieldName ) { + boost::shared_ptr< BSONObjBuilder > b( new BSONObjBuilder( builders.back()->subarrayStart( fieldName ) ) ); + builders.push_back( b ); + fieldNames.push_back( "" ); + indexes.push_back( 0 ); + } BSONObj pop() { - BSONObj ret = back()->obj(); + BSONObj ret; + if ( back()->owned() ) + ret = back()->obj(); + else + ret = back()->done(); builders.pop_back(); fieldNames.pop_back(); indexes.pop_back(); @@ -70,7 +89,10 @@ namespace mongo { struct objectStart { objectStart( ObjectBuilder &_b ) : b( _b ) {} void operator() ( const char &c ) const { - b.push(); + if ( b.empty() ) + b.init(); + else + b.pushObject( b.fieldName() ); } ObjectBuilder &b; }; @@ -78,7 +100,7 @@ namespace mongo { struct arrayStart { arrayStart( ObjectBuilder &_b ) : b( _b ) {} void operator() ( const char &c ) const { - b.push(); + b.pushArray( b.fieldName() ); b.nameFromIndex(); } ObjectBuilder &b; @@ -229,8 +251,7 @@ namespace mongo { struct subobjectEnd { subobjectEnd( ObjectBuilder &_b ) : b( _b ) {} void operator() ( const char *start, const char *end ) const { - BSONObj o = b.pop(); - b.back()->append( b.fieldName(), o ); + b.pop(); } ObjectBuilder &b; }; @@ -238,8 +259,7 @@ namespace mongo { struct arrayEnd { arrayEnd( ObjectBuilder &_b ) : b( _b ) {} void operator() ( const char *start, const char *end ) const { - BSONObj o = b.pop(); - b.back()->appendArray( b.fieldName(), o ); + b.pop(); } ObjectBuilder &b; };