SequoiaDB
 All Classes Namespaces Files Functions Macros Pages
bsonobjbuilder.h
Go to the documentation of this file.
1 
6 /* Copyright 2009 10gen Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #pragma once
22 #if defined (SDB_ENGINE) || defined (SDB_CLIENT)
23 #include "core.hpp"
24 #include "oss.hpp"
25 #endif
26 #include <limits>
27 #include <cmath>
28 //#include "bsonobjiterator.h"
29 //#include "bson-inl.h"
30 #include "bsonmisc.h"
31 #include "bsonnoncopyable.h"
32 #include "bsonDecimal.h"
33 using namespace std;
37 namespace bson {
38 
39 #if defined(_WIN32)
40 // warning: 'this' : used in base member initializer list
41 #pragma warning( disable : 4355 )
42 #endif
43 
44  template<typename T>
46  public:
47  BSONFieldValue( const string& name , const T& t ) {
48  _name = name;
49  _t = t;
50  }
51 
52  const T& value() const { return _t; }
53  const string& name() const { return _name; }
54 
55  private:
56  string _name;
57  T _t;
58  };
59 
60  template<typename T>
61  class BSONField {
62  public:
63  BSONField( const string& name , const string& longName="" )
64  : _name(name), _longName(longName) {}
65  const string& name() const { return _name; }
66  operator string() const { return _name; }
67 
68  BSONFieldValue<T> make( const T& t ) const {
69  return BSONFieldValue<T>( _name , t );
70  }
71 
72  BSONFieldValue<BSONObj> gt( const T& t ) const
73  { return query( "$gt" , t ); }
74  BSONFieldValue<BSONObj> lt( const T& t ) const
75  { return query( "$lt" , t ); }
76 
77  BSONFieldValue<BSONObj> query( const char * q , const T& t ) const;
78 
79  BSONFieldValue<T> operator()( const T& t ) const {
80  return BSONFieldValue<T>( _name , t );
81  }
82 
83  private:
84  string _name;
85  string _longName;
86  };
87 
91 #if defined (SDB_ENGINE) || defined (SDB_CLIENT)
92  class BSONObjBuilder : bsonnoncopyable, public SDBObject {
93 #else
94  class BSONObjBuilder : bsonnoncopyable {
95 #endif
96  public:
99  BSONObjBuilder(int initsize=512) : _b(_buf), _buf(initsize + sizeof(unsigned)),
100  _offset( sizeof(unsigned) ), _s( this ) , _tracker(0) , _doneCalled(false) {
101  _b.appendNum((unsigned)0);
102  _b.skip(4); /*leave room for size field and ref-count*/
103 
104  // Reserve space for the EOO byte. This means _done() can't fail.
105  _b.reserveBytes(1);
106  }
107 
112  BSONObjBuilder( BufBuilder &baseBuilder ) : _b( baseBuilder ), _buf( 0 ),
113  _offset( baseBuilder.len() ), _s( this ) , _tracker(0) , _doneCalled(false) {
114  _b.skip( 4 );
115  // Reserve space for the EOO byte. This means _done() can't fail.
116  _b.reserveBytes(1);
117  }
118 
119  BSONObjBuilder( const BSONSizeTracker & tracker ) : _b(_buf) ,
120  _buf(tracker.getSize() + sizeof(unsigned) ), _offset( sizeof(unsigned) ),
121  _s( this ) , _tracker( (BSONSizeTracker*)(&tracker) ) , _doneCalled(false) {
122  _b.appendNum((unsigned)0); // ref-count
123  _b.skip(4);
124  // Reserve space for the EOO byte. This means _done() can't fail.
125  _b.reserveBytes(1);
126  }
127 
128  ~BSONObjBuilder() {
129  if ( !_doneCalled && _b.buf() && _buf.getSize() == 0 ) {
130  _done();
131  }
132  }
133 
135  BSONObjBuilder& appendElements(BSONObj x);
136 
137  //add all the fields(without fieldName) from the object
138  //specified to this object
139  BSONObjBuilder& appendElementsWithoutName(BSONObj x);
140 
143  BSONObjBuilder& appendElementsUnique( BSONObj x );
144 
147  assert( !e.eoo() ); // do not append eoo, that would corrupt us.
148  // the builder auto appends when done() is called.
149  _b.appendBuf((void*) e.rawdata(), e.size());
150  return *this;
151  }
152 
154  BSONObjBuilder& appendAs(const BSONElement& e,
155  const StringData& fieldName) {
156  assert( !e.eoo() ); // do not append eoo, that would corrupt us.
157  // the builder auto appends when done() is called.
158  _b.appendNum((char) e.type());
159  _b.appendStr(fieldName);
160  _b.appendBuf((void *) e.value(), e.valuesize());
161  return *this;
162  }
163 
165  BSONObjBuilder& append(const StringData& fieldName, BSONObj subObj) {
166  _b.appendNum((char) Object);
167  _b.appendStr(fieldName);
168  _b.appendBuf((void *) subObj.objdata(), subObj.objsize());
169  return *this;
170  }
171 
173  BSONObjBuilder& appendObject(const StringData& fieldName,
174  const char * objdata , int size = 0 ) {
175  assert( objdata );
176  if ( size == 0 ) {
177  size = *((int*)objdata);
178  }
179 
180  assert( size > 4 && size < 100000000 );
181 
182  _b.appendNum((char) Object);
183  _b.appendStr(fieldName);
184  _b.appendBuf((void*)objdata, size );
185  return *this;
186  }
187 
199  BufBuilder &subobjStart(const StringData& fieldName) {
200  _b.appendNum((char) Object);
201  _b.appendStr(fieldName);
202  return _b;
203  }
204 
208  BSONObjBuilder& appendArray(const StringData& fieldName,
209  const BSONObj &subObj) {
210  _b.appendNum((char) Array);
211  _b.appendStr(fieldName);
212  _b.appendBuf((void *) subObj.objdata(), subObj.objsize());
213  return *this;
214  }
215  BSONObjBuilder& append(const StringData& fieldName, BSONArray arr) {
216  return appendArray(fieldName, arr);
217  }
218 
221  BufBuilder &subarrayStart(const StringData& fieldName) {
222  _b.appendNum((char) Array);
223  _b.appendStr(fieldName);
224  return _b;
225  }
226 
228  BSONObjBuilder& appendBool(const StringData& fieldName, int val) {
229  _b.appendNum((char) Bool);
230  _b.appendStr(fieldName);
231  _b.appendNum((char) (val?1:0));
232  return *this;
233  }
234 
236  BSONObjBuilder& append(const StringData& fieldName, bool val) {
237  _b.appendNum((char) Bool);
238  _b.appendStr(fieldName);
239  _b.appendNum((char) (val?1:0));
240  return *this;
241  }
242 
244  BSONObjBuilder& append(const StringData& fieldName, int n) {
245  _b.appendNum((char) NumberInt);
246  _b.appendStr(fieldName);
247  _b.appendNum(n);
248  return *this;
249  }
250 
252  BSONObjBuilder& append(const StringData& fieldName, unsigned n) {
253  return append(fieldName, (int) n);
254  }
255 
257  BSONObjBuilder& append(const StringData& fieldName, long long n) {
258  _b.appendNum((char) NumberLong);
259  _b.appendStr(fieldName);
260  _b.appendNum(n);
261  return *this;
262  }
263 
266  BSONObjBuilder& appendIntOrLL( const StringData& fieldName ,
267  long long n ) {
268  long long x = n;
269  x = x > 0 ? -x : x ;
270  if ( x > -( (numeric_limits<int>::max)() / 2 ) ) // extra () to avoid max macro on windows
271  append( fieldName , (int)n );
272  else
273  append( fieldName , n );
274  return *this;
275  }
276 
281  BSONObjBuilder& appendNumber( const StringData& fieldName , int n ) {
282  return append( fieldName , n );
283  }
284 
285  BSONObjBuilder& appendNumber( const StringData& fieldName , double d ) {
286  return append( fieldName , d );
287  }
288 
289  BSONObjBuilder& appendNumber( const StringData& fieldName , size_t n ) {
290  static size_t maxInt = (size_t)pow( 2.0 , 30.0 );
291 
292  if ( n < maxInt )
293  append( fieldName , (int)n );
294  else
295  append( fieldName , (long long)n );
296  return *this;
297  }
298 
299  BSONObjBuilder& appendNumber( const StringData& fieldName ,
300  long long l ) {
301  static long long maxInt = (int)pow( 2.0 , 30.0 );
302  static long long maxDouble = (long long)pow( 2.0 , 40.0 );
303  long long x = l > 0 ? -l : l;
304  if ( x > -maxInt )
305  append( fieldName , (int)l );
306  else if ( x > -maxDouble )
307  append( fieldName , (double)l );
308  else
309  append( fieldName , l );
310  return *this;
311  }
312 
314  BSONObjBuilder& append(const StringData& fieldName, double n) {
315  _b.appendNum((char) NumberDouble);
316  _b.appendStr(fieldName);
317  _b.appendNum(n);
318  return *this;
319  }
320 
321  BSONObjBuilder& append( const StringData& fieldName,
322  const bsonDecimal& decimal )
323  {
324  int i = 0 ;
325  int size = 0 ;
326  short weight = 0 ;
327  int typemod = 0 ;
328  short scale = 0 ;
329  int ndigit = 0 ;
330  const short *digits = NULL ;
331 
332  weight = decimal.getWeight() ;
333  typemod = decimal.getTypemod() ;
334  scale = decimal.getStorageScale() ;
335  ndigit = decimal.getNdigit() ;
336  digits = decimal.getDigits() ;
337  size = decimal.getSize() ;
338 
339  //define in common_decimal.h __decimal
340  _b.appendNum( (char) NumberDecimal ) ;
341  _b.appendStr( fieldName ) ;
342  _b.appendNum( size ) ; // size
343  _b.appendNum( typemod ) ; // typemod
344  _b.appendNum( scale ) ; // sign + dscale
345  _b.appendNum( weight ) ; // weight
346 
347  for ( i = 0 ; i < ndigit ; i++ )
348  {
349  _b.appendNum( digits[i] ) ;
350  }
351 
352  return *this;
353  }
354 
355  bool appendDecimal( const StringData& fieldName,
356  const StringData& strDecimal,
357  int precision, int scale ) ;
358 
359  bool appendDecimal( const StringData& fieldName,
360  const StringData& strDecimal ) ;
361 
365  bool appendAsNumber( const StringData& fieldName , const string& data );
366 
371  BSONObjBuilder& appendOID(const StringData& fieldName, OID *oid = 0 ,
372  bool generateIfBlank = false ) {
373  _b.appendNum((char) jstOID);
374  _b.appendStr(fieldName);
375  if ( oid )
376  _b.appendBuf( (void *) oid, 12 );
377  else {
378  OID tmp;
379  if ( generateIfBlank )
380  tmp.init();
381  else
382  tmp.clear();
383  _b.appendBuf( (void *) &tmp, 12 );
384  }
385  return *this;
386  }
387 
393  BSONObjBuilder& append( const StringData& fieldName, OID oid ) {
394  _b.appendNum((char) jstOID);
395  _b.appendStr(fieldName);
396  _b.appendBuf( (void *) &oid, 12 );
397  return *this;
398  }
399 
405  return append("_id", OID::gen());
406  }
407 
412  BSONObjBuilder& appendTimeT(const StringData& fieldName, time_t dt) {
413  _b.appendNum((char) Date);
414  _b.appendStr(fieldName);
415  _b.appendNum(static_cast<unsigned long long>(dt) * 1000);
416  return *this;
417  }
422  BSONObjBuilder& appendDate(const StringData& fieldName, Date_t dt) {
423  /* easy to pass a time_t to this and get a bad result.
424  thus this warning. */
425 #if defined(_DEBUG) && defined(MONGO_EXPOSE_MACROS)
426  if( dt > 0 && dt <= 0xffffffff ) {
427  static int n;
428  if( n++ == 0 )
429  log() << "DEV WARNING appendDate() called with a tiny "
430  "(but nonzero) date" << endl;
431  }
432 #endif
433  _b.appendNum((char) Date);
434  _b.appendStr(fieldName);
435  _b.appendNum(dt);
436  return *this;
437  }
438  BSONObjBuilder& append(const StringData& fieldName, Date_t dt) {
439  return appendDate(fieldName, dt);
440  }
441 
446  BSONObjBuilder& appendRegex(const StringData& fieldName,
447  const StringData& regex, const StringData& options = "") {
448  _b.appendNum((char) RegEx);
449  _b.appendStr(fieldName);
450  _b.appendStr(regex);
451  _b.appendStr(options);
452  return *this;
453  }
454 
455  BSONObjBuilder& appendCode(const StringData& fieldName,
456  const StringData& code) {
457  _b.appendNum((char) Code);
458  _b.appendStr(fieldName);
459  _b.appendNum((int) code.size()+1);
460  _b.appendStr(code);
461  return *this;
462  }
463 
466  BSONObjBuilder& append(const StringData& fieldName, const char *str,
467  int sz) {
468  _b.appendNum((char) String);
469  _b.appendStr(fieldName);
470  _b.appendNum((int)sz);
471  _b.appendBuf(str, sz);
472  return *this;
473  }
474 
477  BSONObjBuilder& appendStrWithNoTerminating(const StringData& fieldName, const char *str,
478  int sz)
479  {
480  _b.appendNum((char) String);
481  _b.appendStr(fieldName);
482  _b.appendNum((int)sz + 1);
483  _b.appendBuf(str, sz);
484  char t = '\0';
485  _b.appendBuf(&t, 1);
486  return *this;
487  }
488 
490  BSONObjBuilder& append(const StringData& fieldName, const char *str) {
491  return append(fieldName, str, (int) strlen(str)+1);
492  }
494  BSONObjBuilder& append(const StringData& fieldName, const string& str) {
495  return append(fieldName, str.c_str(), (int) str.size()+1);
496  }
497 
498  BSONObjBuilder& appendSymbol(const StringData& fieldName,
499  const StringData& symbol) {
500  _b.appendNum((char) Symbol);
501  _b.appendStr(fieldName);
502  _b.appendNum((int) symbol.size()+1);
503  _b.appendStr(symbol);
504  return *this;
505  }
506 
508  BSONObjBuilder& appendNull( const StringData& fieldName ) {
509  _b.appendNum( (char) jstNULL );
510  _b.appendStr( fieldName );
511  return *this;
512  }
513 
514  // Append an element that is less than all other keys.
515  BSONObjBuilder& appendMinKey( const StringData& fieldName ) {
516  _b.appendNum( (char) MinKey );
517  _b.appendStr( fieldName );
518  return *this;
519  }
520 
522  BSONObjBuilder& appendUndefined( const StringData& fieldName ) {
523  _b.appendNum( (char) Undefined );
524  _b.appendStr( fieldName );
525  return *this;
526  }
527 
528  // Append an element that is greater than all other keys.
529  BSONObjBuilder& appendMaxKey( const StringData& fieldName ) {
530  _b.appendNum( (char) MaxKey );
531  _b.appendStr( fieldName );
532  return *this;
533  }
534 
535  // Append a Timestamp field -- will be updated to next OpTime on db
536  // insert.
537  BSONObjBuilder& appendTimestamp( const StringData& fieldName ) {
538  _b.appendNum( (char) Timestamp );
539  _b.appendStr( fieldName );
540  _b.appendNum( (long long) 0 );
541  return *this;
542  }
543 
554  BSONObjBuilder& appendTimestamp( const StringData& fieldName , long long val ) {
555  _b.appendNum( (char) Timestamp );
556  _b.appendStr( fieldName );
557  _b.appendNum( val );
558  return *this;
559  }
560 
571  BSONObjBuilder& appendTimestamp( const StringData& fieldName ,
572  long long time , unsigned int inc );
573 
574  /*
575  Append an element of the deprecated DBRef type.
576  @deprecated
577  */
578  BSONObjBuilder& appendDBRef( const StringData& fieldName,
579  const StringData& ns, const OID &oid ) {
580  _b.appendNum( (char) DBRef );
581  _b.appendStr( fieldName );
582  _b.appendNum( (int) ns.size() + 1 );
583  _b.appendStr( ns );
584  _b.appendBuf( (void *) &oid, 12 );
585  return *this;
586  }
587 
596  BSONObjBuilder& appendBinData( const StringData& fieldName, int len,
597  BinDataType type, const char *data ) {
598  if ( type == ByteArrayDeprecated ) {
599  return appendBinDataArrayDeprecated( fieldName.data(), data, len );
600  }
601  else {
602  _b.appendNum( (char) BinData );
603  _b.appendStr( fieldName );
604  _b.appendNum( len );
605  _b.appendNum( (char) type );
606  _b.appendBuf( (void *) data, len );
607  return *this;
608  }
609  }
610  BSONObjBuilder& appendBinData( const StringData& fieldName, int len,
611  BinDataType type, const unsigned char *data ) {
612  return appendBinData(fieldName, len, type, (const char *) data);
613  }
614 
621  BSONObjBuilder& appendBinDataArrayDeprecated( const char * fieldName ,
622  const char * data , int len ) {
623  _b.appendNum( (char) BinData );
624  _b.appendStr( fieldName );
625  _b.appendNum( len + 4 );
626  _b.appendNum( (char)0x2 );
627  _b.appendNum( len );
628  _b.appendBuf( (void *) data, len );
629  return *this;
630  }
631 
635  BSONObjBuilder& appendCodeWScope( const StringData& fieldName,
636  const StringData& code, const BSONObj &scope ) {
637  _b.appendNum( (char) CodeWScope );
638  _b.appendStr( fieldName );
639  _b.appendNum( ( int )( 4 + 4 + code.size() + 1 + scope.objsize() ));
640  _b.appendNum( ( int ) code.size() + 1 );
641  _b.appendStr( code );
642  _b.appendBuf( ( void * )scope.objdata(), scope.objsize() );
643  return *this;
644  }
645 
646  /*void appendUndefined( const StringData& fieldName ) {
647  _b.appendNum( (char) Undefined );
648  _b.appendStr( fieldName );
649  }*/
650 
651  /* helper function -- see Query::where() for primary way to do this. */
652  void appendWhere( const StringData& code, const BSONObj &scope ) {
653  appendCodeWScope( "$where" , code , scope );
654  }
655 
660  void appendMinForType( const StringData& fieldName , int type );
661  void appendMaxForType( const StringData& fieldName , int type );
662 
664  template < class T >
665  BSONObjBuilder& append( const StringData& fieldName,
666  const vector< T >& vals );
667 
668  template < class T >
669  BSONObjBuilder& append( const StringData& fieldName,
670  const list< T >& vals );
671 
673  template < class T >
674  BSONObjBuilder& append( const StringData& fieldName, const set< T >& vals );
675 
682  bool own = owned();
683  massert( 10335 , "builder does not own memory", own );
684  doneFast();
685  BSONObj::Holder* h = (BSONObj::Holder*)_b.buf();
686  decouple(); // sets _b.buf() to NULL
687  return BSONObj(h);
688  }
689 
696  return BSONObj(_done());
697  }
698 
699  // Like 'done' above, but does not construct a BSONObj
700  // to return to the caller.
701  void doneFast() {
702  (void)_done();
703  }
704 
711  BSONObj temp(_done());
712  _b.setlen(_b.len()-1); //next append should overwrite the EOO
713  _b.reserveBytes(1); // Rereserve room for the real EOO
714  _doneCalled = false;
715  return temp;
716  }
717 
718  /* assume ownership of the buffer
719  you must then free it (with free()) */
720  char* decouple(int& l) {
721  char *x = _done();
722  assert( x );
723  l = _b.len();
724  _b.decouple();
725  return x;
726  }
727  void decouple() {
728  _b.decouple(); // post done() call version. be sure jsobj frees...
729  }
730 
731  void appendKeys( const BSONObj& keyPattern , const BSONObj& values );
732 
733  static string numStr( int i ) {
734  if (i>=0 && i<100)
735  return numStrs[i];
736  StringBuilder o;
737  o << i;
738  return o.str();
739  }
740 
742  BSONObjBuilderValueStream &operator<<(const char * name ) {
743  _s.endField( name );
744  return _s;
745  }
746 
748  BSONObjBuilder& operator<<( GENOIDLabeler ) { return genOID(); }
749 
750  // prevent implicit string conversions which would allow bad things
751  // like BSON( BSON( "foo" << 1 ) << 2 )
753  ForceExplicitString( const string &str ) : str_( str ) {}
754  string str_;
755  };
756 
759  { return operator<<( name.str_.c_str() ); }
760 
761  Labeler operator<<( const Labeler::Label &l ) {
762  massert( 10336 , "No subobject started", _s.subobjStarted() );
763  return _s << l;
764  }
765 
766  template<typename T>
767  BSONObjBuilderValueStream& operator<<( const BSONField<T>& f ) {
768  _s.endField( f.name().c_str() );
769  return _s;
770  }
771 
772  template<typename T>
773  BSONObjBuilder& operator<<( const BSONFieldValue<T>& v ) {
774  append( v.name().c_str() , v.value() );
775  return *this;
776  }
777 
778 
781  bool owned() const { return &_b == &_buf; }
782 
783  BSONObjIterator iterator() const ;
784 
785  bool hasField( const StringData& name ) const ;
786 
787  int len() const { return _b.len(); }
788 
789  BufBuilder& bb() { return _b; }
790 
791  private:
792  char* _done() {
793  if ( _doneCalled )
794  return _b.buf() + _offset;
795 
796  _doneCalled = true;
797  _s.endField();
798 
799  _b.claimReservedBytes(1); // Prevents adding EOO from failing.
800  _b.appendNum((char) EOO);
801  char *data = _b.buf() + _offset;
802  int size = _b.len() - _offset;
803  *((int*)data) = size;
804  if ( _tracker )
805  _tracker->got( size );
806  return data;
807  }
808 
809  BufBuilder &_b;
810  BufBuilder _buf;
811  int _offset;
812  BSONObjBuilderValueStream _s;
813  BSONSizeTracker * _tracker;
814  bool _doneCalled;
815 
816  static const string numStrs[100]; // cache of 0 to 99 inclusive
817  };
818 
819 #if defined (SDB_ENGINE) || defined (SDB_CLIENT)
820  class BSONArrayBuilder : bsonnoncopyable, public SDBObject {
821 #else
822  class BSONArrayBuilder : bsonnoncopyable {
823 #endif
824  public:
825  BSONArrayBuilder() : _i(0), _b() {}
826  BSONArrayBuilder( BufBuilder &_b ) : _i(0), _b(_b) {}
827  BSONArrayBuilder( int initialSize ) : _i(0), _b(initialSize) {}
828 
829  template <typename T>
830  BSONArrayBuilder& append(const T& x) {
831  _b.append(num(), x);
832  return *this;
833  }
834 
835  BSONArrayBuilder& appendTimestamp(unsigned long long val) {
836  _b.appendTimestamp(num(),val);
837  return *this;
838  }
839 
840  BSONArrayBuilder& append(const BSONElement& e) {
841  _b.appendAs(e, num());
842  return *this;
843  }
844 
845  template <typename T>
846  BSONArrayBuilder& operator<<(const T& x) {
847  return append(x);
848  }
849 
850  void appendNull() {
851  _b.appendNull(num());
852  }
853 
858  BSONArray arr() { return BSONArray(_b.obj()); }
859 
860  BSONObj done() { return _b.done(); }
861 
862  void doneFast() { _b.doneFast(); }
863 
864  template <typename T>
865  BSONArrayBuilder& append(const StringData& name, const T& x) {
866  fill( name );
867  append( x );
868  return *this;
869  }
870 
871  // These two just use next position
872  BufBuilder &subobjStart() { return _b.subobjStart( num() ); }
873  BufBuilder &subarrayStart() { return _b.subarrayStart( num() ); }
874 
875  // These fill missing entries up to pos. if pos is < next pos is ignored
876  BufBuilder &subobjStart(int pos) {
877  fill(pos);
878  return _b.subobjStart( num() );
879  }
880  BufBuilder &subarrayStart(int pos) {
881  fill(pos);
882  return _b.subarrayStart( num() );
883  }
884 
885  // These should only be used where you really need interface compatability with BSONObjBuilder
886  // Currently they are only used by update.cpp and it should probably stay that way
887  BufBuilder &subobjStart( const StringData& name ) {
888  fill( name );
889  return _b.subobjStart( num() );
890  }
891 
892  BufBuilder &subarrayStart( const char *name ) {
893  fill( name );
894  return _b.subarrayStart( num() );
895  }
896 
897  void appendArray( const StringData& name, BSONObj subObj ) {
898  fill( name );
899  _b.appendArray( num(), subObj );
900  }
901 
902  void appendAs( const BSONElement &e, const char *name) {
903  fill( name );
904  append( e );
905  }
906 
907  int len() const { return _b.len(); }
908 
909  private:
910  void fill( const StringData& name ) {
911  char *r;
912  long int n = strtol( name.data(), &r, 10 );
913  if ( *r )
914  uasserted( 13048, (string)"can't append to array using string"
915  " field name [" + name.data() + "]" );
916  fill(n);
917  }
918 
919  void fill (int upTo){
920  while( _i < upTo )
921  append( nullElt() );
922  }
923 
924  static BSONElement nullElt() {
925  static BSONObj n = nullObj();
926  return n.firstElement();
927  }
928 
929  static BSONObj nullObj() {
930  BSONObjBuilder _b;
931  _b.appendNull( "" );
932  return _b.obj();
933  }
934 
935  string num() { return _b.numStr(_i++); }
936  int _i;
937  BSONObjBuilder _b;
938  };
939 
940  template < class T >
941  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName,
942  const vector< T >& vals ) {
943  BSONObjBuilder arrBuilder;
944  for ( unsigned int i = 0; i < vals.size(); ++i )
945  arrBuilder.append( numStr( i ), vals[ i ] );
946  appendArray( fieldName, arrBuilder.done() );
947  return *this;
948  }
949 
950  template < class L >
951  inline BSONObjBuilder& _appendIt( BSONObjBuilder& _this, const StringData& fieldName, const L& vals ) {
952  BSONObjBuilder arrBuilder;
953  int n = 0;
954  for( typename L::const_iterator i = vals.begin(); i != vals.end(); i++ )
955  arrBuilder.append( BSONObjBuilder::numStr(n++), *i );
956  _this.appendArray( fieldName, arrBuilder.done() );
957  return _this;
958  }
959 
960  template < class T >
961  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName, const list< T >& vals ) {
962  return _appendIt< list< T > >( *this, fieldName, vals );
963  }
964 
965  template < class T >
966  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName, const set< T >& vals ) {
967  return _appendIt< set< T > >( *this, fieldName, vals );
968  }
969 
970 
971  // $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT 6));
972  inline BSONObj OR(const BSONObj& a, const BSONObj& b)
973  { return BSON( "$or" << BSON_ARRAY(a << b) ); }
974  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c)
975  { return BSON( "$or" << BSON_ARRAY(a << b << c) ); }
976  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
977  const BSONObj& d)
978  { return BSON( "$or" << BSON_ARRAY(a << b << c << d) ); }
979  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
980  const BSONObj& d, const BSONObj& e)
981  { return BSON( "$or" << BSON_ARRAY(a << b << c << d << e) ); }
982  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
983  const BSONObj& d, const BSONObj& e, const BSONObj& f)
984  { return BSON( "$or" << BSON_ARRAY(a << b << c << d << e << f) ); }
985 
986 }