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)
23 #include "utilPooledObject.hpp"
24 #elif defined( SDB_CLIENT )
25 #include "core.hpp"
26 #include "oss.hpp"
27 #endif
28 
29 #include <limits>
30 #include <cmath>
31 //#include "bsonobjiterator.h"
32 //#include "bson-inl.h"
33 #include "bsonmisc.h"
34 #include "bsonnoncopyable.h"
35 #include "bsonDecimal.h"
36 using namespace std;
40 namespace bson {
41 
42 #if defined(_WIN32)
43 // warning: 'this' : used in base member initializer list
44 #pragma warning( disable : 4355 )
45 #endif
46 
47  template<typename T>
49  public:
50  BSONFieldValue( const string& name , const T& t ) {
51  _name = name;
52  _t = t;
53  }
54 
55  const T& value() const { return _t; }
56  const string& name() const { return _name; }
57 
58  private:
59  string _name;
60  T _t;
61  };
62 
63  template<typename T>
64  class BSONField {
65  public:
66  BSONField( const string& name , const string& longName="" )
67  : _name(name), _longName(longName) {}
68  const string& name() const { return _name; }
69  operator string() const { return _name; }
70 
71  BSONFieldValue<T> make( const T& t ) const {
72  return BSONFieldValue<T>( _name , t );
73  }
74 
75  BSONFieldValue<BSONObj> gt( const T& t ) const
76  { return query( "$gt" , t ); }
77  BSONFieldValue<BSONObj> lt( const T& t ) const
78  { return query( "$lt" , t ); }
79 
80  BSONFieldValue<BSONObj> query( const char * q , const T& t ) const;
81 
82  BSONFieldValue<T> operator()( const T& t ) const {
83  return BSONFieldValue<T>( _name , t );
84  }
85 
86  private:
87  string _name;
88  string _longName;
89  };
90 
94 #if defined (SDB_ENGINE)
95  class BSONObjBuilder : bsonnoncopyable, public engine::utilPooledObject{
96 #elif defined( SDB_CLIENT )
97  class BSONObjBuilder : bsonnoncopyable, public SDBObject {
98 #else
99  class BSONObjBuilder : bsonnoncopyable {
100 #endif
101  public:
104  BSONObjBuilder(int initsize=512) : _b(_buf),
105  _buf(initsize + sizeof(unsigned), BSONObjMaxInternalSize, BSON_INFO_STR ),
106  _offset( sizeof(unsigned) ), _s( this ) , _tracker(0) , _doneCalled(false) {
107  _orgReserve = _b.getReserveBytes() ;
108  _b.skipDeplay(4) ; /* reference count */
109  _b.skipDeplay(4); /*leave room for size field and ref-count*/
110 
111  // Reserve space for the EOO byte. This means _done() can't fail.
112  _b.reserveBytes(1,true);
113  }
114 
119  BSONObjBuilder( BufBuilder &baseBuilder ) : _b( baseBuilder ),
120  _buf( 0, BSONObjMaxInternalSize, BSON_INFO_STR ),
121  _offset( baseBuilder.len() ), _s( this ) , _tracker(0) , _doneCalled(false) {
122  _orgReserve = _b.getReserveBytes() ;
123  _b.skipDeplay( 4 );
124  // Reserve space for the EOO byte. This means _done() can't fail.
125  _b.reserveBytes(1,true);
126  }
127 
128  BSONObjBuilder( const BSONSizeTracker & tracker ) : _b(_buf) ,
129  _buf(tracker.getSize() + sizeof(unsigned), BSONObjMaxInternalSize, BSON_INFO_STR ),
130  _offset( sizeof(unsigned) ),
131  _s( this ) , _tracker( (BSONSizeTracker*)(&tracker) ) , _doneCalled(false) {
132  _orgReserve = _b.getReserveBytes() ;
133  _b.skipDeplay(4); /* reference count */
134  _b.skipDeplay(4);
135  // Reserve space for the EOO byte. This means _done() can't fail.
136  _b.reserveBytes(1,true);
137  }
138 
139  ~BSONObjBuilder() {
140  if ( !_doneCalled && _b.buf() && _buf.getSize() == 0 ) {
141  try {
142  _done();
143  } catch ( ... ) {
144  _b.setlen( _offset ) ;
145  _b.setReserveBytes( _orgReserve ) ;
146  }
147  }
148  }
149 
150  void reset() {
151  _b.setlen( _offset ) ;
152  _b.setReserveBytes( _orgReserve ) ;
153  _s.reset() ;
154  if ( _tracker )
155  _tracker->reset() ;
156  _doneCalled = false ;
157  _b.skipDeplay( 4 ) ;
158  _b.reserveBytes(1,true) ;
159  }
160 
161  bool isEmpty() const {
162  if ( owned() ) {
163  return _b.len() <= (int)(sizeof(unsigned) + 4) ? true : false ;
164  }
165  return _b.len() <= 4 ? true : false ;
166  }
167 
169  BSONObjBuilder& appendElements(BSONObj x);
170 
171  //add all the fields(without fieldName) from the object
172  //specified to this object
173  BSONObjBuilder& appendElementsWithoutName(BSONObj x);
174 
177  BSONObjBuilder& appendElementsUnique( BSONObj x );
178 
181  assert( !e.eoo() ); // do not append eoo, that would corrupt us.
182  // the builder auto appends when done() is called.
183  _b.appendBuf((void*) e.rawdata(), e.size());
184  return *this;
185  }
186 
188  BSONObjBuilder& appendAs(const BSONElement& e,
189  const StringData& fieldName) {
190  assert( !e.eoo() ); // do not append eoo, that would corrupt us.
191  // the builder auto appends when done() is called.
192  _b.appendNum((char) e.type());
193  _b.appendStr(fieldName);
194  _b.appendBuf((void *) e.value(), e.valuesize());
195  return *this;
196  }
197 
199  BSONObjBuilder& append(const StringData& fieldName, BSONObj subObj) {
200  _b.appendNum((char) Object);
201  _b.appendStr(fieldName);
202  _b.appendBuf((void *) subObj.objdata(), subObj.objsize());
203  return *this;
204  }
205 
207  BSONObjBuilder& appendObject(const StringData& fieldName,
208  const char * objdata , int size = 0 ) {
209  assert( objdata );
210  if ( size == 0 ) {
211  size = *((int*)objdata);
212  }
213 
214  assert( size > 4 && size < 100000000 );
215 
216  _b.appendNum((char) Object);
217  _b.appendStr(fieldName);
218  _b.appendBuf((void*)objdata, size );
219  return *this;
220  }
221 
233  BufBuilder &subobjStart(const StringData& fieldName) {
234  _b.appendNum((char) Object);
235  _b.appendStr(fieldName);
236  return _b;
237  }
238 
242  BSONObjBuilder& appendArray(const StringData& fieldName,
243  const BSONObj &subObj) {
244  _b.appendNum((char) Array);
245  _b.appendStr(fieldName);
246  _b.appendBuf((void *) subObj.objdata(), subObj.objsize());
247  return *this;
248  }
249  BSONObjBuilder& append(const StringData& fieldName, BSONArray arr) {
250  return appendArray(fieldName, arr);
251  }
252 
255  BufBuilder &subarrayStart(const StringData& fieldName) {
256  _b.appendNum((char) Array);
257  _b.appendStr(fieldName);
258  return _b;
259  }
260 
262  BSONObjBuilder& appendBool(const StringData& fieldName, int val) {
263  _b.appendNum((char) Bool);
264  _b.appendStr(fieldName);
265  _b.appendNum((char) (val?1:0));
266  return *this;
267  }
268 
270  BSONObjBuilder& append(const StringData& fieldName, bool val) {
271  _b.appendNum((char) Bool);
272  _b.appendStr(fieldName);
273  _b.appendNum((char) (val?1:0));
274  return *this;
275  }
276 
278  BSONObjBuilder& append(const StringData& fieldName, int n) {
279  _b.appendNum((char) NumberInt);
280  _b.appendStr(fieldName);
281  _b.appendNum(n);
282  return *this;
283  }
284 
286  BSONObjBuilder& append(const StringData& fieldName, unsigned n) {
287  return append(fieldName, (int) n);
288  }
289 
291  BSONObjBuilder& append(const StringData& fieldName, long long n) {
292  _b.appendNum((char) NumberLong);
293  _b.appendStr(fieldName);
294  _b.appendNum(n);
295  return *this;
296  }
297 
300  BSONObjBuilder& appendIntOrLL( const StringData& fieldName ,
301  long long n ) {
302  long long x = n;
303  x = x > 0 ? -x : x ;
304  if ( x > -( (numeric_limits<int>::max)() / 2 ) ) // extra () to avoid max macro on windows
305  append( fieldName , (int)n );
306  else
307  append( fieldName , n );
308  return *this;
309  }
310 
315  BSONObjBuilder& appendNumber( const StringData& fieldName , int n ) {
316  return append( fieldName , n );
317  }
318 
319  BSONObjBuilder& appendNumber( const StringData& fieldName , double d ) {
320  return append( fieldName , d );
321  }
322 
323  BSONObjBuilder& appendNumber( const StringData& fieldName , size_t n ) {
324  static size_t maxInt = (size_t)pow( 2.0 , 30.0 );
325 
326  if ( n < maxInt )
327  append( fieldName , (int)n );
328  else
329  append( fieldName , (long long)n );
330  return *this;
331  }
332 
333  BSONObjBuilder& appendNumber( const StringData& fieldName ,
334  long long l ) {
335  static long long maxInt = (int)pow( 2.0 , 30.0 );
336  static long long maxDouble = (long long)pow( 2.0 , 40.0 );
337  long long x = l > 0 ? -l : l;
338  if ( x > -maxInt )
339  append( fieldName , (int)l );
340  else if ( x > -maxDouble )
341  append( fieldName , (double)l );
342  else
343  append( fieldName , l );
344  return *this;
345  }
346 
348  BSONObjBuilder& append(const StringData& fieldName, double n) {
349  _b.appendNum((char) NumberDouble);
350  _b.appendStr(fieldName);
351  _b.appendNum(n);
352  return *this;
353  }
354 
355  BSONObjBuilder& append( const StringData& fieldName,
356  const bsonDecimal& decimal )
357  {
358  int i = 0 ;
359  int size = 0 ;
360  short weight = 0 ;
361  int typemod = 0 ;
362  short scale = 0 ;
363  int ndigit = 0 ;
364  const short *digits = NULL ;
365 
366  weight = decimal.getWeight() ;
367  typemod = decimal.getTypemod() ;
368  scale = decimal.getStorageScale() ;
369  ndigit = decimal.getNdigit() ;
370  digits = decimal.getDigits() ;
371  size = decimal.getSize() ;
372 
373  //define in common_decimal.h __sdb_decimal
374  _b.appendNum( (char) NumberDecimal ) ;
375  _b.appendStr( fieldName ) ;
376  _b.appendNum( size ) ; // size
377  _b.appendNum( typemod ) ; // typemod
378  _b.appendNum( scale ) ; // sign + dscale
379  _b.appendNum( weight ) ; // weight
380 
381  for ( i = 0 ; i < ndigit ; i++ )
382  {
383  _b.appendNum( digits[i] ) ;
384  }
385 
386  return *this;
387  }
388 
389  bool appendDecimal( const StringData& fieldName,
390  const StringData& strDecimal,
391  int precision, int scale ) ;
392 
393  bool appendDecimal( const StringData& fieldName,
394  const StringData& strDecimal ) ;
395 
399  bool appendAsNumber( const StringData& fieldName , const StringData& data );
400 
405  BSONObjBuilder& appendOID(const StringData& fieldName, OID *oid = 0 ,
406  bool generateIfBlank = false ) {
407  _b.appendNum((char) jstOID);
408  _b.appendStr(fieldName);
409  if ( oid )
410  _b.appendBuf( (void *) oid, 12 );
411  else {
412  OID tmp;
413  if ( generateIfBlank )
414  tmp.init();
415  else
416  tmp.clear();
417  _b.appendBuf( (void *) &tmp, 12 );
418  }
419  return *this;
420  }
421 
427  BSONObjBuilder& append( const StringData& fieldName, OID oid ) {
428  _b.appendNum((char) jstOID);
429  _b.appendStr(fieldName);
430  _b.appendBuf( (void *) &oid, 12 );
431  return *this;
432  }
433 
439  return append("_id", OID::gen());
440  }
441 
446  BSONObjBuilder& appendTimeT(const StringData& fieldName, time_t dt) {
447  _b.appendNum((char) Date);
448  _b.appendStr(fieldName);
449  _b.appendNum(static_cast<unsigned long long>(dt) * 1000);
450  return *this;
451  }
456  BSONObjBuilder& appendDate(const StringData& fieldName, Date_t dt) {
457  /* easy to pass a time_t to this and get a bad result.
458  thus this warning. */
459 #if defined(_DEBUG) && defined(MONGO_EXPOSE_MACROS)
460  if( dt > 0 && dt <= 0xffffffff ) {
461  static int n;
462  if( n++ == 0 )
463  log() << "DEV WARNING appendDate() called with a tiny "
464  "(but nonzero) date" << endl;
465  }
466 #endif
467  _b.appendNum((char) Date);
468  _b.appendStr(fieldName);
469  _b.appendNum(dt);
470  return *this;
471  }
472  BSONObjBuilder& append(const StringData& fieldName, Date_t dt) {
473  return appendDate(fieldName, dt);
474  }
475 
480  BSONObjBuilder& appendRegex(const StringData& fieldName,
481  const StringData& regex, const StringData& options = "") {
482  _b.appendNum((char) RegEx);
483  _b.appendStr(fieldName);
484  _b.appendStr(regex);
485  _b.appendStr(options);
486  return *this;
487  }
488 
489  BSONObjBuilder& appendCode(const StringData& fieldName,
490  const StringData& code) {
491  _b.appendNum((char) Code);
492  _b.appendStr(fieldName);
493  _b.appendNum((int) code.size()+1);
494  _b.appendStr(code);
495  return *this;
496  }
497 
500  BSONObjBuilder& append(const StringData& fieldName, const char *str,
501  int sz) {
502  _b.appendNum((char) String);
503  _b.appendStr(fieldName);
504  _b.appendNum((int)sz);
505  _b.appendBuf(str, sz);
506  return *this;
507  }
508 
511  BSONObjBuilder& appendStrWithNoTerminating(const StringData& fieldName, const char *str,
512  int sz)
513  {
514  _b.appendNum((char) String);
515  _b.appendStr(fieldName);
516  _b.appendNum((int)sz + 1);
517  _b.appendBuf(str, sz);
518  char t = '\0';
519  _b.appendBuf(&t, 1);
520  return *this;
521  }
522 
524  BSONObjBuilder& append(const StringData& fieldName, const char *str) {
525  return append(fieldName, str, (int) strlen(str)+1);
526  }
528  BSONObjBuilder& append(const StringData& fieldName, const string& str) {
529  return append(fieldName, str.c_str(), (int) str.size()+1);
530  }
532  BSONObjBuilder& append(const StringData& fieldName, const StringData& str) {
533  return append(fieldName, str.data(), (int) str.size()+1);
534  }
535 
536  BSONObjBuilder& appendSymbol(const StringData& fieldName,
537  const StringData& symbol) {
538  _b.appendNum((char) Symbol);
539  _b.appendStr(fieldName);
540  _b.appendNum((int) symbol.size()+1);
541  _b.appendStr(symbol);
542  return *this;
543  }
544 
546  BSONObjBuilder& appendNull( const StringData& fieldName ) {
547  _b.appendNum( (char) jstNULL );
548  _b.appendStr( fieldName );
549  return *this;
550  }
551 
552  // Append an element that is less than all other keys.
553  BSONObjBuilder& appendMinKey( const StringData& fieldName ) {
554  _b.appendNum( (char) MinKey );
555  _b.appendStr( fieldName );
556  return *this;
557  }
558 
560  BSONObjBuilder& appendUndefined( const StringData& fieldName ) {
561  _b.appendNum( (char) Undefined );
562  _b.appendStr( fieldName );
563  return *this;
564  }
565 
566  // Append an element that is greater than all other keys.
567  BSONObjBuilder& appendMaxKey( const StringData& fieldName ) {
568  _b.appendNum( (char) MaxKey );
569  _b.appendStr( fieldName );
570  return *this;
571  }
572 
573  // Append a Timestamp field -- will be updated to next OpTime on db
574  // insert.
575  BSONObjBuilder& appendTimestamp( const StringData& fieldName ) {
576  _b.appendNum( (char) Timestamp );
577  _b.appendStr( fieldName );
578  _b.appendNum( (long long) 0 );
579  return *this;
580  }
581 
592  BSONObjBuilder& appendTimestamp( const StringData& fieldName , long long val ) {
593  _b.appendNum( (char) Timestamp );
594  _b.appendStr( fieldName );
595  _b.appendNum( val );
596  return *this;
597  }
598 
609  BSONObjBuilder& appendTimestamp( const StringData& fieldName ,
610  long long time , unsigned int inc );
611 
612  /*
613  Append an element of the deprecated DBRef type.
614  @deprecated
615  */
616  BSONObjBuilder& appendDBRef( const StringData& fieldName,
617  const StringData& ns, const OID &oid ) {
618  _b.appendNum( (char) DBRef );
619  _b.appendStr( fieldName );
620  _b.appendNum( (int) ns.size() + 1 );
621  _b.appendStr( ns );
622  _b.appendBuf( (void *) &oid, 12 );
623  return *this;
624  }
625 
634  BSONObjBuilder& appendBinData( const StringData& fieldName, int len,
635  BinDataType type, const char *data ) {
636  if ( type == ByteArrayDeprecated ) {
637  return appendBinDataArrayDeprecated( fieldName.data(), data, len );
638  }
639  else {
640  _b.appendNum( (char) BinData );
641  _b.appendStr( fieldName );
642  _b.appendNum( len );
643  _b.appendNum( (char) type );
644  _b.appendBuf( (void *) data, len );
645  return *this;
646  }
647  }
648  BSONObjBuilder& appendBinData( const StringData& fieldName, int len,
649  BinDataType type, const unsigned char *data ) {
650  return appendBinData(fieldName, len, type, (const char *) data);
651  }
652 
659  BSONObjBuilder& appendBinDataArrayDeprecated( const char * fieldName ,
660  const char * data , int len ) {
661  _b.appendNum( (char) BinData );
662  _b.appendStr( fieldName );
663  _b.appendNum( len + 4 );
664  _b.appendNum( (char)0x2 );
665  _b.appendNum( len );
666  _b.appendBuf( (void *) data, len );
667  return *this;
668  }
669 
673  BSONObjBuilder& appendCodeWScope( const StringData& fieldName,
674  const StringData& code, const BSONObj &scope ) {
675  _b.appendNum( (char) CodeWScope );
676  _b.appendStr( fieldName );
677  _b.appendNum( ( int )( 4 + 4 + code.size() + 1 + scope.objsize() ));
678  _b.appendNum( ( int ) code.size() + 1 );
679  _b.appendStr( code );
680  _b.appendBuf( ( void * )scope.objdata(), scope.objsize() );
681  return *this;
682  }
683 
684  /*void appendUndefined( const StringData& fieldName ) {
685  _b.appendNum( (char) Undefined );
686  _b.appendStr( fieldName );
687  }*/
688 
689  /* helper function -- see Query::where() for primary way to do this. */
690  void appendWhere( const StringData& code, const BSONObj &scope ) {
691  appendCodeWScope( "$where" , code , scope );
692  }
693 
698  void appendMinForType( const StringData& fieldName , int type );
699  void appendMaxForType( const StringData& fieldName , int type );
700 
702  template < class T >
703  BSONObjBuilder& append( const StringData& fieldName,
704  const vector< T >& vals );
705 
706  template < class T >
707  BSONObjBuilder& append( const StringData& fieldName,
708  const list< T >& vals );
709 
711  template < class T >
712  BSONObjBuilder& append( const StringData& fieldName, const set< T >& vals );
713 
720  bool own = owned();
721  massert( 10335 , "builder does not own memory", own );
722  doneFast();
723  bson_intrusive_ptr<BSONObj::Holder,BufBuilder::myAllocator> h ;
724  h = (BSONObj::Holder*)_b.buf();
725  decouple(); // sets _b.buf() to NULL
726  return BSONObj(h);
727  }
728 
735  return BSONObj(_done());
736  }
737 
738  // Like 'done' above, but does not construct a BSONObj
739  // to return to the caller.
740  void doneFast() {
741  (void)_done();
742  }
743 
750  BSONObj temp(_done());
751  _b.setlen(_b.len()-1); //next append should overwrite the EOO
752  _b.reserveBytes(1); // Rereserve room for the real EOO
753  _doneCalled = false;
754  return temp;
755  }
756 
757  /* assume ownership of the buffer
758  you must then free it (with free()) */
759  char* decouple(int& l) {
760  char *x = _done();
761  assert( x );
762  l = _b.len();
763  _b.decouple();
764  return x;
765  }
766  void decouple() {
767  _b.decouple(); // post done() call version. be sure jsobj frees...
768  }
769 
770  void appendKeys( const BSONObj& keyPattern , const BSONObj& values );
771 
772  static string numStr( int i ) {
773  if (i>=0 && i<100)
774  return numStrs[i];
775  StringBuilder o;
776  o << i;
777  return o.str();
778  }
779 
781  BSONObjBuilderValueStream &operator<<(const char * name ) {
782  _s.endField( name );
783  return _s;
784  }
785 
787  BSONObjBuilder& operator<<( GENOIDLabeler ) { return genOID(); }
788 
789  // prevent implicit string conversions which would allow bad things
790  // like BSON( BSON( "foo" << 1 ) << 2 )
792  ForceExplicitString( const string &str ) : str_( str ) {}
793  string str_;
794  };
795 
798  { return operator<<( name.str_.c_str() ); }
799 
800  Labeler operator<<( const Labeler::Label &l ) {
801  massert( 10336 , "No subobject started", _s.subobjStarted() );
802  return _s << l;
803  }
804 
805  template<typename T>
806  BSONObjBuilderValueStream& operator<<( const BSONField<T>& f ) {
807  _s.endField( f.name().c_str() );
808  return _s;
809  }
810 
811  template<typename T>
812  BSONObjBuilder& operator<<( const BSONFieldValue<T>& v ) {
813  append( v.name().c_str() , v.value() );
814  return *this;
815  }
816 
817 
820  bool owned() const { return &_b == &_buf; }
821 
822  BSONObjIterator iterator() const ;
823 
824  bool hasField( const StringData& name ) const ;
825 
826  int len() const { return _b.len(); }
827 
828  BufBuilder& bb() { return _b; }
829 
830  private:
831  char* _done() {
832  if ( _doneCalled )
833  return _b.buf() + _offset;
834 
835  _doneCalled = true;
836  _s.endField();
837 
838  _b.claimReservedBytes(1); // Prevents adding EOO from failing.
839  _b.appendNum((char) EOO);
840  if ( owned() ) {
841  *(unsigned*)_b.buf() = 0 ; /* reference count */
842  }
843  char *data = _b.buf() + _offset;
844  int size = _b.len() - _offset;
845  *((int*)data) = size; /* object size */
846  if ( _tracker )
847  _tracker->got( size );
848  return data;
849  }
850 
851  BufBuilder &_b;
852  BufBuilder _buf;
853  int _offset;
854  int _orgReserve ;
855  BSONObjBuilderValueStream _s;
856  BSONSizeTracker * _tracker;
857  bool _doneCalled;
858 
859  static const string numStrs[100]; // cache of 0 to 99 inclusive
860  };
861 
862 #if defined (SDB_ENGINE)
863  class BSONArrayBuilder : bsonnoncopyable, public engine::utilPooledObject {
864 #elif defined( SDB_CLIENT )
865  class BSONArrayBuilder : bsonnoncopyable, public SDBObject {
866 #else
867  class BSONArrayBuilder : bsonnoncopyable {
868 #endif
869  public:
870  BSONArrayBuilder() : _i(0), _b() {}
871  BSONArrayBuilder( BufBuilder &_b ) : _i(0), _b(_b) {}
872  BSONArrayBuilder( int initialSize ) : _i(0), _b(initialSize) {}
873 
874  template <typename T>
875  BSONArrayBuilder& append(const T& x) {
876  _b.append(num(), x);
877  return *this;
878  }
879 
880  BSONArrayBuilder& appendTimestamp(unsigned long long val) {
881  _b.appendTimestamp(num(),val);
882  return *this;
883  }
884 
885  BSONArrayBuilder& append(const BSONElement& e) {
886  _b.appendAs(e, num());
887  return *this;
888  }
889 
890  template <typename T>
891  BSONArrayBuilder& operator<<(const T& x) {
892  return append(x);
893  }
894 
895  void appendNull() {
896  _b.appendNull(num());
897  }
898 
903  BSONArray arr() { return BSONArray(_b.obj()); }
904 
905  BSONObj done() { return _b.done(); }
906 
907  void doneFast() { _b.doneFast(); }
908 
909  template <typename T>
910  BSONArrayBuilder& append(const StringData& name, const T& x) {
911  fill( name );
912  append( x );
913  return *this;
914  }
915 
916  // These two just use next position
917  BufBuilder &subobjStart() { return _b.subobjStart( num() ); }
918  BufBuilder &subarrayStart() { return _b.subarrayStart( num() ); }
919 
920  // These fill missing entries up to pos. if pos is < next pos is ignored
921  BufBuilder &subobjStart(int pos) {
922  fill(pos);
923  return _b.subobjStart( num() );
924  }
925  BufBuilder &subarrayStart(int pos) {
926  fill(pos);
927  return _b.subarrayStart( num() );
928  }
929 
930  // These should only be used where you really need interface compatability with BSONObjBuilder
931  // Currently they are only used by update.cpp and it should probably stay that way
932  BufBuilder &subobjStart( const StringData& name ) {
933  fill( name );
934  return _b.subobjStart( num() );
935  }
936 
937  BufBuilder &subarrayStart( const char *name ) {
938  fill( name );
939  return _b.subarrayStart( num() );
940  }
941 
942  void appendArray( const StringData& name, BSONObj subObj ) {
943  fill( name );
944  _b.appendArray( num(), subObj );
945  }
946 
947  void appendAs( const BSONElement &e, const char *name) {
948  fill( name );
949  append( e );
950  }
951 
952  int len() const { return _b.len(); }
953 
954  private:
955  void fill( const StringData& name ) {
956  char *r;
957  long int n = strtol( name.data(), &r, 10 );
958  if ( *r )
959  uasserted( 13048, (string)"can't append to array using string"
960  " field name [" + name.data() + "]" );
961  fill(n);
962  }
963 
964  void fill (int upTo){
965  while( _i < upTo )
966  append( nullElt() );
967  }
968 
969  static BSONElement nullElt() {
970  static BSONObj n = nullObj();
971  return n.firstElement();
972  }
973 
974  static BSONObj nullObj() {
975  BSONObjBuilder _b;
976  _b.appendNull( "" );
977  return _b.obj();
978  }
979 
980  string num() { return _b.numStr(_i++); }
981  int _i;
982  BSONObjBuilder _b;
983  };
984 
985  template < class T >
986  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName,
987  const vector< T >& vals ) {
988  BSONObjBuilder arrBuilder;
989  for ( unsigned int i = 0; i < vals.size(); ++i )
990  arrBuilder.append( numStr( i ), vals[ i ] );
991  appendArray( fieldName, arrBuilder.done() );
992  return *this;
993  }
994 
995  template < class L >
996  inline BSONObjBuilder& _appendIt( BSONObjBuilder& _this, const StringData& fieldName, const L& vals ) {
997  BSONObjBuilder arrBuilder;
998  int n = 0;
999  for( typename L::const_iterator i = vals.begin(); i != vals.end(); i++ )
1000  arrBuilder.append( BSONObjBuilder::numStr(n++), *i );
1001  _this.appendArray( fieldName, arrBuilder.done() );
1002  return _this;
1003  }
1004 
1005  template < class T >
1006  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName, const list< T >& vals ) {
1007  return _appendIt< list< T > >( *this, fieldName, vals );
1008  }
1009 
1010  template < class T >
1011  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName, const set< T >& vals ) {
1012  return _appendIt< set< T > >( *this, fieldName, vals );
1013  }
1014 
1015 
1016  // $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT 6));
1017  inline BSONObj OR(const BSONObj& a, const BSONObj& b)
1018  { return BSON( "$or" << BSON_ARRAY(a << b) ); }
1019  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c)
1020  { return BSON( "$or" << BSON_ARRAY(a << b << c) ); }
1021  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
1022  const BSONObj& d)
1023  { return BSON( "$or" << BSON_ARRAY(a << b << c << d) ); }
1024  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
1025  const BSONObj& d, const BSONObj& e)
1026  { return BSON( "$or" << BSON_ARRAY(a << b << c << d << e) ); }
1027  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
1028  const BSONObj& d, const BSONObj& e, const BSONObj& f)
1029  { return BSON( "$or" << BSON_ARRAY(a << b << c << d << e << f) ); }
1030 
1031 }