MongoDB  2.6.0
bsonelement.h
1 // bsonelement.h
2 
3 /* Copyright 2009 10gen Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #pragma once
19 
20 #include <string.h> // strlen
21 #include <string>
22 #include <vector>
23 
24 #include "mongo/bson/bsontypes.h"
25 #include "mongo/bson/oid.h"
26 #include "mongo/client/export_macros.h"
27 #include "mongo/platform/cstdint.h"
28 #include "mongo/platform/float_utils.h"
29 
30 namespace mongo {
31  class OpTime;
32  class BSONObj;
33  class BSONElement;
34  class BSONObjBuilder;
35 }
36 
37 namespace bson {
38  typedef mongo::BSONElement be;
39  typedef mongo::BSONObj bo;
40  typedef mongo::BSONObjBuilder bob;
41 }
42 
43 namespace mongo {
44 
45  /* l and r MUST have same type when called: check that first. */
46  int compareElementValues(const BSONElement& l, const BSONElement& r);
47 
48 
62  class MONGO_CLIENT_API BSONElement {
63  public:
69  std::string String() const { return chk(mongo::String).str(); }
70  Date_t Date() const { return chk(mongo::Date).date(); }
71  double Number() const { return chk(isNumber()).number(); }
72  double Double() const { return chk(NumberDouble)._numberDouble(); }
73  long long Long() const { return chk(NumberLong)._numberLong(); }
74  int Int() const { return chk(NumberInt)._numberInt(); }
75  bool Bool() const { return chk(mongo::Bool).boolean(); }
76  std::vector<BSONElement> Array() const; // see implementation for detailed comments
77  mongo::OID OID() const { return chk(jstOID).__oid(); }
78  void Null() const { chk(isNull()); } // throw MsgAssertionException if not null
79  void OK() const { chk(ok()); } // throw MsgAssertionException if element DNE
80 
87  BSONObj Obj() const;
88 
92  void Val(Date_t& v) const { v = Date(); }
93  void Val(long long& v) const { v = Long(); }
94  void Val(bool& v) const { v = Bool(); }
95  void Val(BSONObj& v) const;
96  void Val(mongo::OID& v) const { v = OID(); }
97  void Val(int& v) const { v = Int(); }
98  void Val(double& v) const { v = Double(); }
99  void Val(std::string& v) const { v = String(); }
100 
104  bool ok() const { return !eoo(); }
105 
106  std::string toString( bool includeFieldName = true, bool full=false) const;
107  void toString(StringBuilder& s, bool includeFieldName = true, bool full=false, int depth=0) const;
108  std::string jsonString( JsonStringFormat format, bool includeFieldNames = true, int pretty = 0 ) const;
109  operator std::string() const { return toString(); }
110 
112  BSONType type() const { return (BSONType) *reinterpret_cast< const signed char * >(data); }
113 
117  BSONElement operator[] (const std::string& field) const;
118 
120  int canonicalType() const { return canonicalizeBSONType(type()); }
121 
125  bool eoo() const { return type() == EOO; }
126 
130  int size( int maxLen ) const;
131  int size() const;
132 
134  BSONObj wrap() const;
135 
137  BSONObj wrap( const StringData& newName) const;
138 
143  const char * fieldName() const {
144  if ( eoo() ) return ""; // no fieldname for it.
145  return data + 1;
146  }
147 
151  int fieldNameSize() const {
152  if ( fieldNameSize_ == -1 )
153  fieldNameSize_ = (int)strlen( fieldName() ) + 1;
154  return fieldNameSize_;
155  }
156 
157  const StringData fieldNameStringData() const {
158  return StringData(fieldName(), fieldNameSize() - 1);
159  }
160 
162  const char * value() const {
163  return (data + fieldNameSize() + 1);
164  }
166  int valuesize() const {
167  return size() - fieldNameSize() - 1;
168  }
169 
170  bool isBoolean() const { return type() == mongo::Bool; }
171 
175  bool boolean() const {
176  return *value() ? true : false;
177  }
178 
179  bool booleanSafe() const { return isBoolean() && boolean(); }
180 
185  Date_t date() const {
186  return *reinterpret_cast< const Date_t* >( value() );
187  }
188 
192  bool trueValue() const;
193 
195  bool isSimpleType() const;
196 
198  bool isNumber() const;
199 
201  double _numberDouble() const {return (reinterpret_cast< const PackedDouble* >( value() ))->d; }
203  int _numberInt() const {return *reinterpret_cast< const int* >( value() ); }
205  long long _numberLong() const {return *reinterpret_cast< const long long* >( value() ); }
206 
208  int numberInt() const;
212  long long numberLong() const;
213 
219  long long safeNumberLong() const;
220 
224  double numberDouble() const;
228  double number() const { return numberDouble(); }
229 
232  const mongo::OID &__oid() const { return *reinterpret_cast< const mongo::OID* >( value() ); }
233 
235  bool isNull() const {
236  return type() == jstNULL;
237  }
238 
243  int valuestrsize() const {
244  return *reinterpret_cast< const int* >( value() );
245  }
246 
247  // for objects the size *includes* the size of the size field
248  size_t objsize() const {
249  return static_cast< const size_t >( *reinterpret_cast< const uint32_t* >( value() ) );
250  }
251 
255  const char * valuestr() const {
256  return value() + 4;
257  }
258 
260  const char *valuestrsafe() const {
261  return type() == mongo::String ? valuestr() : "";
262  }
264  std::string str() const {
265  return type() == mongo::String ? std::string(valuestr(), valuestrsize()-1) : std::string();
266  }
267 
269  const char * codeWScopeCode() const {
270  massert( 16177 , "not codeWScope" , type() == CodeWScope );
271  return value() + 4 + 4; //two ints precede code (see BSON spec)
272  }
273 
276  int codeWScopeCodeLen() const {
277  massert( 16178 , "not codeWScope" , type() == CodeWScope );
278  return *(int *)( value() + 4 );
279  }
280 
288  const char * codeWScopeScopeDataUnsafe() const {
289  //This can error if there are null chars in the codeWScopeCode
290  return codeWScopeCode() + strlen( codeWScopeCode() ) + 1;
291  }
292 
293  /* Get the scope SavedContext of a CodeWScope data element.
294  *
295  * This is the corrected version of codeWScopeScopeDataUnsafe(),
296  * but note that existing uses might rely on the behavior of
297  * that function so be careful in choosing which version to use.
298  */
299  const char * codeWScopeScopeData() const {
300  return codeWScopeCode() + codeWScopeCodeLen();
301  }
302 
304  BSONObj embeddedObject() const;
305 
306  /* uasserts if not an object */
307  BSONObj embeddedObjectUserCheck() const;
308 
309  BSONObj codeWScopeObject() const;
310 
312  const char *binData(int& len) const {
313  // BinData: <int len> <byte subtype> <byte[len] data>
314  verify( type() == BinData );
315  len = valuestrsize();
316  return value() + 5;
317  }
319  const char *binDataClean(int& len) const {
320  // BinData: <int len> <byte subtype> <byte[len] data>
321  if (binDataType() != ByteArrayDeprecated) {
322  return binData(len);
323  }
324  else {
325  // Skip extra size
326  len = valuestrsize() - 4;
327  return value() + 5 + 4;
328  }
329  }
330 
331  BinDataType binDataType() const {
332  // BinData: <int len> <byte subtype> <byte[len] data>
333  verify( type() == BinData );
334  unsigned char c = (value() + 4)[0];
335  return (BinDataType)c;
336  }
337 
339  const char *regex() const {
340  verify(type() == RegEx);
341  return value();
342  }
343 
345  const char *regexFlags() const {
346  const char *p = regex();
347  return p + strlen(p) + 1;
348  }
349 
353  bool valuesEqual(const BSONElement& r) const {
354  return woCompare( r , false ) == 0;
355  }
356 
358  bool operator==(const BSONElement& r) const {
359  return woCompare( r , true ) == 0;
360  }
362  bool operator!=(const BSONElement& r) const { return !operator==(r); }
363 
369  int woCompare( const BSONElement &e, bool considerFieldName = true ) const;
370 
371  const char * rawdata() const { return data; }
372 
374  int getGtLtOp( int def = 0 ) const;
375 
377  BSONElement();
378 
380  bool mayEncapsulate() const {
381  switch ( type() ) {
382  case Object:
383  case mongo::Array:
384  case CodeWScope:
385  return true;
386  default:
387  return false;
388  }
389  }
390 
392  bool isABSONObj() const {
393  switch( type() ) {
394  case Object:
395  case mongo::Array:
396  return true;
397  default:
398  return false;
399  }
400  }
401 
402  Date_t timestampTime() const {
403  unsigned long long t = ((unsigned int*)(value() + 4 ))[0];
404  return t * 1000;
405  }
406  unsigned int timestampInc() const {
407  return ((unsigned int*)(value() ))[0];
408  }
409 
410  unsigned long long timestampValue() const {
411  return reinterpret_cast<const unsigned long long*>( value() )[0];
412  }
413 
414  const char * dbrefNS() const {
415  uassert( 10063 , "not a dbref" , type() == DBRef );
416  return value() + 4;
417  }
418 
419  const mongo::OID& dbrefOID() const {
420  uassert( 10064 , "not a dbref" , type() == DBRef );
421  const char * start = value();
422  start += 4 + *reinterpret_cast< const int* >( start );
423  return *reinterpret_cast< const mongo::OID* >( start );
424  }
425 
427  bool operator<( const BSONElement& other ) const {
428  int x = (int)canonicalType() - (int)other.canonicalType();
429  if ( x < 0 ) return true;
430  else if ( x > 0 ) return false;
431  return compareElementValues(*this,other) < 0;
432  }
433 
434  // @param maxLen don't scan more than maxLen bytes
435  explicit BSONElement(const char *d, int maxLen) : data(d) {
436  if ( eoo() ) {
437  totalSize = 1;
438  fieldNameSize_ = 0;
439  }
440  else {
441  totalSize = -1;
442  fieldNameSize_ = -1;
443  if ( maxLen != -1 ) {
444  int size = (int) strnlen( fieldName(), maxLen - 1 );
445  uassert( 10333 , "Invalid field name", size != -1 );
446  fieldNameSize_ = size + 1;
447  }
448  }
449  }
450 
451  explicit BSONElement(const char *d) : data(d) {
452  fieldNameSize_ = -1;
453  totalSize = -1;
454  if ( eoo() ) {
455  fieldNameSize_ = 0;
456  totalSize = 1;
457  }
458  }
459 
460  struct FieldNameSizeTag {}; // For disambiguation with ctor taking 'maxLen' above.
461 
467  BSONElement(const char* d, int fieldNameSize, FieldNameSizeTag)
468  : data(d)
469  , fieldNameSize_(fieldNameSize) // internal size includes null terminator
470  , totalSize(-1) {
471  }
472 
473  std::string _asCode() const;
474  OpTime _opTime() const;
475 
476  template<typename T> bool coerce( T* out ) const;
477 
478  private:
479  const char *data;
480  mutable int fieldNameSize_; // cached value
481 
482  mutable int totalSize; /* caches the computed size */
483 
484  friend class BSONObjIterator;
485  friend class BSONObj;
486  const BSONElement& chk(int t) const {
487  if ( t != type() ) {
488  StringBuilder ss;
489  if( eoo() )
490  ss << "field not found, expected type " << t;
491  else
492  ss << "wrong type for field (" << fieldName() << ") " << type() << " != " << t;
493  msgasserted(13111, ss.str() );
494  }
495  return *this;
496  }
497  const BSONElement& chk(bool expr) const {
498  massert(13118, "unexpected or missing type value in BSON object", expr);
499  return *this;
500  }
501  };
502 
503  inline bool BSONElement::trueValue() const {
504  // NOTE Behavior changes must be replicated in Value::coerceToBool().
505  switch( type() ) {
506  case NumberLong:
507  return *reinterpret_cast< const long long* >( value() ) != 0;
508  case NumberDouble:
509  return (reinterpret_cast < const PackedDouble* >(value ()))->d != 0;
510  case NumberInt:
511  return *reinterpret_cast< const int* >( value() ) != 0;
512  case mongo::Bool:
513  return boolean();
514  case EOO:
515  case jstNULL:
516  case Undefined:
517  return false;
518 
519  default:
520  ;
521  }
522  return true;
523  }
524 
526  inline bool BSONElement::isNumber() const {
527  switch( type() ) {
528  case NumberLong:
529  case NumberDouble:
530  case NumberInt:
531  return true;
532  default:
533  return false;
534  }
535  }
536 
537  inline bool BSONElement::isSimpleType() const {
538  switch( type() ) {
539  case NumberLong:
540  case NumberDouble:
541  case NumberInt:
542  case mongo::String:
543  case mongo::Bool:
544  case mongo::Date:
545  case jstOID:
546  return true;
547  default:
548  return false;
549  }
550  }
551 
552  inline double BSONElement::numberDouble() const {
553  switch( type() ) {
554  case NumberDouble:
555  return _numberDouble();
556  case NumberInt:
557  return *reinterpret_cast< const int* >( value() );
558  case NumberLong:
559  return (double) *reinterpret_cast< const long long* >( value() );
560  default:
561  return 0;
562  }
563  }
564 
566  inline int BSONElement::numberInt() const {
567  switch( type() ) {
568  case NumberDouble:
569  return (int) _numberDouble();
570  case NumberInt:
571  return _numberInt();
572  case NumberLong:
573  return (int) _numberLong();
574  default:
575  return 0;
576  }
577  }
578 
580  inline long long BSONElement::numberLong() const {
581  switch( type() ) {
582  case NumberDouble:
583  return (long long) _numberDouble();
584  case NumberInt:
585  return _numberInt();
586  case NumberLong:
587  return _numberLong();
588  default:
589  return 0;
590  }
591  }
592 
598  inline long long BSONElement::safeNumberLong() const {
599  double d;
600  switch( type() ) {
601  case NumberDouble:
602  d = numberDouble();
603  if ( isNaN( d ) ){
604  return 0;
605  }
606  if ( d > (double) std::numeric_limits<long long>::max() ){
607  return std::numeric_limits<long long>::max();
608  }
609  if ( d < std::numeric_limits<long long>::min() ){
610  return std::numeric_limits<long long>::min();
611  }
612  default:
613  return numberLong();
614  }
615  }
616 
618  static char z = 0;
619  data = &z;
620  fieldNameSize_ = 0;
621  totalSize = 1;
622  }
623 
624 }
end of object
Definition: bsontypes.h:48
void Val(Date_t &v) const
populate v with the value of the element.
Definition: bsonelement.h:92
double _numberDouble() const
Return double value for this field.
Definition: bsonelement.h:201
Utility for creating a BSONObj.
Definition: bsonobjbuilder.h:52
int fieldNameSize() const
NOTE: size includes the NULL terminator.
Definition: bsonelement.h:151
JsonStringFormat
Formatting mode for generating JSON from BSON.
Definition: oid.h:152
bool isABSONObj() const
True if this element can be a BSONObj.
Definition: bsonelement.h:392
bool mayEncapsulate() const
True if this element may contain subobjects.
Definition: bsonelement.h:380
const char * valuestrsafe() const
Get the string value of the element.
Definition: bsonelement.h:260
std::string String() const
These functions, which start with a capital letter, throw a MsgAssertionException if the element is n...
Definition: bsonelement.h:69
double numberDouble() const
Retrieve the numeric value of the element.
Definition: bsonelement.h:552
BSONType type() const
Returns the type of the element.
Definition: bsonelement.h:112
long long safeNumberLong() const
Like numberLong() but with well-defined behavior for doubles that are NaNs, or too large/small to be ...
Definition: bsonelement.h:598
int numberInt() const
Retrieve int value for the element safely.
Definition: bsonelement.h:566
const char * fieldName() const
field name of the element.
Definition: bsonelement.h:143
LogstreamBuilder out()
Synonym for log().
Definition: log.h:79
BSONElement(const char *d, int fieldNameSize, FieldNameSizeTag)
Construct a BSONElement where you already know the length of the name.
Definition: bsonelement.h:467
bool ok() const
Use ok() to check if a value is assigned: if( myObj[&quot;foo&quot;].ok() ) ...
Definition: bsonelement.h:104
const char * regex() const
Retrieve the regex string for a Regex element.
Definition: bsonelement.h:339
const char * binDataClean(int &len) const
Get binary data.
Definition: bsonelement.h:319
Definition: bsonelement.h:460
bool trueValue() const
Convert the value to boolean, regardless of its type, in a javascript-like fashion (i...
Definition: bsonelement.h:503
Definition: time_support.h:34
long long numberLong() const
Retrieve long value for the element safely.
Definition: bsonelement.h:580
const char * binData(int &len) const
Get raw binary data.
Definition: bsonelement.h:312
bool isNull() const
True if element is null.
Definition: bsonelement.h:235
int codeWScopeCodeLen() const
Get length of the code part of the CodeWScope object This INCLUDES the null char at the end...
Definition: bsonelement.h:276
date type
Definition: bsontypes.h:66
const char * value() const
raw data of the element&#39;s value (so be careful).
Definition: bsonelement.h:162
boolean type
Definition: bsontypes.h:64
const mongo::OID & __oid() const
Retrieve the object ID stored in the object.
Definition: bsonelement.h:232
const char * valuestr() const
Get a string&#39;s value.
Definition: bsonelement.h:255
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:44
int valuesize() const
size in bytes of the element&#39;s value (when applicable).
Definition: bsonelement.h:166
ObjectId.
Definition: bsontypes.h:62
an embedded object
Definition: bsontypes.h:54
32 bit signed integer
Definition: bsontypes.h:80
double precision floating point value
Definition: bsontypes.h:50
null type
Definition: bsontypes.h:68
javascript code that can execute on the database server, with SavedContext
Definition: bsontypes.h:78
bool isNumber() const
True if element is of a numeric type.
Definition: bsonelement.h:526
Definition: optime.h:41
const char * codeWScopeCode() const
Get javascript code of a CodeWScope data element.
Definition: bsonelement.h:269
Undefined type.
Definition: bsontypes.h:60
iterator for a BSONObj
Definition: bsonobjiterator.h:37
bool operator!=(const BSONElement &r) const
Returns true if elements are unequal.
Definition: bsonelement.h:362
int canonicalType() const
See canonicalizeBSONType in bsontypes.h.
Definition: bsonelement.h:120
regular expression, a pattern with options
Definition: bsontypes.h:70
64 bit integer
Definition: bsontypes.h:84
an embedded array
Definition: bsontypes.h:56
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
deprecated / will be redesigned
Definition: bsontypes.h:72
BSONElement represents an &quot;element&quot; in a BSONObj.
Definition: bsonelement.h:62
bool operator==(const BSONElement &r) const
Returns true if elements are equal.
Definition: bsonelement.h:358
C++ representation of a &quot;BSON&quot; object – that is, an extended JSON-style object in a binary representa...
Definition: bsonobj.h:77
int valuestrsize() const
Size (length) of a string element.
Definition: bsonelement.h:243
bool boolean() const
Definition: bsonelement.h:175
bool operator<(const BSONElement &other) const
this does not use fieldName in the comparison, just the value
Definition: bsonelement.h:427
bool valuesEqual(const BSONElement &r) const
like operator== but doesn&#39;t check the fieldname, just the value.
Definition: bsonelement.h:353
int canonicalizeBSONType(BSONType type)
Returns a number for where a given type falls in the sort order.
Definition: bsontypes.h:116
Object ID type.
Definition: oid.h:42
const char * codeWScopeScopeDataUnsafe() const
Get the scope SavedContext of a CodeWScope data element.
Definition: bsonelement.h:288
binary data
Definition: bsontypes.h:58
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()
Constructs an empty element.
Definition: bsonelement.h:617
std::string str() const
Get the string value of the element.
Definition: bsonelement.h:264
bool isSimpleType() const
True if number, string, bool, date, OID.
Definition: bsonelement.h:537
character string, stored in utf8
Definition: bsontypes.h:52