MongoDB C++ Driver  legacy-1.0.3
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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/base/data_cursor.h"
25 #include "mongo/bson/bsontypes.h"
26 #include "mongo/bson/oid.h"
27 #include "mongo/bson/timestamp.h"
28 #include "mongo/client/export_macros.h"
29 #include "mongo/platform/cstdint.h"
30 #include "mongo/platform/float_utils.h"
31 #include "mongo/platform/strnlen.h"
32 
33 namespace mongo {
34  class BSONObj;
35  class BSONElement;
36  class BSONObjBuilder;
37 
38  /* l and r MUST have same type when called: check that first. */
39  int compareElementValues(const BSONElement& l, const BSONElement& r);
40 
41 
55  class MONGO_CLIENT_API BSONElement {
56  public:
62  std::string String() const { return chk(mongo::String).str(); }
63  const StringData checkAndGetStringData() const {
64  return chk(mongo::String).valueStringData();
65  }
66  Date_t Date() const { return chk(mongo::Date).date(); }
67  double Number() const { return chk(isNumber()).number(); }
68  double Double() const { return chk(NumberDouble)._numberDouble(); }
69  long long Long() const { return chk(NumberLong)._numberLong(); }
70  int Int() const { return chk(NumberInt)._numberInt(); }
71  bool Bool() const { return chk(mongo::Bool).boolean(); }
72  std::vector<BSONElement> Array() const; // see implementation for detailed comments
73  mongo::OID OID() const { return chk(jstOID).__oid(); }
74  void Null() const { chk(isNull()); } // throw MsgAssertionException if not null
75  void OK() const { chk(ok()); } // throw MsgAssertionException if element DNE
76  Timestamp_t Timestamp() const { return chk(mongo::Timestamp).timestamp(); }
77 
84  BSONObj Obj() const;
85 
89  void Val(Date_t& v) const { v = Date(); }
90  void Val(long long& v) const { v = Long(); }
91  void Val(bool& v) const { v = Bool(); }
92  void Val(BSONObj& v) const;
93  void Val(mongo::OID& v) const { v = OID(); }
94  void Val(int& v) const { v = Int(); }
95  void Val(double& v) const { v = Double(); }
96  void Val(std::string& v) const { v = String(); }
97 
101  bool ok() const { return !eoo(); }
102 
103  std::string toString( bool includeFieldName = true, bool full=false) const;
104  void toString(StringBuilder& s, bool includeFieldName = true, bool full=false, int depth=0) const;
105  std::string jsonString( JsonStringFormat format, bool includeFieldNames = true, int pretty = 0 ) const;
106  operator std::string() const { return toString(); }
107 
109  BSONType type() const {
110  const signed char typeByte = ConstDataView(data).readLE<signed char>();
111  return static_cast<BSONType>(typeByte);
112  }
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(), eoo() ? 0 : 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 Date_t(ConstDataView(value()).readLE<unsigned long long>());
187  }
188 
192  bool trueValue() const;
193 
195  bool isSimpleType() const;
196 
198  bool isNumber() const;
199 
201  double _numberDouble() const {
202  return ConstDataView(value()).readLE<double>();
203  }
204 
206  int _numberInt() const {
207  return ConstDataView(value()).readLE<int>();
208  }
209 
211  long long _numberLong() const {
212  return ConstDataView(value()).readLE<long long>();
213  }
214 
216  int numberInt() const;
220  long long numberLong() const;
221 
227  long long safeNumberLong() const;
228 
232  double numberDouble() const;
236  double number() const { return numberDouble(); }
237 
240  mongo::OID __oid() const {
241  return OID::from(value());
242  }
243 
245  bool isNull() const {
246  return type() == jstNULL;
247  }
248 
253  int valuestrsize() const {
254  return ConstDataView(value()).readLE<int>();
255  }
256 
257  // for objects the size *includes* the size of the size field
258  size_t objsize() const {
259  return ConstDataView(value()).readLE<uint32_t>();
260  }
261 
265  const char * valuestr() const {
266  return value() + 4;
267  }
268 
270  const char *valuestrsafe() const {
271  return type() == mongo::String ? valuestr() : "";
272  }
274  std::string str() const {
275  return type() == mongo::String ? std::string(valuestr(), valuestrsize()-1) : std::string();
276  }
277 
282  const StringData valueStringData() const {
283  return StringData(valuestr(), valuestrsize() - 1);
284  }
285 
287  const char * codeWScopeCode() const {
288  massert( 16177 , "not codeWScope" , type() == CodeWScope );
289  return value() + 4 + 4; //two ints precede code (see BSON spec)
290  }
291 
294  int codeWScopeCodeLen() const {
295  massert( 16178 , "not codeWScope" , type() == CodeWScope );
296  return ConstDataView(value() + 4).readLE<int>();
297  }
298 
306  const char * codeWScopeScopeDataUnsafe() const {
307  //This can error if there are null chars in the codeWScopeCode
308  return codeWScopeCode() + strlen( codeWScopeCode() ) + 1;
309  }
310 
311  /* Get the scope SavedContext of a CodeWScope data element.
312  *
313  * This is the corrected version of codeWScopeScopeDataUnsafe(),
314  * but note that existing uses might rely on the behavior of
315  * that function so be careful in choosing which version to use.
316  */
317  const char * codeWScopeScopeData() const {
318  return codeWScopeCode() + codeWScopeCodeLen();
319  }
320 
322  BSONObj embeddedObject() const;
323 
324  /* uasserts if not an object */
325  BSONObj embeddedObjectUserCheck() const;
326 
327  BSONObj codeWScopeObject() const;
328 
330  const char *binData(int& len) const {
331  // BinData: <int len> <byte subtype> <byte[len] data>
332  verify( type() == BinData );
333  len = valuestrsize();
334  return value() + 5;
335  }
337  const char *binDataClean(int& len) const {
338  // BinData: <int len> <byte subtype> <byte[len] data>
339  if (binDataType() != ByteArrayDeprecated) {
340  return binData(len);
341  }
342  else {
343  // Skip extra size
344  len = valuestrsize() - 4;
345  return value() + 5 + 4;
346  }
347  }
348 
349  BinDataType binDataType() const {
350  // BinData: <int len> <byte subtype> <byte[len] data>
351  verify( type() == BinData );
352  unsigned char c = (value() + 4)[0];
353  return (BinDataType)c;
354  }
355 
357  const char *regex() const {
358  verify(type() == RegEx);
359  return value();
360  }
361 
363  const char *regexFlags() const {
364  const char *p = regex();
365  return p + strlen(p) + 1;
366  }
367 
371  bool valuesEqual(const BSONElement& r) const {
372  return woCompare( r , false ) == 0;
373  }
374 
376  bool operator==(const BSONElement& r) const {
377  return woCompare( r , true ) == 0;
378  }
380  bool operator!=(const BSONElement& r) const { return !operator==(r); }
381 
387  int woCompare( const BSONElement &e, bool considerFieldName = true ) const;
388 
394  struct Hasher {
395  size_t operator() (const BSONElement& elem) const;
396  };
397 
398  const char * rawdata() const { return data; }
399 
401  int getGtLtOp( int def = 0 ) const;
402 
404  BSONElement();
405 
407  bool mayEncapsulate() const {
408  switch ( type() ) {
409  case Object:
410  case mongo::Array:
411  case CodeWScope:
412  return true;
413  default:
414  return false;
415  }
416  }
417 
419  bool isABSONObj() const {
420  switch( type() ) {
421  case Object:
422  case mongo::Array:
423  return true;
424  default:
425  return false;
426  }
427  }
428 
429  Timestamp_t timestamp() const {
430  ConstDataCursor cursor(value());
431  const uint32_t increment = cursor.readLEAndAdvance<uint32_t>();
432  const uint32_t seconds = cursor.readLE<uint32_t>();
433  return Timestamp_t(seconds, increment);
434  }
435 
436  const char * dbrefNS() const {
437  uassert( 10063 , "not a dbref" , type() == DBRef );
438  return value() + 4;
439  }
440 
441  const mongo::OID dbrefOID() const {
442  uassert( 10064 , "not a dbref" , type() == DBRef );
443  const char * start = value();
444  start += 4 + ConstDataView(start).readLE<int>();
445  return mongo::OID::from(start);
446  }
447 
449  bool operator<( const BSONElement& other ) const {
450  int x = (int)canonicalType() - (int)other.canonicalType();
451  if ( x < 0 ) return true;
452  else if ( x > 0 ) return false;
453  return compareElementValues(*this,other) < 0;
454  }
455 
456  // @param maxLen don't scan more than maxLen bytes
457  explicit BSONElement(const char *d, int maxLen) : data(d) {
458  if ( eoo() ) {
459  totalSize = 1;
460  fieldNameSize_ = 0;
461  }
462  else {
463  totalSize = -1;
464  fieldNameSize_ = -1;
465  if ( maxLen != -1 ) {
466  size_t size = strnlen( fieldName(), maxLen - 1 );
467  uassert( 10333 , "Invalid field name", size < size_t(maxLen - 1) );
468  fieldNameSize_ = size + 1;
469  }
470  }
471  }
472 
473  explicit BSONElement(const char *d) : data(d) {
474  fieldNameSize_ = -1;
475  totalSize = -1;
476  if ( eoo() ) {
477  fieldNameSize_ = 0;
478  totalSize = 1;
479  }
480  }
481 
482  struct FieldNameSizeTag {}; // For disambiguation with ctor taking 'maxLen' above.
483 
489  BSONElement(const char* d, int fieldNameSize, FieldNameSizeTag)
490  : data(d)
491  , fieldNameSize_(fieldNameSize) // internal size includes null terminator
492  , totalSize(-1) {
493  }
494 
495  std::string _asCode() const;
496 
497  template<typename T> bool coerce( T* out ) const;
498 
499  private:
500  const char *data;
501  mutable int fieldNameSize_; // cached value
502 
503  mutable int totalSize; /* caches the computed size */
504 
505  friend class BSONObjIterator;
506  friend class BSONObj;
507  const BSONElement& chk(int t) const {
508  if ( t != type() ) {
509  StringBuilder ss;
510  if( eoo() )
511  ss << "field not found, expected type " << t;
512  else
513  ss << "wrong type for field (" << fieldName() << ") " << type() << " != " << t;
514  msgasserted(13111, ss.str() );
515  }
516  return *this;
517  }
518  const BSONElement& chk(bool expr) const {
519  massert(13118, "unexpected or missing type value in BSON object", expr);
520  return *this;
521  }
522  };
523 
524  inline bool BSONElement::trueValue() const {
525  // NOTE Behavior changes must be replicated in Value::coerceToBool().
526  switch( type() ) {
527  case NumberLong:
528  return _numberLong() != 0;
529  case NumberDouble:
530  return _numberDouble() != 0;
531  case NumberInt:
532  return _numberInt() != 0;
533  case mongo::Bool:
534  return boolean();
535  case EOO:
536  case jstNULL:
537  case Undefined:
538  return false;
539 
540  default:
541  ;
542  }
543  return true;
544  }
545 
547  inline bool BSONElement::isNumber() const {
548  switch( type() ) {
549  case NumberLong:
550  case NumberDouble:
551  case NumberInt:
552  return true;
553  default:
554  return false;
555  }
556  }
557 
558  inline bool BSONElement::isSimpleType() const {
559  switch( type() ) {
560  case NumberLong:
561  case NumberDouble:
562  case NumberInt:
563  case mongo::String:
564  case mongo::Bool:
565  case mongo::Date:
566  case jstOID:
567  return true;
568  default:
569  return false;
570  }
571  }
572 
573  inline double BSONElement::numberDouble() const {
574  switch( type() ) {
575  case NumberDouble:
576  return _numberDouble();
577  case NumberInt:
578  return _numberInt();
579  case NumberLong:
580  return _numberLong();
581  default:
582  return 0;
583  }
584  }
585 
587  inline int BSONElement::numberInt() const {
588  switch( type() ) {
589  case NumberDouble:
590  return (int) _numberDouble();
591  case NumberInt:
592  return _numberInt();
593  case NumberLong:
594  return (int) _numberLong();
595  default:
596  return 0;
597  }
598  }
599 
601  inline long long BSONElement::numberLong() const {
602  switch( type() ) {
603  case NumberDouble:
604  return (long long) _numberDouble();
605  case NumberInt:
606  return _numberInt();
607  case NumberLong:
608  return _numberLong();
609  default:
610  return 0;
611  }
612  }
613 
619  inline long long BSONElement::safeNumberLong() const {
620  double d;
621  switch( type() ) {
622  case NumberDouble:
623  d = numberDouble();
624  if ( isNaN( d ) ){
625  return 0;
626  }
627  if ( d > (double) std::numeric_limits<long long>::max() ){
628  return std::numeric_limits<long long>::max();
629  }
630  if ( d < std::numeric_limits<long long>::min() ){
631  return std::numeric_limits<long long>::min();
632  }
633  default:
634  return numberLong();
635  }
636  }
637 
639  static const char kEooElement[] = "";
640  data = kEooElement;
641  fieldNameSize_ = 0;
642  totalSize = 1;
643  }
644 
645  // TODO(SERVER-14596): move to a better place; take a StringData.
646  std::string escape( const std::string& s , bool escape_slash=false);
647 
648 }
const char * codeWScopeCode() const
Get javascript code of a CodeWScope data element.
Definition: bsonelement.h:287
Definition: timestamp.h:23
end of object
Definition: bsontypes.h:42
bool boolean() const
Definition: bsonelement.h:175
JsonStringFormat
Formatting mode for generating JSON from BSON.
Definition: oid.h:204
bool mayEncapsulate() const
True if this element may contain subobjects.
Definition: bsonelement.h:407
const char * binDataClean(int &len) const
Get binary data.
Definition: bsonelement.h:337
const char * regex() const
Retrieve the regex string for a Regex element.
Definition: bsonelement.h:357
void Val(Date_t &v) const
populate v with the value of the element.
Definition: bsonelement.h:89
std::stringstream deals with locale so this is a lot faster than std::stringstream for UTF8 ...
Definition: builder.h:53
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:619
int numberInt() const
Retrieve int value for the element safely.
Definition: bsonelement.h:587
bool isSimpleType() const
True if number, string, bool, date, OID.
Definition: bsonelement.h:558
the main MongoDB namespace
Definition: bulk_operation_builder.h:24
Object ID type.
Definition: oid.h:60
bool operator<(const BSONElement &other) const
this does not use fieldName in the comparison, just the value
Definition: bsonelement.h:449
bool operator!=(const BSONElement &r) const
Returns true if elements are unequal.
Definition: bsonelement.h:380
Updated to a Date with value next OpTime on insert.
Definition: bsontypes.h:76
bool valuesEqual(const BSONElement &r) const
like operator== but doesn't check the fieldname, just the value.
Definition: bsonelement.h:371
bool isABSONObj() const
True if this element can be a BSONObj.
Definition: bsonelement.h:419
date type
Definition: bsontypes.h:60
boolean type
Definition: bsontypes.h:58
const char * regexFlags() const
Retrieve the regex flags (options) for a Regex element.
Definition: bsonelement.h:363
double _numberDouble() const
Return double value for this field.
Definition: bsonelement.h:201
const char * binData(int &len) const
Get raw binary data.
Definition: bsonelement.h:330
BSONType
the complete list of valid BSON types see also bsonspec.org
Definition: bsontypes.h:38
const char * value() const
raw data of the element's value (so be careful).
Definition: bsonelement.h:162
BSONType type() const
Returns the type of the element.
Definition: bsonelement.h:109
Definition: time_support.h:39
int canonicalType() const
See canonicalizeBSONType in bsontypes.h.
Definition: bsonelement.h:120
bool isNumber() const
True if element is of a numeric type.
Definition: bsonelement.h:547
int codeWScopeCodeLen() const
Get length of the code part of the CodeWScope object This INCLUDES the null char at the end...
Definition: bsonelement.h:294
ObjectId.
Definition: bsontypes.h:56
an embedded object
Definition: bsontypes.h:48
32 bit signed integer
Definition: bsontypes.h:74
double precision floating point value
Definition: bsontypes.h:44
double numberDouble() const
Retrieve the numeric value of the element.
Definition: bsonelement.h:573
null type
Definition: bsontypes.h:62
bool isNull() const
True if element is null.
Definition: bsonelement.h:245
javascript code that can execute on the database server, with SavedContext
Definition: bsontypes.h:72
const char * codeWScopeScopeDataUnsafe() const
Get the scope SavedContext of a CodeWScope data element.
Definition: bsonelement.h:306
const StringData valueStringData() const
Returns a StringData pointing into this element's data.
Definition: bsonelement.h:282
iterator for a BSONObj
Definition: bsonobjiterator.h:37
const char * valuestr() const
Get a string's value.
Definition: bsonelement.h:265
int fieldNameSize() const
NOTE: size includes the NULL terminator.
Definition: bsonelement.h:151
std::string String() const
These functions, which start with a capital letter, throw a MsgAssertionException if the element is n...
Definition: bsonelement.h:62
BSONElement()
Constructs an empty element.
Definition: bsonelement.h:638
mongo::OID __oid() const
Retrieve the object ID stored in the object.
Definition: bsonelement.h:240
bool ok() const
Use ok() to check if a value is assigned: if( myObj["foo"].ok() ) ...
Definition: bsonelement.h:101
long long _numberLong() const
Return long long value for this field.
Definition: bsonelement.h:211
int valuesize() const
size in bytes of the element's value (when applicable).
Definition: bsonelement.h:166
Undefined type.
Definition: bsontypes.h:54
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
bool trueValue() const
Convert the value to boolean, regardless of its type, in a javascript-like fashion (i...
Definition: bsonelement.h:524
Date_t date() const
Retrieve a java style date value from the element.
Definition: bsonelement.h:185
regular expression, a pattern with options
Definition: bsontypes.h:64
64 bit integer
Definition: bsontypes.h:78
double number() const
Retrieve the numeric value of the element.
Definition: bsonelement.h:236
an embedded array
Definition: bsontypes.h:50
const char * valuestrsafe() const
Get the string value of the element.
Definition: bsonelement.h:270
Functor compatible with std::hash for std::unordered_{map,set} Warning: The hash function is subject ...
Definition: bsonelement.h:394
BSONElement represents an "element" in a BSONObj.
Definition: bsonelement.h:55
deprecated / will be redesigned
Definition: bsontypes.h:66
int _numberInt() const
Return int value for this field.
Definition: bsonelement.h:206
const char * fieldName() const
field name of the element.
Definition: bsonelement.h:143
Definition: bsonelement.h:482
BSONElement(const char *d, int fieldNameSize, FieldNameSizeTag)
Construct a BSONElement where you already know the length of the name.
Definition: bsonelement.h:489
int valuestrsize() const
Size (length) of a string element.
Definition: bsonelement.h:253
std::string str() const
Get the string value of the element.
Definition: bsonelement.h:274
bool operator==(const BSONElement &r) const
Returns true if elements are equal.
Definition: bsonelement.h:376
int canonicalizeBSONType(BSONType type)
Returns a number for where a given type falls in the sort order.
Definition: bsontypes.h:109
binary data
Definition: bsontypes.h:52
C++ representation of a "BSON" object – that is, an extended JSON-style object in a binary represent...
Definition: bsonobj.h:78
long long numberLong() const
Retrieve long value for the element safely.
Definition: bsonelement.h:601
character string, stored in utf8
Definition: bsontypes.h:46