MongoDB  2.7.0
bson-inl.h
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 
23 #include <map>
24 #include <limits>
25 
26 
27 #if defined(_WIN32)
28 #undef max
29 #undef min
30 #endif
31 
32 namespace mongo {
33 
34  /* must be same type when called, unless both sides are #s
35  this large function is in header to facilitate inline-only use of bson
36  */
37  inline int compareElementValues(const BSONElement& l, const BSONElement& r) {
38  int f;
39 
40  switch ( l.type() ) {
41  case EOO:
42  case Undefined: // EOO and Undefined are same canonicalType
43  case jstNULL:
44  case MaxKey:
45  case MinKey:
46  f = l.canonicalType() - r.canonicalType();
47  if ( f<0 ) return -1;
48  return f==0 ? 0 : 1;
49  case Bool:
50  return *l.value() - *r.value();
51  case Timestamp:
52  // unsigned compare for timestamps - note they are not really dates but (ordinal + time_t)
53  if ( l.date() < r.date() )
54  return -1;
55  return l.date() == r.date() ? 0 : 1;
56  case Date:
57  {
58  long long a = (long long) l.Date().millis;
59  long long b = (long long) r.Date().millis;
60  if( a < b )
61  return -1;
62  return a == b ? 0 : 1;
63  }
64  case NumberLong:
65  if( r.type() == NumberLong ) {
66  long long L = l._numberLong();
67  long long R = r._numberLong();
68  if( L < R ) return -1;
69  if( L == R ) return 0;
70  return 1;
71  }
72  goto dodouble;
73  case NumberInt:
74  if( r.type() == NumberInt ) {
75  int L = l._numberInt();
76  int R = r._numberInt();
77  if( L < R ) return -1;
78  return L == R ? 0 : 1;
79  }
80  // else fall through
81  case NumberDouble:
82 dodouble:
83  {
84  double left = l.number();
85  double right = r.number();
86  if( left < right )
87  return -1;
88  if( left == right )
89  return 0;
90  if( isNaN(left) )
91  return isNaN(right) ? 0 : -1;
92  return 1;
93  }
94  case jstOID:
95  return memcmp(l.value(), r.value(), 12);
96  case Code:
97  case Symbol:
98  case String:
99  /* todo: a utf sort order version one day... */
100  {
101  // we use memcmp as we allow zeros in UTF8 strings
102  int lsz = l.valuestrsize();
103  int rsz = r.valuestrsize();
104  int common = std::min(lsz, rsz);
105  int res = memcmp(l.valuestr(), r.valuestr(), common);
106  if( res )
107  return res;
108  // longer string is the greater one
109  return lsz-rsz;
110  }
111  case Object:
112  case Array:
113  return l.embeddedObject().woCompare( r.embeddedObject() );
114  case DBRef: {
115  int lsz = l.valuesize();
116  int rsz = r.valuesize();
117  if ( lsz - rsz != 0 ) return lsz - rsz;
118  return memcmp(l.value(), r.value(), lsz);
119  }
120  case BinData: {
121  int lsz = l.objsize(); // our bin data size in bytes, not including the subtype byte
122  int rsz = r.objsize();
123  if ( lsz - rsz != 0 ) return lsz - rsz;
124  return memcmp(l.value()+4, r.value()+4, lsz+1 /*+1 for subtype byte*/);
125  }
126  case RegEx: {
127  int c = strcmp(l.regex(), r.regex());
128  if ( c )
129  return c;
130  return strcmp(l.regexFlags(), r.regexFlags());
131  }
132  case CodeWScope : {
133  f = l.canonicalType() - r.canonicalType();
134  if ( f )
135  return f;
136  f = strcmp( l.codeWScopeCode() , r.codeWScopeCode() );
137  if ( f )
138  return f;
139  f = strcmp( l.codeWScopeScopeDataUnsafe() , r.codeWScopeScopeDataUnsafe() );
140  if ( f )
141  return f;
142  return 0;
143  }
144  default:
145  verify( false);
146  }
147  return -1;
148  }
149 
150  /* wo = "well ordered"
151  note: (mongodb related) : this can only change in behavior when index version # changes
152  */
153  inline int BSONElement::woCompare( const BSONElement &e,
154  bool considerFieldName ) const {
155  int lt = (int) canonicalType();
156  int rt = (int) e.canonicalType();
157  int x = lt - rt;
158  if( x != 0 && (!isNumber() || !e.isNumber()) )
159  return x;
160  if ( considerFieldName ) {
161  x = strcmp(fieldName(), e.fieldName());
162  if ( x != 0 )
163  return x;
164  }
165  x = compareElementValues(*this, e);
166  return x;
167  }
168 
170  return BSONObjIterator(*this);
171  }
172 
173  inline BSONObj BSONElement::embeddedObjectUserCheck() const {
174  if ( MONGO_likely(isABSONObj()) )
175  return BSONObj(value());
176  std::stringstream ss;
177  ss << "invalid parameter: expected an object (" << fieldName() << ")";
178  uasserted( 10065 , ss.str() );
179  return BSONObj(); // never reachable
180  }
181 
183  verify( isABSONObj() );
184  return BSONObj(value());
185  }
186 
187  inline BSONObj BSONElement::codeWScopeObject() const {
188  verify( type() == CodeWScope );
189  int strSizeWNull = *(int *)( value() + 4 );
190  return BSONObj( value() + 4 + 4 + strSizeWNull );
191  }
192 
193  // deep (full) equality
194  inline bool BSONObj::equal(const BSONObj &rhs) const {
195  BSONObjIterator i(*this);
196  BSONObjIterator j(rhs);
197  BSONElement l,r;
198  do {
199  // so far, equal...
200  l = i.next();
201  r = j.next();
202  if ( l.eoo() )
203  return r.eoo();
204  } while( l == r );
205  return false;
206  }
207 
208  inline NOINLINE_DECL void BSONObj::_assertInvalid() const {
209  StringBuilder ss;
210  int os = objsize();
211  ss << "BSONObj size: " << os << " (0x" << integerToHex( os ) << ") is invalid. "
212  << "Size must be between 0 and " << BSONObjMaxInternalSize
213  << "(" << ( BSONObjMaxInternalSize/(1024*1024) ) << "MB)";
214  try {
215  BSONElement e = firstElement();
216  ss << " First element: " << e.toString();
217  }
218  catch ( ... ) { }
219  massert( 10334 , ss.str() , 0 );
220  }
221 
222  /* the idea with NOINLINE_DECL here is to keep this from inlining in the
223  getOwned() method. the presumption being that is better.
224  */
225  inline NOINLINE_DECL BSONObj BSONObj::copy() const {
226  Holder *h = (Holder*) malloc(objsize() + sizeof(unsigned));
227  h->zero();
228  memcpy(h->data, objdata(), objsize());
229  return BSONObj(h);
230  }
231 
232  inline BSONObj BSONObj::getOwned() const {
233  if ( isOwned() )
234  return *this;
235  return copy();
236  }
237 
238  // wrap this element up as a singleton object.
239  inline BSONObj BSONElement::wrap() const {
240  BSONObjBuilder b(size()+6);
241  b.append(*this);
242  return b.obj();
243  }
244 
245  inline BSONObj BSONElement::wrap( const StringData& newName ) const {
246  BSONObjBuilder b(size() + 6 + newName.size());
247  b.appendAs(*this,newName);
248  return b.obj();
249  }
250 
251  inline void BSONObj::getFields(unsigned n, const char **fieldNames, BSONElement *fields) const {
252  BSONObjIterator i(*this);
253  while ( i.more() ) {
254  BSONElement e = i.next();
255  const char *p = e.fieldName();
256  for( unsigned i = 0; i < n; i++ ) {
257  if( strcmp(p, fieldNames[i]) == 0 ) {
258  fields[i] = e;
259  break;
260  }
261  }
262  }
263  }
264 
265  inline BSONElement BSONObj::getField(const StringData& name) const {
266  BSONObjIterator i(*this);
267  while ( i.more() ) {
268  BSONElement e = i.next();
269  if ( name == e.fieldName() )
270  return e;
271  }
272  return BSONElement();
273  }
274 
275  inline int BSONObj::getIntField(const StringData& name) const {
276  BSONElement e = getField(name);
277  return e.isNumber() ? (int) e.number() : std::numeric_limits< int >::min();
278  }
279 
280  inline bool BSONObj::getBoolField(const StringData& name) const {
281  BSONElement e = getField(name);
282  return e.type() == Bool ? e.boolean() : false;
283  }
284 
285  inline const char * BSONObj::getStringField(const StringData& name) const {
286  BSONElement e = getField(name);
287  return e.type() == String ? e.valuestr() : "";
288  }
289 
290  /* add all the fields from the object specified to this object */
292  if (!x.isEmpty())
293  _b.appendBuf(
294  x.objdata() + 4, // skip over leading length
295  x.objsize() - 5); // ignore leading length and trailing \0
296  return *this;
297  }
298 
299  /* add all the fields from the object specified to this object if they don't exist */
301  std::set<std::string> have;
302  {
303  BSONObjIterator i = iterator();
304  while ( i.more() )
305  have.insert( i.next().fieldName() );
306  }
307 
308  BSONObjIterator it(x);
309  while ( it.more() ) {
310  BSONElement e = it.next();
311  if ( have.count( e.fieldName() ) )
312  continue;
313  append(e);
314  }
315  return *this;
316  }
317 
318 
319  inline bool BSONObj::isValid() const {
320  int x = objsize();
321  return x > 0 && x <= BSONObjMaxInternalSize;
322  }
323 
324  inline bool BSONObj::getObjectID(BSONElement& e) const {
325  BSONElement f = getField("_id");
326  if( !f.eoo() ) {
327  e = f;
328  return true;
329  }
330  return false;
331  }
332 
333  inline BSONObjBuilderValueStream::BSONObjBuilderValueStream( BSONObjBuilder * builder ) {
334  _builder = builder;
335  }
336 
337  template<class T>
338  inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( T value ) {
339  _builder->append(_fieldName, value);
340  _fieldName = StringData();
341  return *_builder;
342  }
343 
344  inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( const BSONElement& e ) {
345  _builder->appendAs( e , _fieldName );
346  _fieldName = StringData();
347  return *_builder;
348  }
349 
350  inline BufBuilder& BSONObjBuilderValueStream::subobjStart() {
351  StringData tmp = _fieldName;
352  _fieldName = StringData();
353  return _builder->subobjStart(tmp);
354  }
355 
356  inline BufBuilder& BSONObjBuilderValueStream::subarrayStart() {
357  StringData tmp = _fieldName;
358  _fieldName = StringData();
359  return _builder->subarrayStart(tmp);
360  }
361 
362  inline Labeler BSONObjBuilderValueStream::operator<<( const Labeler::Label &l ) {
363  return Labeler( l, this );
364  }
365 
366  inline void BSONObjBuilderValueStream::endField( const StringData& nextFieldName ) {
367  if ( haveSubobj() ) {
368  verify( _fieldName.rawData() );
369  _builder->append( _fieldName, subobj()->done() );
370  _subobj.reset();
371  }
372  _fieldName = nextFieldName;
373  }
374 
375  inline BSONObjBuilder *BSONObjBuilderValueStream::subobj() {
376  if ( !haveSubobj() )
377  _subobj.reset( new BSONObjBuilder() );
378  return _subobj.get();
379  }
380 
381  template<class T> inline
382  BSONObjBuilder& Labeler::operator<<( T value ) {
383  s_->subobj()->append( l_.l_, value );
384  return *s_->_builder;
385  }
386 
387  inline
388  BSONObjBuilder& Labeler::operator<<( const BSONElement& e ) {
389  s_->subobj()->appendAs( e, l_.l_ );
390  return *s_->_builder;
391  }
392 
393  // {a: {b:1}} -> {a.b:1}
394  void nested2dotted(BSONObjBuilder& b, const BSONObj& obj, const std::string& base="");
395  inline BSONObj nested2dotted(const BSONObj& obj) {
396  BSONObjBuilder b;
397  nested2dotted(b, obj);
398  return b.obj();
399  }
400 
401  // {a.b:1} -> {a: {b:1}}
402  void dotted2nested(BSONObjBuilder& b, const BSONObj& obj);
403  inline BSONObj dotted2nested(const BSONObj& obj) {
404  BSONObjBuilder b;
405  dotted2nested(b, obj);
406  return b.obj();
407  }
408 
409  inline BSONObjIterator BSONObjBuilder::iterator() const {
410  const char * s = _b.buf() + _offset;
411  const char * e = _b.buf() + _b.len();
412  return BSONObjIterator( s , e );
413  }
414 
415  inline bool BSONObjBuilder::hasField( const StringData& name ) const {
416  BSONObjIterator i = iterator();
417  while ( i.more() )
418  if ( name == i.next().fieldName() )
419  return true;
420  return false;
421  }
422 
423  /* WARNING: nested/dotted conversions are not 100% reversible
424  * nested2dotted(dotted2nested({a.b: {c:1}})) -> {a.b.c: 1}
425  * also, dotted2nested ignores order
426  */
427 
428  typedef std::map<std::string, BSONElement> BSONMap;
429  inline BSONMap bson2map(const BSONObj& obj) {
430  BSONMap m;
431  BSONObjIterator it(obj);
432  while (it.more()) {
433  BSONElement e = it.next();
434  m[e.fieldName()] = e;
435  }
436  return m;
437  }
438 
440  bool operator()( const BSONElement &l, const BSONElement &r ) const {
441  return strcmp( l.fieldName() , r.fieldName() ) <= 0;
442  }
443  };
444 
445  typedef std::set<BSONElement, BSONElementFieldNameCmp> BSONSortedElements;
446  inline BSONSortedElements bson2set( const BSONObj& obj ) {
447  BSONSortedElements s;
448  BSONObjIterator it(obj);
449  while ( it.more() )
450  s.insert( it.next() );
451  return s;
452  }
453 
454  inline std::string BSONObj::toString( bool isArray, bool full ) const {
455  if ( isEmpty() ) return (isArray ? "[]" : "{}");
456  StringBuilder s;
457  toString(s, isArray, full);
458  return s.str();
459  }
460  inline void BSONObj::toString( StringBuilder& s, bool isArray, bool full, int depth ) const {
461  if ( isEmpty() ) {
462  s << (isArray ? "[]" : "{}");
463  return;
464  }
465 
466  s << ( isArray ? "[ " : "{ " );
467  BSONObjIterator i(*this);
468  bool first = true;
469  while ( 1 ) {
470  massert( 10327 , "Object does not end with EOO", i.moreWithEOO() );
471  BSONElement e = i.next( true );
472  massert( 10328 , "Invalid element size", e.size() > 0 );
473  massert( 10329 , "Element too large", e.size() < ( 1 << 30 ) );
474  int offset = (int) (e.rawdata() - this->objdata());
475  massert( 10330 , "Element extends past end of object",
476  e.size() + offset <= this->objsize() );
477  bool end = ( e.size() + offset == this->objsize() );
478  if ( e.eoo() ) {
479  massert( 10331 , "EOO Before end of object", end );
480  break;
481  }
482  if ( first )
483  first = false;
484  else
485  s << ", ";
486  e.toString( s, !isArray, full, depth );
487  }
488  s << ( isArray ? " ]" : " }" );
489  }
490 
491  inline int BSONElement::size( int maxLen ) const {
492  if ( totalSize >= 0 )
493  return totalSize;
494 
495  int remain = maxLen - fieldNameSize() - 1;
496 
497  int x = 0;
498  switch ( type() ) {
499  case EOO:
500  case Undefined:
501  case jstNULL:
502  case MaxKey:
503  case MinKey:
504  break;
505  case mongo::Bool:
506  x = 1;
507  break;
508  case NumberInt:
509  x = 4;
510  break;
511  case Timestamp:
512  case mongo::Date:
513  case NumberDouble:
514  case NumberLong:
515  x = 8;
516  break;
517  case jstOID:
518  x = 12;
519  break;
520  case Symbol:
521  case Code:
522  case mongo::String:
523  massert( 10313 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
524  x = valuestrsize() + 4;
525  break;
526  case CodeWScope:
527  massert( 10314 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
528  x = objsize();
529  break;
530 
531  case DBRef:
532  massert( 10315 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
533  x = valuestrsize() + 4 + 12;
534  break;
535  case Object:
536  case mongo::Array:
537  massert( 10316 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
538  x = objsize();
539  break;
540  case BinData:
541  massert( 10317 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
542  x = valuestrsize() + 4 + 1/*subtype*/;
543  break;
544  case RegEx: {
545  const char *p = value();
546  size_t len1 = ( maxLen == -1 ) ? strlen( p ) : (size_t)mongo::strnlen( p, remain );
547  //massert( 10318 , "Invalid regex string", len1 != -1 ); // ERH - 4/28/10 - don't think this does anything
548  p = p + len1 + 1;
549  size_t len2;
550  if( maxLen == -1 )
551  len2 = strlen( p );
552  else {
553  size_t x = remain - len1 - 1;
554  verify( x <= 0x7fffffff );
555  len2 = mongo::strnlen( p, (int) x );
556  }
557  //massert( 10319 , "Invalid regex options string", len2 != -1 ); // ERH - 4/28/10 - don't think this does anything
558  x = (int) (len1 + 1 + len2 + 1);
559  }
560  break;
561  default: {
562  StringBuilder ss;
563  ss << "BSONElement: bad type " << (int) type();
564  std::string msg = ss.str();
565  massert( 13655 , msg.c_str(),false);
566  }
567  }
568  totalSize = x + fieldNameSize() + 1; // BSONType
569 
570  return totalSize;
571  }
572 
573  inline int BSONElement::size() const {
574  if ( totalSize >= 0 )
575  return totalSize;
576 
577  int x = 0;
578  switch ( type() ) {
579  case EOO:
580  case Undefined:
581  case jstNULL:
582  case MaxKey:
583  case MinKey:
584  break;
585  case mongo::Bool:
586  x = 1;
587  break;
588  case NumberInt:
589  x = 4;
590  break;
591  case Timestamp:
592  case mongo::Date:
593  case NumberDouble:
594  case NumberLong:
595  x = 8;
596  break;
597  case jstOID:
598  x = 12;
599  break;
600  case Symbol:
601  case Code:
602  case mongo::String:
603  x = valuestrsize() + 4;
604  break;
605  case DBRef:
606  x = valuestrsize() + 4 + 12;
607  break;
608  case CodeWScope:
609  case Object:
610  case mongo::Array:
611  x = objsize();
612  break;
613  case BinData:
614  x = valuestrsize() + 4 + 1/*subtype*/;
615  break;
616  case RegEx:
617  {
618  const char *p = value();
619  size_t len1 = strlen(p);
620  p = p + len1 + 1;
621  size_t len2;
622  len2 = strlen( p );
623  x = (int) (len1 + 1 + len2 + 1);
624  }
625  break;
626  default:
627  {
628  StringBuilder ss;
629  ss << "BSONElement: bad type " << (int) type();
630  std::string msg = ss.str();
631  massert(10320 , msg.c_str(),false);
632  }
633  }
634  totalSize = x + fieldNameSize() + 1; // BSONType
635 
636  return totalSize;
637  }
638 
639  inline std::string BSONElement::toString( bool includeFieldName, bool full ) const {
640  StringBuilder s;
641  toString(s, includeFieldName, full);
642  return s.str();
643  }
644  inline void BSONElement::toString( StringBuilder& s, bool includeFieldName, bool full, int depth ) const {
645 
646  if ( depth > BSONObj::maxToStringRecursionDepth ) {
647  // check if we want the full/complete string
648  if ( full ) {
649  StringBuilder s;
650  s << "Reached maximum recursion depth of ";
651  s << BSONObj::maxToStringRecursionDepth;
652  uassert(16150, s.str(), full != true);
653  }
654  s << "...";
655  return;
656  }
657 
658  if ( includeFieldName && type() != EOO )
659  s << fieldName() << ": ";
660  switch ( type() ) {
661  case EOO:
662  s << "EOO";
663  break;
664  case mongo::Date:
665  s << "new Date(" << (long long) date() << ')';
666  break;
667  case RegEx: {
668  s << "/" << regex() << '/';
669  const char *p = regexFlags();
670  if ( p ) s << p;
671  }
672  break;
673  case NumberDouble:
674  s.appendDoubleNice( number() );
675  break;
676  case NumberLong:
677  s << _numberLong();
678  break;
679  case NumberInt:
680  s << _numberInt();
681  break;
682  case mongo::Bool:
683  s << ( boolean() ? "true" : "false" );
684  break;
685  case Object:
686  embeddedObject().toString(s, false, full, depth+1);
687  break;
688  case mongo::Array:
689  embeddedObject().toString(s, true, full, depth+1);
690  break;
691  case Undefined:
692  s << "undefined";
693  break;
694  case jstNULL:
695  s << "null";
696  break;
697  case MaxKey:
698  s << "MaxKey";
699  break;
700  case MinKey:
701  s << "MinKey";
702  break;
703  case CodeWScope:
704  s << "CodeWScope( "
705  << codeWScopeCode() << ", " << codeWScopeObject().toString(false, full) << ")";
706  break;
707  case Code:
708  if ( !full && valuestrsize() > 80 ) {
709  s.write(valuestr(), 70);
710  s << "...";
711  }
712  else {
713  s.write(valuestr(), valuestrsize()-1);
714  }
715  break;
716  case Symbol:
717  case mongo::String:
718  s << '"';
719  if ( !full && valuestrsize() > 160 ) {
720  s.write(valuestr(), 150);
721  s << "...\"";
722  }
723  else {
724  s.write(valuestr(), valuestrsize()-1);
725  s << '"';
726  }
727  break;
728  case DBRef:
729  s << "DBRef('" << valuestr() << "',";
730  {
731  mongo::OID *x = (mongo::OID *) (valuestr() + valuestrsize());
732  s << *x << ')';
733  }
734  break;
735  case jstOID:
736  s << "ObjectId('";
737  s << __oid() << "')";
738  break;
739  case BinData:
740  s << "BinData";
741  if (full) {
742  int len;
743  const char* data = binDataClean(len);
744  s << '(' << binDataType() << ", " << toHex(data, len) << ')';
745  }
746  break;
747  case Timestamp:
748  s << "Timestamp " << timestampTime() << "|" << timestampInc();
749  break;
750  default:
751  s << "?type=" << type();
752  break;
753  }
754  }
755 
756  /* return has eoo() true if no match
757  supports "." notation to reach into embedded objects
758  */
759  inline BSONElement BSONObj::getFieldDotted(const StringData& name) const {
760  BSONElement e = getField(name);
761  if (e.eoo()) {
762  size_t dot_offset = name.find('.');
763  if (dot_offset != string::npos) {
764  StringData left = name.substr(0, dot_offset);
765  StringData right = name.substr(dot_offset + 1);
766  BSONObj sub = getObjectField(left);
767  return sub.isEmpty() ? BSONElement() : sub.getFieldDotted(right);
768  }
769  }
770 
771  return e;
772  }
773 
774  inline BSONObj BSONObj::getObjectField(const StringData& name) const {
775  BSONElement e = getField(name);
776  BSONType t = e.type();
777  return t == Object || t == Array ? e.embeddedObject() : BSONObj();
778  }
779 
780  inline int BSONObj::nFields() const {
781  int n = 0;
782  BSONObjIterator i(*this);
783  while ( i.moreWithEOO() ) {
784  BSONElement e = i.next();
785  if ( e.eoo() )
786  break;
787  n++;
788  }
789  return n;
790  }
791 
792  inline BSONObj::BSONObj() {
793  /* little endian ordering here, but perhaps that is ok regardless as BSON is spec'd
794  to be little endian external to the system. (i.e. the rest of the implementation of bson,
795  not this part, fails to support big endian)
796  */
797  static char p[] = { /*size*/5, 0, 0, 0, /*eoo*/0 };
798  _objdata = p;
799  }
800 
801  inline BSONObj BSONElement::Obj() const { return embeddedObjectUserCheck(); }
802 
803  inline BSONElement BSONElement::operator[] (const std::string& field) const {
804  BSONObj o = Obj();
805  return o[field];
806  }
807 
808  inline void BSONObj::elems(std::vector<BSONElement> &v) const {
809  BSONObjIterator i(*this);
810  while( i.more() )
811  v.push_back(i.next());
812  }
813 
814  inline void BSONObj::elems(std::list<BSONElement> &v) const {
815  BSONObjIterator i(*this);
816  while( i.more() )
817  v.push_back(i.next());
818  }
819 
820  template <class T>
821  void BSONObj::Vals(std::vector<T>& v) const {
822  BSONObjIterator i(*this);
823  while( i.more() ) {
824  T t;
825  i.next().Val(t);
826  v.push_back(t);
827  }
828  }
829  template <class T>
830  void BSONObj::Vals(std::list<T>& v) const {
831  BSONObjIterator i(*this);
832  while( i.more() ) {
833  T t;
834  i.next().Val(t);
835  v.push_back(t);
836  }
837  }
838 
839  template <class T>
840  void BSONObj::vals(std::vector<T>& v) const {
841  BSONObjIterator i(*this);
842  while( i.more() ) {
843  try {
844  T t;
845  i.next().Val(t);
846  v.push_back(t);
847  }
848  catch(...) { }
849  }
850  }
851  template <class T>
852  void BSONObj::vals(std::list<T>& v) const {
853  BSONObjIterator i(*this);
854  while( i.more() ) {
855  try {
856  T t;
857  i.next().Val(t);
858  v.push_back(t);
859  }
860  catch(...) { }
861  }
862  }
863 
864  inline std::ostream& operator<<( std::ostream &s, const BSONObj &o ) {
865  return s << o.toString();
866  }
867 
868  inline std::ostream& operator<<( std::ostream &s, const BSONElement &e ) {
869  return s << e.toString();
870  }
871 
872  inline StringBuilder& operator<<( StringBuilder &s, const BSONObj &o ) {
873  o.toString( s );
874  return s;
875  }
876  inline StringBuilder& operator<<( StringBuilder &s, const BSONElement &e ) {
877  e.toString( s );
878  return s;
879  }
880 
881 
882  inline void BSONElement::Val(BSONObj& v) const { v = Obj(); }
883 
884  template<typename T>
885  inline BSONFieldValue<BSONObj> BSONField<T>::query( const char * q , const T& t ) const {
886  BSONObjBuilder b;
887  b.append( q , t );
888  return BSONFieldValue<BSONObj>( _name , b.obj() );
889  }
890 
891  // used by jsonString()
892  inline std::string escape( const std::string& s , bool escape_slash=false) {
893  StringBuilder ret;
894  for ( std::string::const_iterator i = s.begin(); i != s.end(); ++i ) {
895  switch ( *i ) {
896  case '"':
897  ret << "\\\"";
898  break;
899  case '\\':
900  ret << "\\\\";
901  break;
902  case '/':
903  ret << (escape_slash ? "\\/" : "/");
904  break;
905  case '\b':
906  ret << "\\b";
907  break;
908  case '\f':
909  ret << "\\f";
910  break;
911  case '\n':
912  ret << "\\n";
913  break;
914  case '\r':
915  ret << "\\r";
916  break;
917  case '\t':
918  ret << "\\t";
919  break;
920  default:
921  if ( *i >= 0 && *i <= 0x1f ) {
922  //TODO: these should be utf16 code-units not bytes
923  char c = *i;
924  ret << "\\u00" << toHexLower(&c, 1);
925  }
926  else {
927  ret << *i;
928  }
929  }
930  }
931  return ret.str();
932  }
933 
934  inline std::string BSONObj::hexDump() const {
935  std::stringstream ss;
936  const char *d = objdata();
937  int size = objsize();
938  for( int i = 0; i < size; ++i ) {
939  ss.width( 2 );
940  ss.fill( '0' );
941  ss << std::hex << (unsigned)(unsigned char)( d[ i ] ) << std::dec;
942  if ( ( d[ i ] >= '0' && d[ i ] <= '9' ) || ( d[ i ] >= 'A' && d[ i ] <= 'z' ) )
943  ss << '\'' << d[ i ] << '\'';
944  if ( i != size - 1 )
945  ss << ' ';
946  }
947  return ss.str();
948  }
949 
950  inline void BSONObjBuilder::appendKeys( const BSONObj& keyPattern , const BSONObj& values ) {
951  BSONObjIterator i(keyPattern);
952  BSONObjIterator j(values);
953 
954  while ( i.more() && j.more() ) {
955  appendAs( j.next() , i.next().fieldName() );
956  }
957 
958  verify( ! i.more() );
959  verify( ! j.more() );
960  }
961 
962  inline BSONObj BSONObj::removeField(const StringData& name) const {
963  BSONObjBuilder b;
964  BSONObjIterator i(*this);
965  while ( i.more() ) {
966  BSONElement e = i.next();
967  const char *fname = e.fieldName();
968  if ( name != fname )
969  b.append(e);
970  }
971  return b.obj();
972  }
973 
974  template<typename T> bool BSONObj::coerceVector( std::vector<T>* out ) const {
975  BSONObjIterator i( *this );
976  while ( i.more() ) {
977  BSONElement e = i.next();
978  T t;
979  if ( ! e.coerce<T>( &t ) )
980  return false;
981  out->push_back( t );
982  }
983  return true;
984  }
985 
986 
987  template<> inline bool BSONElement::coerce<std::string>( std::string* out ) const {
988  if ( type() != mongo::String )
989  return false;
990  *out = String();
991  return true;
992  }
993 
994  template<> inline bool BSONElement::coerce<int>( int* out ) const {
995  if ( !isNumber() )
996  return false;
997  *out = numberInt();
998  return true;
999  }
1000 
1001  template<> inline bool BSONElement::coerce<double>( double* out ) const {
1002  if ( !isNumber() )
1003  return false;
1004  *out = numberDouble();
1005  return true;
1006  }
1007 
1008  template<> inline bool BSONElement::coerce<bool>( bool* out ) const {
1009  *out = trueValue();
1010  return true;
1011  }
1012 
1013  template<> inline bool BSONElement::coerce< std::vector<std::string> >( std::vector<std::string>* out ) const {
1014  if ( type() != mongo::Array )
1015  return false;
1016  return Obj().coerceVector<std::string>( out );
1017  }
1018 
1019 
1020 }
Definition: bsonobj.h:501
BSONObj()
Construct an empty BSONObj – that is, {}.
Definition: bson-inl.h:792
end of object
Definition: bsontypes.h:47
void Val(Date_t &v) const
populate v with the value of the element.
Definition: bsonelement.h:92
Utility for creating a BSONObj.
Definition: bsonobjbuilder.h:52
int fieldNameSize() const
NOTE: size includes the NULL terminator.
Definition: bsonelement.h:151
BSONObjBuilder & append(const BSONElement &e)
append element to the object we are building
Definition: bsonobjbuilder.h:85
bool isABSONObj() const
True if this element can be a BSONObj.
Definition: bsonelement.h:392
BSONType type() const
Returns the type of the element.
Definition: bsonelement.h:112
int size(int maxLen) const
Size of the element.
Definition: bson-inl.h:491
const char * objdata() const
Definition: bsonobj.h:266
const char * getStringField(const StringData &name) const
Definition: bson-inl.h:285
const char * fieldName() const
field name of the element.
Definition: bsonelement.h:143
larger than all other types
Definition: bsontypes.h:87
int len() const
Definition: builder.h:195
LogstreamBuilder out()
Synonym for log().
Definition: log.h:79
int getIntField(const StringData &name) const
Definition: bson-inl.h:275
int objsize() const
Definition: bsonobj.h:270
bool isEmpty() const
Definition: bsonobj.h:320
Definition: bson-inl.h:439
const char * regex() const
Retrieve the regex string for a Regex element.
Definition: bsonelement.h:339
BufBuilder & subarrayStart(const StringData &fieldName)
add header for a new subarray and return bufbuilder for writing to the subarray's body ...
Definition: bsonobjbuilder.h:155
const char * binDataClean(int &len) const
Get binary data.
Definition: bsonelement.h:319
BSONObjIterator begin() const
use something like this: for( BSONObj::iterator i = myObj.begin(); i.more(); ) { BSONElement e = i...
Definition: bson-inl.h:169
void elems(std::vector< BSONElement > &) const
add all elements of the object to the specified vector
Definition: bson-inl.h:808
BSONObj copy() const
Definition: bson-inl.h:225
std::string hexDump() const
Alternative output format.
Definition: bson-inl.h:934
BSONElement operator[](const std::string &field) const
retrieve a field within this element throws exception if *this is not an embedded object ...
Definition: bson-inl.h:803
BSONObj obj()
destructive The returned BSONObj will free the buffer when it is finished.
Definition: bsonobjbuilder.h:573
BSONObj getOwned() const
assure the data buffer is under the control of this BSONObj and not a remote buffer ...
Definition: bson-inl.h:232
bool moreWithEOO()
Definition: bsonobjiterator.h:60
BSONObjBuilder & appendElements(BSONObj x)
add all the fields from the object specified to this object
Definition: bson-inl.h:291
BSONObj removeField(const StringData &name) const
remove specified field and return a new object with the remaining fields.
Definition: bson-inl.h:962
bool isOwned() const
A BSONObj can use a buffer it "owns" or one it does not.
Definition: bsonobj.h:131
Updated to a Date with value next OpTime on insert.
Definition: bsontypes.h:81
BSONObjBuilder & appendElementsUnique(BSONObj x)
add all the fields from the object specified to this object if they don't exist already ...
Definition: bson-inl.h:300
date type
Definition: bsontypes.h:65
const char * value() const
raw data of the element's value (so be careful).
Definition: bsonelement.h:162
boolean type
Definition: bsontypes.h:63
const mongo::OID & __oid() const
Retrieve the object ID stored in the object.
Definition: bsonelement.h:232
const char * valuestr() const
Get a string's value.
Definition: bsonelement.h:255
smaller than all other types
Definition: bsontypes.h:45
bool eoo() const
Indicates if it is the end-of-object element, which is present at the end of every BSON object...
Definition: bsonelement.h:125
double number() const
Retrieve the numeric value of the element.
Definition: bsonelement.h:228
BSONType
the complete list of valid BSON types see also bsonspec.org
Definition: bsontypes.h:43
BufBuilder & subobjStart(const StringData &fieldName)
add header for a new subobject and return bufbuilder for writing to the subobject's body ...
Definition: bsonobjbuilder.h:134
ObjectId.
Definition: bsontypes.h:61
an embedded object
Definition: bsontypes.h:53
32 bit signed integer
Definition: bsontypes.h:79
double precision floating point value
Definition: bsontypes.h:49
int woCompare(const BSONElement &e, bool considerFieldName=true) const
Well ordered comparison.
Definition: bson-inl.h:153
null type
Definition: bsontypes.h:67
BSONObjBuilder & appendAs(const BSONElement &e, const StringData &fieldName)
append an element but with a new name
Definition: bsonobjbuilder.h:92
void vals(std::vector< T > &) const
add all values of the object to the specified vector.
Definition: bson-inl.h:840
BSONElement firstElement() const
Definition: bsonobj.h:383
a programming language (e.g., Python) symbol
Definition: bsontypes.h:75
javascript code that can execute on the database server, with SavedContext
Definition: bsontypes.h:77
BSONElement getField(const StringData &name) const
Get the field of the specified name.
Definition: bson-inl.h:265
void getFields(unsigned n, const char **fieldNames, BSONElement *fields) const
Get several fields at once.
Definition: bson-inl.h:251
bool isNumber() const
True if element is of a numeric type.
Definition: bsonelement.h:526
const char * codeWScopeCode() const
Get javascript code of a CodeWScope data element.
Definition: bsonelement.h:269
Undefined type.
Definition: bsontypes.h:59
iterator for a BSONObj
Definition: bsonobjiterator.h:37
int canonicalType() const
See canonicalizeBSONType in bsontypes.h.
Definition: bsonelement.h:120
BSONObj getObjectField(const StringData &name) const
Definition: bson-inl.h:774
bool more()
Definition: bsonobjiterator.h:57
bool getBoolField(const StringData &name) const
Definition: bson-inl.h:280
regular expression, a pattern with options
Definition: bsontypes.h:69
64 bit integer
Definition: bsontypes.h:83
an embedded array
Definition: bsontypes.h:55
deprecated / use CodeWScope
Definition: bsontypes.h:73
int _numberInt() const
Return int value for this field.
Definition: bsonelement.h:203
stringstream deals with locale so this is a lot faster than std::stringstream for UTF8 ...
Definition: builder.h:61
BSONObj Obj() const
Definition: bson-inl.h:801
deprecated / will be redesigned
Definition: bsontypes.h:71
BSONElement represents an "element" in a BSONObj.
Definition: bsonelement.h:62
C++ representation of a "BSON" object – that is, an extended JSON-style object in a binary representa...
Definition: bsonobj.h:77
BSONObj embeddedObject() const
Get the embedded object this element holds.
Definition: bson-inl.h:182
BSONObj wrap() const
Wrap this element up as a singleton object.
Definition: bson-inl.h:239
int valuestrsize() const
Size (length) of a string element.
Definition: bsonelement.h:243
BSONElement next(bool checkEnd)
Definition: bsonobjiterator.h:63
bool boolean() const
Definition: bsonelement.h:175
void Vals(std::vector< T > &) const
add all values of the object to the specified vector.
Definition: bson-inl.h:821
bool isValid() const
performs a cursory check on the object's size only.
Definition: bson-inl.h:319
bool getObjectID(BSONElement &e) const
Get the _id field from the object.
Definition: bson-inl.h:324
Object ID type.
Definition: oid.h:42
binary data
Definition: bsontypes.h:57
Date_t date() const
Retrieve a java style date value from the element.
Definition: bsonelement.h:185
long long _numberLong() const
Return long long value for this field.
Definition: bsonelement.h:205
const char * regexFlags() const
Retrieve the regex flags (options) for a Regex element.
Definition: bsonelement.h:345
BSONElement getFieldDotted(const StringData &name) const
Definition: bson-inl.h:759
int nFields() const
returns # of top level fields in the object note: iterates to count the fields
Definition: bson-inl.h:780
character string, stored in utf8
Definition: bsontypes.h:51