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 
91  /*
92  BSONObjBuilderOption define
93  */
95  {
96  public:
98  : isClientReadable( false ),
99  isAbbrevMode( false )
100  {
101  }
102 
103  BSONObjBuilderOption( bool isClientReadable,
104  bool isAbbrevMode )
105  : isClientReadable( isClientReadable ),
106  isAbbrevMode( isAbbrevMode )
107  {
108  }
109 
111 
112  void reset()
113  {
114  isClientReadable = false ;
115  isAbbrevMode = false ;
116  }
117 
118  bool isEnabled() const
119  {
120  return isClientReadable || isAbbrevMode ;
121  }
122 
123  public:
124  bool isClientReadable ;
125  bool isAbbrevMode ;
126  } ;
127 
131 #if defined (SDB_ENGINE)
132  class BSONObjBuilder : bsonnoncopyable, public engine::utilPooledObject{
133 #elif defined( SDB_CLIENT )
134  class BSONObjBuilder : bsonnoncopyable, public SDBObject {
135 #else
136  class BSONObjBuilder : bsonnoncopyable {
137 #endif
138  public:
141  BSONObjBuilder(int initsize=512) : _b(_buf),
142  _buf(initsize + sizeof(unsigned), BSONObjMaxInternalSize, BSON_INFO_STR ),
143  _offset( sizeof(unsigned) ), _s( this ) , _tracker(0) , _doneCalled(false) {
144  _orgReserve = _b.getReserveBytes() ;
145  _b.skipDeplay(4) ; /* reference count */
146  _b.skipDeplay(4); /*leave room for size field and ref-count*/
147 
148  // Reserve space for the EOO byte. This means _done() can't fail.
149  _b.reserveBytes(1,true);
150  }
151 
156  BSONObjBuilder( BufBuilder &baseBuilder ) : _b( baseBuilder ),
157  _buf( 0, BSONObjMaxInternalSize, BSON_INFO_STR ),
158  _offset( baseBuilder.len() ), _s( this ) , _tracker(0) , _doneCalled(false) {
159  _orgReserve = _b.getReserveBytes() ;
160  _b.skipDeplay( 4 );
161  // Reserve space for the EOO byte. This means _done() can't fail.
162  _b.reserveBytes(1,true);
163  }
164 
165  BSONObjBuilder( const BSONSizeTracker & tracker ) : _b(_buf) ,
166  _buf(tracker.getSize() + sizeof(unsigned), BSONObjMaxInternalSize, BSON_INFO_STR ),
167  _offset( sizeof(unsigned) ),
168  _s( this ) , _tracker( (BSONSizeTracker*)(&tracker) ) , _doneCalled(false) {
169  _orgReserve = _b.getReserveBytes() ;
170  _b.skipDeplay(4); /* reference count */
171  _b.skipDeplay(4);
172  // Reserve space for the EOO byte. This means _done() can't fail.
173  _b.reserveBytes(1,true);
174  }
175 
176  ~BSONObjBuilder() {
177  // if done is not been called, and builder is not owned,
178  // which means we are in a sub-object or sub-array builder
179  // need call done to finish the BSON for outer builder
180  if ( !_doneCalled && !owned() ) {
181  try {
182  _done();
183  } catch ( ... ) {
184  _b.setlen( _offset ) ;
185  _b.setReserveBytes( _orgReserve ) ;
186  }
187  }
188  }
189 
190  void reset() {
191  _b.setlen( _offset ) ;
192  _b.setReserveBytes( _orgReserve ) ;
193  _s.reset() ;
194  if ( _tracker )
195  _tracker->reset() ;
196  _doneCalled = false ;
197  _b.skipDeplay( 4 ) ;
198  _b.reserveBytes(1,true) ;
199  }
200 
208  void abandon() {
209  _doneCalled = true;
210  }
211 
212  bool isEmpty() const {
213  if ( owned() ) {
214  return ( _b.len() - _offset ) <= (int)(sizeof(unsigned) + 4) ? true : false ;
215  }
216  return ( _b.len() - _offset ) <= 4 ? true : false ;
217  }
218 
220  BSONObjBuilder& appendElements(BSONObj x);
221 
222  //add all the fields(without fieldName) from the object
223  //specified to this object
224  BSONObjBuilder& appendElementsWithoutName(BSONObj x);
225 
228  BSONObjBuilder& appendElementsUnique( BSONObj x );
229 
232  assert( !e.eoo() ); // do not append eoo, that would corrupt us.
233  // the builder auto appends when done() is called.
234  _b.appendBuf((void*) e.rawdata(), e.size());
235  return *this;
236  }
237 
239  BSONObjBuilder& appendAs(const BSONElement& e,
240  const StringData& fieldName) {
241  assert( !e.eoo() ); // do not append eoo, that would corrupt us.
242  // the builder auto appends when done() is called.
243  _b.appendNum((char) e.type());
244  _b.appendStr(fieldName);
245  _b.appendBuf((void *) e.value(), e.valuesize());
246  return *this;
247  }
248 
250  BSONObjBuilder& append(const StringData& fieldName, BSONObj subObj) {
251  _b.appendNum((char) Object);
252  _b.appendStr(fieldName);
253  _b.appendBuf((void *) subObj.objdata(), subObj.objsize());
254  return *this;
255  }
256 
258  BSONObjBuilder &appendEx( const BSONElement &element,
259  const BSONObjBuilderOption &option )
260  {
261  return appendEx( element.fieldName(), element, option ) ;
262  }
263 
265  BSONObjBuilder &appendEx( const StringData &fieldName,
266  const BSONElement &element,
267  const BSONObjBuilderOption &option ) ;
268 
270  BSONObjBuilder &appendEx( const BSONObj &object,
271  const BSONObjBuilderOption &option ) ;
272 
274  BSONObjBuilder &appendEx( const StringData &fieldName,
275  const BSONObj &subObject,
276  const BSONObjBuilderOption &option )
277  {
278  if ( option.isEnabled() )
279  {
280  BSONObjBuilder subBuilder( subobjStart( fieldName ) ) ;
281  subBuilder.appendEx( subObject, option ) ;
282  subBuilder.doneFast() ;
283  }
284  else
285  {
286  append( fieldName, subObject ) ;
287  }
288  return (*this) ;
289  }
290 
292  BSONObjBuilder& appendObject(const StringData& fieldName,
293  const char * objdata , int size = 0 ) {
294  assert( objdata );
295  if ( size == 0 ) {
296  size = *((int*)objdata);
297  }
298 
299  assert( size > 4 && size < 100000000 );
300 
301  _b.appendNum((char) Object);
302  _b.appendStr(fieldName);
303  _b.appendBuf((void*)objdata, size );
304  return *this;
305  }
306 
318  BufBuilder &subobjStart(const StringData& fieldName) {
319  _b.appendNum((char) Object);
320  _b.appendStr(fieldName);
321  return _b;
322  }
323 
327  BSONObjBuilder& appendArray(const StringData& fieldName,
328  const BSONObj &subObj) {
329  _b.appendNum((char) Array);
330  _b.appendStr(fieldName);
331  _b.appendBuf((void *) subObj.objdata(), subObj.objsize());
332  return *this;
333  }
334  BSONObjBuilder& append(const StringData& fieldName, BSONArray arr) {
335  return appendArray(fieldName, arr);
336  }
337 
340  BufBuilder &subarrayStart(const StringData& fieldName) {
341  _b.appendNum((char) Array);
342  _b.appendStr(fieldName);
343  return _b;
344  }
345 
347  BSONObjBuilder& appendBool(const StringData& fieldName, int val) {
348  _b.appendNum((char) Bool);
349  _b.appendStr(fieldName);
350  _b.appendNum((char) (val?1:0));
351  return *this;
352  }
353 
355  BSONObjBuilder& append(const StringData& fieldName, bool val) {
356  _b.appendNum((char) Bool);
357  _b.appendStr(fieldName);
358  _b.appendNum((char) (val?1:0));
359  return *this;
360  }
361 
363  BSONObjBuilder& append(const StringData& fieldName, int n) {
364  _b.appendNum((char) NumberInt);
365  _b.appendStr(fieldName);
366  _b.appendNum(n);
367  return *this;
368  }
369 
371  BSONObjBuilder& append(const StringData& fieldName, unsigned n) {
372  return append(fieldName, (int) n);
373  }
374 
376  BSONObjBuilder& append(const StringData& fieldName, long long n) {
377  _b.appendNum((char) NumberLong);
378  _b.appendStr(fieldName);
379  _b.appendNum(n);
380  return *this;
381  }
382 
385  BSONObjBuilder& appendIntOrLL( const StringData& fieldName ,
386  long long n ) {
387  long long x = n;
388  x = x > 0 ? -x : x ;
389  if ( x > -( (numeric_limits<int>::max)() / 2 ) ) // extra () to avoid max macro on windows
390  append( fieldName , (int)n );
391  else
392  append( fieldName , n );
393  return *this;
394  }
395 
400  BSONObjBuilder& appendNumber( const StringData& fieldName , int n ) {
401  return append( fieldName , n );
402  }
403 
404  BSONObjBuilder& appendNumber( const StringData& fieldName , double d ) {
405  return append( fieldName , d );
406  }
407 
408  BSONObjBuilder& appendNumber( const StringData& fieldName , size_t n ) {
409  static size_t maxInt = (size_t)pow( 2.0 , 30.0 );
410 
411  if ( n < maxInt )
412  append( fieldName , (int)n );
413  else
414  append( fieldName , (long long)n );
415  return *this;
416  }
417 
418  BSONObjBuilder& appendNumber( const StringData& fieldName ,
419  long long l ) {
420  static long long maxInt = (int)pow( 2.0 , 30.0 );
421  static long long maxDouble = (long long)pow( 2.0 , 40.0 );
422  long long x = l > 0 ? -l : l;
423  if ( x > -maxInt )
424  append( fieldName , (int)l );
425  else if ( x > -maxDouble )
426  append( fieldName , (double)l );
427  else
428  append( fieldName , l );
429  return *this;
430  }
431 
433  BSONObjBuilder& append(const StringData& fieldName, double n) {
434  _b.appendNum((char) NumberDouble);
435  _b.appendStr(fieldName);
436  _b.appendNum(n);
437  return *this;
438  }
439 
440  BSONObjBuilder& append( const StringData& fieldName,
441  const bsonDecimal& decimal )
442  {
443  int i = 0 ;
444  int size = 0 ;
445  short weight = 0 ;
446  int typemod = 0 ;
447  short scale = 0 ;
448  int ndigit = 0 ;
449  const short *digits = NULL ;
450 
451  weight = decimal.getWeight() ;
452  typemod = decimal.getTypemod() ;
453  scale = decimal.getStorageScale() ;
454  ndigit = decimal.getNdigit() ;
455  digits = decimal.getDigits() ;
456  size = decimal.getSize() ;
457 
458  //define in common_decimal.h __sdb_decimal
459  _b.appendNum( (char) NumberDecimal ) ;
460  _b.appendStr( fieldName ) ;
461  _b.appendNum( size ) ; // size
462  _b.appendNum( typemod ) ; // typemod
463  _b.appendNum( scale ) ; // sign + dscale
464  _b.appendNum( weight ) ; // weight
465 
466  for ( i = 0 ; i < ndigit ; i++ )
467  {
468  _b.appendNum( digits[i] ) ;
469  }
470 
471  return *this;
472  }
473 
474  bool appendDecimal( const StringData& fieldName,
475  const StringData& strDecimal,
476  int precision, int scale ) ;
477 
478  bool appendDecimal( const StringData& fieldName,
479  const StringData& strDecimal ) ;
480 
484  bool appendAsNumber( const StringData& fieldName , const StringData& data );
485 
490  BSONObjBuilder& appendOID(const StringData& fieldName, OID *oid = 0 ,
491  bool generateIfBlank = false ) {
492  _b.appendNum((char) jstOID);
493  _b.appendStr(fieldName);
494  if ( oid )
495  _b.appendBuf( (void *) oid, 12 );
496  else {
497  OID tmp;
498  if ( generateIfBlank )
499  tmp.init();
500  else
501  tmp.clear();
502  _b.appendBuf( (void *) &tmp, 12 );
503  }
504  return *this;
505  }
506 
512  BSONObjBuilder& append( const StringData& fieldName, OID oid ) {
513  _b.appendNum((char) jstOID);
514  _b.appendStr(fieldName);
515  _b.appendBuf( (void *) &oid, 12 );
516  return *this;
517  }
518 
524  return append("_id", OID::gen());
525  }
526 
531  BSONObjBuilder& appendTimeT(const StringData& fieldName, time_t dt) {
532  _b.appendNum((char) Date);
533  _b.appendStr(fieldName);
534  _b.appendNum(static_cast<unsigned long long>(dt) * 1000);
535  return *this;
536  }
541  BSONObjBuilder& appendDate(const StringData& fieldName, Date_t dt) {
542  /* easy to pass a time_t to this and get a bad result.
543  thus this warning. */
544 #if defined(_DEBUG) && defined(MONGO_EXPOSE_MACROS)
545  if( dt > 0 && dt <= 0xffffffff ) {
546  static int n;
547  if( n++ == 0 )
548  log() << "DEV WARNING appendDate() called with a tiny "
549  "(but nonzero) date" << endl;
550  }
551 #endif
552  _b.appendNum((char) Date);
553  _b.appendStr(fieldName);
554  _b.appendNum(dt);
555  return *this;
556  }
557  BSONObjBuilder& append(const StringData& fieldName, Date_t dt) {
558  return appendDate(fieldName, dt);
559  }
560 
565  BSONObjBuilder& appendRegex(const StringData& fieldName,
566  const StringData& regex, const StringData& options = "") {
567  _b.appendNum((char) RegEx);
568  _b.appendStr(fieldName);
569  _b.appendStr(regex);
570  _b.appendStr(options);
571  return *this;
572  }
573 
574  BSONObjBuilder& appendCode(const StringData& fieldName,
575  const StringData& code) {
576  _b.appendNum((char) Code);
577  _b.appendStr(fieldName);
578  _b.appendNum((int) code.size()+1);
579  _b.appendStr(code);
580  return *this;
581  }
582 
585  BSONObjBuilder& append(const StringData& fieldName, const char *str,
586  int sz) {
587  _b.appendNum((char) String);
588  _b.appendStr(fieldName);
589  _b.appendNum((int)sz);
590  _b.appendBuf(str, sz);
591  return *this;
592  }
593 
596  BSONObjBuilder& appendStrWithNoTerminating(const StringData& fieldName, const char *str,
597  int sz)
598  {
599  _b.appendNum((char) String);
600  _b.appendStr(fieldName);
601  _b.appendNum((int)sz + 1);
602  _b.appendBuf(str, sz);
603  char t = '\0';
604  _b.appendBuf(&t, 1);
605  return *this;
606  }
607 
609  BSONObjBuilder& append(const StringData& fieldName, const char *str) {
610  return append(fieldName, str, (int) strlen(str)+1);
611  }
613  BSONObjBuilder& append(const StringData& fieldName, const string& str) {
614  return append(fieldName, str.c_str(), (int) str.size()+1);
615  }
617  BSONObjBuilder& append(const StringData& fieldName, const StringData& str) {
618  return append(fieldName, str.data(), (int) str.size()+1);
619  }
620 
621  BSONObjBuilder& appendSymbol(const StringData& fieldName,
622  const StringData& symbol) {
623  _b.appendNum((char) Symbol);
624  _b.appendStr(fieldName);
625  _b.appendNum((int) symbol.size()+1);
626  _b.appendStr(symbol);
627  return *this;
628  }
629 
631  BSONObjBuilder& appendNull( const StringData& fieldName ) {
632  _b.appendNum( (char) jstNULL );
633  _b.appendStr( fieldName );
634  return *this;
635  }
636 
637  // Append an element that is less than all other keys.
638  BSONObjBuilder& appendMinKey( const StringData& fieldName ) {
639  _b.appendNum( (char) MinKey );
640  _b.appendStr( fieldName );
641  return *this;
642  }
643 
645  BSONObjBuilder& appendUndefined( const StringData& fieldName ) {
646  _b.appendNum( (char) Undefined );
647  _b.appendStr( fieldName );
648  return *this;
649  }
650 
651  // Append an element that is greater than all other keys.
652  BSONObjBuilder& appendMaxKey( const StringData& fieldName ) {
653  _b.appendNum( (char) MaxKey );
654  _b.appendStr( fieldName );
655  return *this;
656  }
657 
658  // Append a Timestamp field -- will be updated to next OpTime on db
659  // insert.
660  BSONObjBuilder& appendTimestamp( const StringData& fieldName ) {
661  _b.appendNum( (char) Timestamp );
662  _b.appendStr( fieldName );
663  _b.appendNum( (long long) 0 );
664  return *this;
665  }
666 
677  BSONObjBuilder& appendTimestamp( const StringData& fieldName , long long val ) {
678  _b.appendNum( (char) Timestamp );
679  _b.appendStr( fieldName );
680  _b.appendNum( val );
681  return *this;
682  }
683 
694  BSONObjBuilder& appendTimestamp( const StringData& fieldName ,
695  long long time , unsigned int inc );
696 
697  /*
698  Append an element of the deprecated DBRef type.
699  @deprecated
700  */
701  BSONObjBuilder& appendDBRef( const StringData& fieldName,
702  const StringData& ns, const OID &oid ) {
703  _b.appendNum( (char) DBRef );
704  _b.appendStr( fieldName );
705  _b.appendNum( (int) ns.size() + 1 );
706  _b.appendStr( ns );
707  _b.appendBuf( (void *) &oid, 12 );
708  return *this;
709  }
710 
719  BSONObjBuilder& appendBinData( const StringData& fieldName, int len,
720  BinDataType type, const char *data ) {
721  if ( type == ByteArrayDeprecated ) {
722  return appendBinDataArrayDeprecated( fieldName.data(), data, len );
723  }
724  else {
725  _b.appendNum( (char) BinData );
726  _b.appendStr( fieldName );
727  _b.appendNum( len );
728  _b.appendNum( (char) type );
729  _b.appendBuf( (void *) data, len );
730  return *this;
731  }
732  }
733  BSONObjBuilder& appendBinData( const StringData& fieldName, int len,
734  BinDataType type, const unsigned char *data ) {
735  return appendBinData(fieldName, len, type, (const char *) data);
736  }
737 
744  BSONObjBuilder& appendBinDataArrayDeprecated( const char * fieldName ,
745  const char * data , int len ) {
746  _b.appendNum( (char) BinData );
747  _b.appendStr( fieldName );
748  _b.appendNum( len + 4 );
749  _b.appendNum( (char)0x2 );
750  _b.appendNum( len );
751  _b.appendBuf( (void *) data, len );
752  return *this;
753  }
754 
758  BSONObjBuilder& appendCodeWScope( const StringData& fieldName,
759  const StringData& code, const BSONObj &scope ) {
760  _b.appendNum( (char) CodeWScope );
761  _b.appendStr( fieldName );
762  _b.appendNum( ( int )( 4 + 4 + code.size() + 1 + scope.objsize() ));
763  _b.appendNum( ( int ) code.size() + 1 );
764  _b.appendStr( code );
765  _b.appendBuf( ( void * )scope.objdata(), scope.objsize() );
766  return *this;
767  }
768 
769  /*void appendUndefined( const StringData& fieldName ) {
770  _b.appendNum( (char) Undefined );
771  _b.appendStr( fieldName );
772  }*/
773 
774  /* helper function -- see Query::where() for primary way to do this. */
775  void appendWhere( const StringData& code, const BSONObj &scope ) {
776  appendCodeWScope( "$where" , code , scope );
777  }
778 
783  void appendMinForType( const StringData& fieldName , int type );
784  void appendMaxForType( const StringData& fieldName , int type );
785 
787  template < class T >
788  BSONObjBuilder& append( const StringData& fieldName,
789  const vector< T >& vals );
790 
791  template < class T >
792  BSONObjBuilder& append( const StringData& fieldName,
793  const list< T >& vals );
794 
796  template < class T >
797  BSONObjBuilder& append( const StringData& fieldName, const set< T >& vals );
798 
805  bool own = owned();
806  massert( 10335 , "builder does not own memory", own );
807  doneFast();
808  bson_intrusive_ptr<BSONObj::Holder,BufBuilder::myAllocator> h ;
809  h = (BSONObj::Holder*)_b.buf();
810  decouple(); // sets _b.buf() to NULL
811  return BSONObj(h);
812  }
813 
820  return BSONObj(_done());
821  }
822 
823  // Like 'done' above, but does not construct a BSONObj
824  // to return to the caller.
825  void doneFast() {
826  (void)_done();
827  }
828 
835  BSONObj temp(_done());
836  _b.setlen(_b.len()-1); //next append should overwrite the EOO
837  _b.reserveBytes(1); // Rereserve room for the real EOO
838  _doneCalled = false;
839  return temp;
840  }
841 
842  /* assume ownership of the buffer
843  you must then free it (with free()) */
844  char* decouple(int& l) {
845  char *x = _done();
846  assert( x );
847  l = _b.len();
848  _b.decouple();
849  return x;
850  }
851  void decouple() {
852  _b.decouple(); // post done() call version. be sure jsobj frees...
853  }
854 
855  void appendKeys( const BSONObj& keyPattern , const BSONObj& values );
856 
857  static string numStr( int i ) {
858  if (i>=0 && i<100)
859  return numStrs[i];
860  StringBuilder o;
861  o << i;
862  return o.str();
863  }
864 
866  BSONObjBuilderValueStream &operator<<(const char * name ) {
867  _s.endField( name );
868  return _s;
869  }
870 
872  BSONObjBuilder& operator<<( GENOIDLabeler ) { return genOID(); }
873 
874  // prevent implicit string conversions which would allow bad things
875  // like BSON( BSON( "foo" << 1 ) << 2 )
877  ForceExplicitString( const string &str ) : str_( str ) {}
878  string str_;
879  };
880 
883  { return operator<<( name.str_.c_str() ); }
884 
885  Labeler operator<<( const Labeler::Label &l ) {
886  massert( 10336 , "No subobject started", _s.subobjStarted() );
887  return _s << l;
888  }
889 
890  template<typename T>
891  BSONObjBuilderValueStream& operator<<( const BSONField<T>& f ) {
892  _s.endField( f.name().c_str() );
893  return _s;
894  }
895 
896  template<typename T>
897  BSONObjBuilder& operator<<( const BSONFieldValue<T>& v ) {
898  append( v.name().c_str() , v.value() );
899  return *this;
900  }
901 
902 
905  bool owned() const { return &_b == &_buf; }
906 
907  BSONObjIterator iterator() const ;
908 
909  bool hasField( const StringData& name ) const ;
910 
911  int len() const { return _b.len(); }
912 
913  BufBuilder& bb() { return _b; }
914 
915  private:
916  char* _done() {
917  if ( _doneCalled )
918  return _b.buf() + _offset;
919 
920  _doneCalled = true;
921  _s.endField();
922 
923  _b.claimReservedBytes(1); // Prevents adding EOO from failing.
924  _b.appendNum((char) EOO);
925  if ( owned() ) {
926  *(unsigned*)_b.buf() = 0 ; /* reference count */
927  }
928  char *data = _b.buf() + _offset;
929  int size = _b.len() - _offset;
930  *((int*)data) = size; /* object size */
931  if ( _tracker )
932  _tracker->got( size );
933  return data;
934  }
935 
936  StringData _genAbbrevStr( StackBufBuilder &builder,
937  const StringData &value ) ;
938 
939  BufBuilder &_b;
940  BufBuilder _buf;
941  int _offset;
942  int _orgReserve ;
943  BSONObjBuilderValueStream _s;
944  BSONSizeTracker * _tracker;
945  bool _doneCalled;
946 
947  static const string numStrs[100]; // cache of 0 to 99 inclusive
948  };
949 
950 #if defined (SDB_ENGINE)
951  class BSONArrayBuilder : bsonnoncopyable, public engine::utilPooledObject {
952 #elif defined( SDB_CLIENT )
953  class BSONArrayBuilder : bsonnoncopyable, public SDBObject {
954 #else
955  class BSONArrayBuilder : bsonnoncopyable {
956 #endif
957  public:
958  BSONArrayBuilder() : _i(0), _b() {}
959  BSONArrayBuilder( BufBuilder &_b ) : _i(0), _b(_b) {}
960  BSONArrayBuilder( int initialSize ) : _i(0), _b(initialSize) {}
961 
962  template <typename T>
963  BSONArrayBuilder& append(const T& x) {
964  _b.append(num(), x);
965  return *this;
966  }
967 
968  BSONArrayBuilder& appendTimestamp(unsigned long long val) {
969  _b.appendTimestamp(num(),val);
970  return *this;
971  }
972 
973  BSONArrayBuilder& append(const BSONElement& e) {
974  _b.appendAs(e, num());
975  return *this;
976  }
977 
978  BSONArrayBuilder &appendEx( const BSONElement &e,
979  const BSONObjBuilderOption &option )
980  {
981  _b.appendEx( num(), e, option ) ;
982  return *this ;
983  }
984 
985  template <typename T>
986  BSONArrayBuilder& operator<<(const T& x) {
987  return append(x);
988  }
989 
990  void appendNull() {
991  _b.appendNull(num());
992  }
993 
998  BSONArray arr() { return BSONArray(_b.obj()); }
999 
1000  BSONObj done() { return _b.done(); }
1001 
1002  void doneFast() { _b.doneFast(); }
1003 
1004  void abandon() { _b.abandon() ; }
1005 
1006  template <typename T>
1007  BSONArrayBuilder& append(const StringData& name, const T& x) {
1008  fill( name );
1009  append( x );
1010  return *this;
1011  }
1012 
1013  // These two just use next position
1014  BufBuilder &subobjStart() { return _b.subobjStart( num() ); }
1015  BufBuilder &subarrayStart() { return _b.subarrayStart( num() ); }
1016 
1017  // These fill missing entries up to pos. if pos is < next pos is ignored
1018  BufBuilder &subobjStart(int pos) {
1019  fill(pos);
1020  return _b.subobjStart( num() );
1021  }
1022  BufBuilder &subarrayStart(int pos) {
1023  fill(pos);
1024  return _b.subarrayStart( num() );
1025  }
1026 
1027  // These should only be used where you really need interface compatability with BSONObjBuilder
1028  // Currently they are only used by update.cpp and it should probably stay that way
1029  BufBuilder &subobjStart( const StringData& name ) {
1030  fill( name );
1031  return _b.subobjStart( num() );
1032  }
1033 
1034  BufBuilder &subarrayStart( const char *name ) {
1035  fill( name );
1036  return _b.subarrayStart( num() );
1037  }
1038 
1039  void appendArray( const StringData& name, BSONObj subObj ) {
1040  fill( name );
1041  _b.appendArray( num(), subObj );
1042  }
1043 
1044  void appendAs( const BSONElement &e, const char *name) {
1045  fill( name );
1046  append( e );
1047  }
1048 
1049  int len() const { return _b.len(); }
1050 
1051  private:
1052  void fill( const StringData& name ) {
1053  char *r;
1054  long int n = strtol( name.data(), &r, 10 );
1055  if ( *r )
1056  uasserted( 13048, (string)"can't append to array using string"
1057  " field name [" + name.data() + "]" );
1058  fill(n);
1059  }
1060 
1061  void fill (int upTo){
1062  while( _i < upTo )
1063  append( nullElt() );
1064  }
1065 
1066  static BSONElement nullElt() {
1067  static BSONObj n = nullObj();
1068  return n.firstElement();
1069  }
1070 
1071  static BSONObj nullObj() {
1072  BSONObjBuilder _b;
1073  _b.appendNull( "" );
1074  return _b.obj();
1075  }
1076 
1077  string num() { return _b.numStr(_i++); }
1078  int _i;
1079  BSONObjBuilder _b;
1080  };
1081 
1082  template < class T >
1083  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName,
1084  const vector< T >& vals ) {
1085  BSONObjBuilder arrBuilder;
1086  for ( unsigned int i = 0; i < vals.size(); ++i )
1087  arrBuilder.append( numStr( i ), vals[ i ] );
1088  appendArray( fieldName, arrBuilder.done() );
1089  return *this;
1090  }
1091 
1092  template < class L >
1093  inline BSONObjBuilder& _appendIt( BSONObjBuilder& _this, const StringData& fieldName, const L& vals ) {
1094  BSONObjBuilder arrBuilder;
1095  int n = 0;
1096  for( typename L::const_iterator i = vals.begin(); i != vals.end(); i++ )
1097  arrBuilder.append( BSONObjBuilder::numStr(n++), *i );
1098  _this.appendArray( fieldName, arrBuilder.done() );
1099  return _this;
1100  }
1101 
1102  template < class T >
1103  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName, const list< T >& vals ) {
1104  return _appendIt< list< T > >( *this, fieldName, vals );
1105  }
1106 
1107  template < class T >
1108  inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldName, const set< T >& vals ) {
1109  return _appendIt< set< T > >( *this, fieldName, vals );
1110  }
1111 
1112 
1113  // $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT 6));
1114  inline BSONObj OR(const BSONObj& a, const BSONObj& b)
1115  { return BSON( "$or" << BSON_ARRAY(a << b) ); }
1116  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c)
1117  { return BSON( "$or" << BSON_ARRAY(a << b << c) ); }
1118  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
1119  const BSONObj& d)
1120  { return BSON( "$or" << BSON_ARRAY(a << b << c << d) ); }
1121  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
1122  const BSONObj& d, const BSONObj& e)
1123  { return BSON( "$or" << BSON_ARRAY(a << b << c << d << e) ); }
1124  inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
1125  const BSONObj& d, const BSONObj& e, const BSONObj& f)
1126  { return BSON( "$or" << BSON_ARRAY(a << b << c << d << e << f) ); }
1127 
1128 }