MongoDB C++ Driver  legacy-1.1.2
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 {
63  return chk(mongo::String).str();
64  }
65  const StringData checkAndGetStringData() const {
66  return chk(mongo::String).valueStringData();
67  }
68  Date_t Date() const {
69  return chk(mongo::Date).date();
70  }
71  double Number() const {
72  return chk(isNumber()).number();
73  }
74  double Double() const {
75  return chk(NumberDouble)._numberDouble();
76  }
77  long long Long() const {
78  return chk(NumberLong)._numberLong();
79  }
80  int Int() const {
81  return chk(NumberInt)._numberInt();
82  }
83  bool Bool() const {
84  return chk(mongo::Bool).boolean();
85  }
86  std::vector<BSONElement> Array() const; // see implementation for detailed comments
87  mongo::OID OID() const {
88  return chk(jstOID).__oid();
89  }
90  void Null() const {
91  chk(isNull());
92  } // throw MsgAssertionException if not null
93  void OK() const {
94  chk(ok());
95  } // throw MsgAssertionException if element DNE
96  Timestamp_t Timestamp() const {
97  return chk(mongo::Timestamp).timestamp();
98  }
99 
106  BSONObj Obj() const;
107 
111  void Val(Date_t& v) const {
112  v = Date();
113  }
114  void Val(long long& v) const {
115  v = Long();
116  }
117  void Val(bool& v) const {
118  v = Bool();
119  }
120  void Val(BSONObj& v) const;
121  void Val(mongo::OID& v) const {
122  v = OID();
123  }
124  void Val(int& v) const {
125  v = Int();
126  }
127  void Val(double& v) const {
128  v = Double();
129  }
130  void Val(std::string& v) const {
131  v = String();
132  }
133 
137  bool ok() const {
138  return !eoo();
139  }
140 
141  std::string toString(bool includeFieldName = true, bool full = false) const;
142  void toString(StringBuilder& s,
143  bool includeFieldName = true,
144  bool full = false,
145  int depth = 0) const;
146  std::string jsonString(JsonStringFormat format,
147  bool includeFieldNames = true,
148  int pretty = 0) const;
149  operator std::string() const {
150  return toString();
151  }
152 
154  BSONType type() const {
155  const signed char typeByte = ConstDataView(data).readLE<signed char>();
156  return static_cast<BSONType>(typeByte);
157  }
158 
162  BSONElement operator[](const std::string& field) const;
163 
165  int canonicalType() const {
166  return canonicalizeBSONType(type());
167  }
168 
172  bool eoo() const {
173  return type() == EOO;
174  }
175 
179  int size(int maxLen) const;
180  int size() const;
181 
183  BSONObj wrap() const;
184 
186  BSONObj wrap(const StringData& newName) const;
187 
192  const char* fieldName() const {
193  if (eoo())
194  return ""; // no fieldname for it.
195  return data + 1;
196  }
197 
201  int fieldNameSize() const {
202  if (fieldNameSize_ == -1)
203  fieldNameSize_ = (int)strlen(fieldName()) + 1;
204  return fieldNameSize_;
205  }
206 
207  const StringData fieldNameStringData() const {
208  return StringData(fieldName(), eoo() ? 0 : fieldNameSize() - 1);
209  }
210 
212  const char* value() const {
213  return (data + fieldNameSize() + 1);
214  }
216  int valuesize() const {
217  return size() - fieldNameSize() - 1;
218  }
219 
220  bool isBoolean() const {
221  return type() == mongo::Bool;
222  }
223 
227  bool boolean() const {
228  return *value() ? true : false;
229  }
230 
231  bool booleanSafe() const {
232  return isBoolean() && boolean();
233  }
234 
239  Date_t date() const {
240  return Date_t(ConstDataView(value()).readLE<unsigned long long>());
241  }
242 
246  bool trueValue() const;
247 
249  bool isSimpleType() const;
250 
252  bool isNumber() const;
253 
255  double _numberDouble() const {
256  return ConstDataView(value()).readLE<double>();
257  }
258 
260  int _numberInt() const {
261  return ConstDataView(value()).readLE<int>();
262  }
263 
265  long long _numberLong() const {
266  return ConstDataView(value()).readLE<long long>();
267  }
268 
270  int numberInt() const;
274  long long numberLong() const;
275 
281  long long safeNumberLong() const;
282 
286  double numberDouble() const;
290  double number() const {
291  return numberDouble();
292  }
293 
296  mongo::OID __oid() const {
297  return OID::from(value());
298  }
299 
301  bool isNull() const {
302  return type() == jstNULL;
303  }
304 
309  int valuestrsize() const {
310  return ConstDataView(value()).readLE<int>();
311  }
312 
313  // for objects the size *includes* the size of the size field
314  size_t objsize() const {
315  return ConstDataView(value()).readLE<uint32_t>();
316  }
317 
321  const char* valuestr() const {
322  return value() + 4;
323  }
324 
326  const char* valuestrsafe() const {
327  return type() == mongo::String ? valuestr() : "";
328  }
330  std::string str() const {
331  return type() == mongo::String ? std::string(valuestr(), valuestrsize() - 1)
332  : std::string();
333  }
334 
339  const StringData valueStringData() const {
340  return StringData(valuestr(), valuestrsize() - 1);
341  }
342 
344  const char* codeWScopeCode() const {
345  massert(16177, "not codeWScope", type() == CodeWScope);
346  return value() + 4 + 4; // two ints precede code (see BSON spec)
347  }
348 
351  int codeWScopeCodeLen() const {
352  massert(16178, "not codeWScope", type() == CodeWScope);
353  return ConstDataView(value() + 4).readLE<int>();
354  }
355 
363  const char* codeWScopeScopeDataUnsafe() const {
364  // This can error if there are null chars in the codeWScopeCode
365  return codeWScopeCode() + strlen(codeWScopeCode()) + 1;
366  }
367 
368  /* Get the scope SavedContext of a CodeWScope data element.
369  *
370  * This is the corrected version of codeWScopeScopeDataUnsafe(),
371  * but note that existing uses might rely on the behavior of
372  * that function so be careful in choosing which version to use.
373  */
374  const char* codeWScopeScopeData() const {
375  return codeWScopeCode() + codeWScopeCodeLen();
376  }
377 
379  BSONObj embeddedObject() const;
380 
381  /* uasserts if not an object */
382  BSONObj embeddedObjectUserCheck() const;
383 
384  BSONObj codeWScopeObject() const;
385 
387  const char* binData(int& len) const {
388  // BinData: <int len> <byte subtype> <byte[len] data>
389  verify(type() == BinData);
390  len = valuestrsize();
391  return value() + 5;
392  }
394  const char* binDataClean(int& len) const {
395  // BinData: <int len> <byte subtype> <byte[len] data>
396  if (binDataType() != ByteArrayDeprecated) {
397  return binData(len);
398  } else {
399  // Skip extra size
400  len = valuestrsize() - 4;
401  return value() + 5 + 4;
402  }
403  }
404 
405  BinDataType binDataType() const {
406  // BinData: <int len> <byte subtype> <byte[len] data>
407  verify(type() == BinData);
408  unsigned char c = (value() + 4)[0];
409  return (BinDataType)c;
410  }
411 
413  const char* regex() const {
414  verify(type() == RegEx);
415  return value();
416  }
417 
419  const char* regexFlags() const {
420  const char* p = regex();
421  return p + strlen(p) + 1;
422  }
423 
427  bool valuesEqual(const BSONElement& r) const {
428  return woCompare(r, false) == 0;
429  }
430 
432  bool operator==(const BSONElement& r) const {
433  return woCompare(r, true) == 0;
434  }
436  bool operator!=(const BSONElement& r) const {
437  return !operator==(r);
438  }
439 
445  int woCompare(const BSONElement& e, bool considerFieldName = true) const;
446 
452  struct Hasher {
453  size_t operator()(const BSONElement& elem) const;
454  };
455 
456  const char* rawdata() const {
457  return data;
458  }
459 
461  int getGtLtOp(int def = 0) const;
462 
464  BSONElement();
465 
467  bool mayEncapsulate() const {
468  switch (type()) {
469  case Object:
470  case mongo::Array:
471  case CodeWScope:
472  return true;
473  default:
474  return false;
475  }
476  }
477 
479  bool isABSONObj() const {
480  switch (type()) {
481  case Object:
482  case mongo::Array:
483  return true;
484  default:
485  return false;
486  }
487  }
488 
489  Timestamp_t timestamp() const {
490  ConstDataCursor cursor(value());
491  const uint32_t increment = cursor.readLEAndAdvance<uint32_t>();
492  const uint32_t seconds = cursor.readLE<uint32_t>();
493  return Timestamp_t(seconds, increment);
494  }
495 
496  const char* dbrefNS() const {
497  uassert(10063, "not a dbref", type() == DBRef);
498  return value() + 4;
499  }
500 
501  const mongo::OID dbrefOID() const {
502  uassert(10064, "not a dbref", type() == DBRef);
503  const char* start = value();
504  start += 4 + ConstDataView(start).readLE<int>();
505  return mongo::OID::from(start);
506  }
507 
509  bool operator<(const BSONElement& other) const {
510  int x = (int)canonicalType() - (int)other.canonicalType();
511  if (x < 0)
512  return true;
513  else if (x > 0)
514  return false;
515  return compareElementValues(*this, other) < 0;
516  }
517 
518  // @param maxLen don't scan more than maxLen bytes
519  explicit BSONElement(const char* d, int maxLen) : data(d) {
520  if (eoo()) {
521  totalSize = 1;
522  fieldNameSize_ = 0;
523  } else {
524  totalSize = -1;
525  fieldNameSize_ = -1;
526  if (maxLen != -1) {
527  size_t size = strnlen(fieldName(), maxLen - 1);
528  uassert(10333, "Invalid field name", size < size_t(maxLen - 1));
529  fieldNameSize_ = size + 1;
530  }
531  }
532  }
533 
534  explicit BSONElement(const char* d) : data(d) {
535  fieldNameSize_ = -1;
536  totalSize = -1;
537  if (eoo()) {
538  fieldNameSize_ = 0;
539  totalSize = 1;
540  }
541  }
542 
543  struct FieldNameSizeTag {}; // For disambiguation with ctor taking 'maxLen' above.
544 
550  BSONElement(const char* d, int fieldNameSize, FieldNameSizeTag)
551  : data(d),
552  fieldNameSize_(fieldNameSize) // internal size includes null terminator
553  ,
554  totalSize(-1) {}
555 
556  std::string _asCode() const;
557 
558  template <typename T>
559  bool coerce(T* out) const;
560 
561 private:
562  const char* data;
563  mutable int fieldNameSize_; // cached value
564 
565  mutable int totalSize; /* caches the computed size */
566 
567  friend class BSONObjIterator;
568  friend class BSONObj;
569  const BSONElement& chk(int t) const {
570  if (t != type()) {
571  StringBuilder ss;
572  if (eoo())
573  ss << "field not found, expected type " << t;
574  else
575  ss << "wrong type for field (" << fieldName() << ") " << type() << " != " << t;
576  msgasserted(13111, ss.str());
577  }
578  return *this;
579  }
580  const BSONElement& chk(bool expr) const {
581  massert(13118, "unexpected or missing type value in BSON object", expr);
582  return *this;
583  }
584 };
585 
586 inline bool BSONElement::trueValue() const {
587  // NOTE Behavior changes must be replicated in Value::coerceToBool().
588  switch (type()) {
589  case NumberLong:
590  return _numberLong() != 0;
591  case NumberDouble:
592  return _numberDouble() != 0;
593  case NumberInt:
594  return _numberInt() != 0;
595  case mongo::Bool:
596  return boolean();
597  case EOO:
598  case jstNULL:
599  case Undefined:
600  return false;
601 
602  default:
603  ;
604  }
605  return true;
606 }
607 
609 inline bool BSONElement::isNumber() const {
610  switch (type()) {
611  case NumberLong:
612  case NumberDouble:
613  case NumberInt:
614  return true;
615  default:
616  return false;
617  }
618 }
619 
620 inline bool BSONElement::isSimpleType() const {
621  switch (type()) {
622  case NumberLong:
623  case NumberDouble:
624  case NumberInt:
625  case mongo::String:
626  case mongo::Bool:
627  case mongo::Date:
628  case jstOID:
629  return true;
630  default:
631  return false;
632  }
633 }
634 
635 inline double BSONElement::numberDouble() const {
636  switch (type()) {
637  case NumberDouble:
638  return _numberDouble();
639  case NumberInt:
640  return _numberInt();
641  case NumberLong:
642  return _numberLong();
643  default:
644  return 0;
645  }
646 }
647 
650 inline int BSONElement::numberInt() const {
651  switch (type()) {
652  case NumberDouble:
653  return (int)_numberDouble();
654  case NumberInt:
655  return _numberInt();
656  case NumberLong:
657  return (int)_numberLong();
658  default:
659  return 0;
660  }
661 }
662 
664 inline long long BSONElement::numberLong() const {
665  switch (type()) {
666  case NumberDouble:
667  return (long long)_numberDouble();
668  case NumberInt:
669  return _numberInt();
670  case NumberLong:
671  return _numberLong();
672  default:
673  return 0;
674  }
675 }
676 
682 inline long long BSONElement::safeNumberLong() const {
683  double d;
684  switch (type()) {
685  case NumberDouble:
686  d = numberDouble();
687  if (isNaN(d)) {
688  return 0;
689  }
690  if (d > (double)std::numeric_limits<long long>::max()) {
691  return std::numeric_limits<long long>::max();
692  }
693  if (d < std::numeric_limits<long long>::min()) {
694  return std::numeric_limits<long long>::min();
695  }
696  default:
697  return numberLong();
698  }
699 }
700 
702  static const char kEooElement[] = "";
703  data = kEooElement;
704  fieldNameSize_ = 0;
705  totalSize = 1;
706 }
707 
708 // TODO(SERVER-14596): move to a better place; take a StringData.
709 std::string escape(const std::string& s, bool escape_slash = false);
710 }
const char * codeWScopeCode() const
Get javascript code of a CodeWScope data element.
Definition: bsonelement.h:344
Definition: timestamp.h:23
end of object
Definition: bsontypes.h:42
bool boolean() const
Definition: bsonelement.h:227
JsonStringFormat
Formatting mode for generating JSON from BSON.
Definition: oid.h:205
bool mayEncapsulate() const
True if this element may contain subobjects.
Definition: bsonelement.h:467
const char * binDataClean(int &len) const
Get binary data.
Definition: bsonelement.h:394
const char * regex() const
Retrieve the regex string for a Regex element.
Definition: bsonelement.h:413
void Val(Date_t &v) const
populate v with the value of the element.
Definition: bsonelement.h:111
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:682
int numberInt() const
Retrieve int value for the element safely.
Definition: bsonelement.h:650
bool isSimpleType() const
True if number, string, bool, date, OID.
Definition: bsonelement.h:620
A StringData object wraps a 'const string&' or a 'const char*' without copying its contents...
Definition: string_data.h:43
Utility functions for parsing numbers from strings.
Definition: compare_numbers.h:20
Object ID type.
Definition: oid.h:60
Definition: data_view.h:30
bool operator<(const BSONElement &other) const
this does not use fieldName in the comparison, just the value
Definition: bsonelement.h:509
Definition: data_cursor.h:26
bool operator!=(const BSONElement &r) const
Returns true if elements are unequal.
Definition: bsonelement.h:436
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:427
bool isABSONObj() const
True if this element can be a BSONObj.
Definition: bsonelement.h:479
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:419
double _numberDouble() const
Return double value for this field.
Definition: bsonelement.h:255
const char * binData(int &len) const
Get raw binary data.
Definition: bsonelement.h:387
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:212
BSONType type() const
Returns the type of the element.
Definition: bsonelement.h:154
Definition: time_support.h:39
int canonicalType() const
See canonicalizeBSONType in bsontypes.h.
Definition: bsonelement.h:165
bool isNumber() const
True if element is of a numeric type.
Definition: bsonelement.h:609
int codeWScopeCodeLen() const
Get length of the code part of the CodeWScope object This INCLUDES the null char at the end...
Definition: bsonelement.h:351
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:635
null type
Definition: bsontypes.h:62
bool isNull() const
True if element is null.
Definition: bsonelement.h:301
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:363
const StringData valueStringData() const
Returns a StringData pointing into this element's data.
Definition: bsonelement.h:339
iterator for a BSONObj
Definition: bsonobjiterator.h:37
const char * valuestr() const
Get a string's value.
Definition: bsonelement.h:321
int fieldNameSize() const
NOTE: size includes the NULL terminator.
Definition: bsonelement.h:201
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:701
mongo::OID __oid() const
Retrieve the object ID stored in the object.
Definition: bsonelement.h:296
bool ok() const
Use ok() to check if a value is assigned: if( myObj["foo"].ok() ) ...
Definition: bsonelement.h:137
long long _numberLong() const
Return long long value for this field.
Definition: bsonelement.h:265
int valuesize() const
size in bytes of the element's value (when applicable).
Definition: bsonelement.h:216
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:172
bool trueValue() const
Convert the value to boolean, regardless of its type, in a javascript-like fashion (i...
Definition: bsonelement.h:586
Date_t date() const
Retrieve a java style date value from the element.
Definition: bsonelement.h:239
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:290
an embedded array
Definition: bsontypes.h:50
const char * valuestrsafe() const
Get the string value of the element.
Definition: bsonelement.h:326
Functor compatible with std::hash for std::unordered_{map,set} Warning: The hash function is subject ...
Definition: bsonelement.h:452
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:260
const char * fieldName() const
field name of the element.
Definition: bsonelement.h:192
Definition: bsonelement.h:543
BSONElement(const char *d, int fieldNameSize, FieldNameSizeTag)
Construct a BSONElement where you already know the length of the name.
Definition: bsonelement.h:550
int valuestrsize() const
Size (length) of a string element.
Definition: bsonelement.h:309
std::string str() const
Get the string value of the element.
Definition: bsonelement.h:330
bool operator==(const BSONElement &r) const
Returns true if elements are equal.
Definition: bsonelement.h:432
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:664
character string, stored in utf8
Definition: bsontypes.h:46