mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-30 09:06:21 +01:00
92 lines
3.3 KiB
C++
92 lines
3.3 KiB
C++
// embedded_builder.h
|
|
|
|
/* Copyright 2009 10gen Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
namespace mongo {
|
|
// utility class for assembling hierarchical objects
|
|
class EmbeddedBuilder {
|
|
public:
|
|
EmbeddedBuilder( BSONObjBuilder *b ) {
|
|
_builders.push_back( make_pair( "", b ) );
|
|
}
|
|
// It is assumed that the calls to prepareContext will be made with the 'name'
|
|
// parameter in lex ascending order.
|
|
void prepareContext( string &name ) {
|
|
int i = 1, n = _builders.size();
|
|
while( i < n &&
|
|
name.substr( 0, _builders[ i ].first.length() ) == _builders[ i ].first &&
|
|
( name[ _builders[i].first.length() ] == '.' || name[ _builders[i].first.length() ] == 0 )
|
|
){
|
|
name = name.substr( _builders[ i ].first.length() + 1 );
|
|
++i;
|
|
}
|
|
for( int j = n - 1; j >= i; --j ) {
|
|
popBuilder();
|
|
}
|
|
for( string next = splitDot( name ); !next.empty(); next = splitDot( name ) ) {
|
|
addBuilder( next );
|
|
}
|
|
}
|
|
void appendAs( const BSONElement &e, string name ) {
|
|
if ( e.type() == Object && e.valuesize() == 5 ) { // empty object -- this way we can add to it later
|
|
string dummyName = name + ".foo";
|
|
prepareContext( dummyName );
|
|
return;
|
|
}
|
|
prepareContext( name );
|
|
back()->appendAs( e, name.c_str() );
|
|
}
|
|
BufBuilder &subarrayStartAs( string name ) {
|
|
prepareContext( name );
|
|
return back()->subarrayStart( name.c_str() );
|
|
}
|
|
void done() {
|
|
while( ! _builderStorage.empty() )
|
|
popBuilder();
|
|
}
|
|
|
|
static string splitDot( string & str ) {
|
|
size_t pos = str.find( '.' );
|
|
if ( pos == string::npos )
|
|
return "";
|
|
string ret = str.substr( 0, pos );
|
|
str = str.substr( pos + 1 );
|
|
return ret;
|
|
}
|
|
|
|
private:
|
|
void addBuilder( const string &name ) {
|
|
shared_ptr< BSONObjBuilder > newBuilder( new BSONObjBuilder( back()->subobjStart( name.c_str() ) ) );
|
|
_builders.push_back( make_pair( name, newBuilder.get() ) );
|
|
_builderStorage.push_back( newBuilder );
|
|
}
|
|
void popBuilder() {
|
|
back()->done();
|
|
_builders.pop_back();
|
|
_builderStorage.pop_back();
|
|
}
|
|
|
|
BSONObjBuilder *back() { return _builders.back().second; }
|
|
|
|
vector< pair< string, BSONObjBuilder * > > _builders;
|
|
vector< shared_ptr< BSONObjBuilder > > _builderStorage;
|
|
|
|
};
|
|
|
|
} //namespace mongo
|