1 // bsonelement.h
2 
3 
4 /**
5  *    Copyright (C) 2018-present MongoDB, Inc.
6  *
7  *    This program is free software: you can redistribute it and/or modify
8  *    it under the terms of the Server Side Public License, version 1,
9  *    as published by MongoDB, Inc.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    Server Side Public License for more details.
15  *
16  *    You should have received a copy of the Server Side Public License
17  *    along with this program. If not, see
18  *    <http://www.mongodb.com/licensing/server-side-public-license>.
19  *
20  *    As a special exception, the copyright holders give permission to link the
21  *    code of portions of this program with the OpenSSL library under certain
22  *    conditions as described in each individual source file and distribute
23  *    linked combinations including the program with the OpenSSL library. You
24  *    must comply with the Server Side Public License in all respects for
25  *    all of the code used other than as permitted herein. If you modify file(s)
26  *    with this exception, you may extend this exception to your version of the
27  *    file(s), but you are not obligated to do so. If you do not wish to do so,
28  *    delete this exception statement from your version. If you delete this
29  *    exception statement from all source files in the program, then also delete
30  *    it in the license file.
31  */
32 
33 #pragma once
34 
35 #include <cmath>
36 #include <cstdint>
37 #include <string.h>  // strlen
38 #include <string>
39 #include <vector>
40 
41 #include "mongo/base/data_range.h"
42 #include "mongo/base/data_type_endian.h"
43 #include "mongo/base/data_view.h"
44 #include "mongo/base/string_data_comparator_interface.h"
45 #include "mongo/bson/bson_comparator_interface_base.h"
46 #include "mongo/bson/bsontypes.h"
47 #include "mongo/bson/oid.h"
48 #include "mongo/bson/timestamp.h"
49 #include "mongo/config.h"
50 #include "mongo/platform/decimal128.h"
51 #include "mongo/platform/strnlen.h"
52 
53 namespace mongo {
54 class BSONObj;
55 class BSONElement;
56 class BSONObjBuilder;
57 class Timestamp;
58 
59 typedef BSONElement be;
60 typedef BSONObj bo;
61 typedef BSONObjBuilder bob;
62 
63 /** BSONElement represents an "element" in a BSONObj.  So for the object { a : 3, b : "abc" },
64     'a : 3' is the first element (key+value).
65 
66     The BSONElement object points into the BSONObj's data.  Thus the BSONObj must stay in scope
67     for the life of the BSONElement.
68 
69     internals:
70     <type><fieldName    ><value>
71     -------- size() ------------
72     -fieldNameSize-
73     value()
74     type()
75 */
76 class BSONElement {
77 public:
78     // Declared in bsonobj_comparator_interface.h.
79     class ComparatorInterface;
80 
81     /**
82      * Operator overloads for relops return a DeferredComparison which can subsequently be evaluated
83      * by a BSONObj::ComparatorInterface.
84      */
85     using DeferredComparison = BSONComparatorInterfaceBase<BSONElement>::DeferredComparison;
86 
87     /**
88      * Set of rules that dictate the behavior of the comparison APIs.
89      */
90     using ComparisonRules = BSONComparatorInterfaceBase<BSONElement>::ComparisonRules;
91     using ComparisonRulesSet = BSONComparatorInterfaceBase<BSONElement>::ComparisonRulesSet;
92 
93     /**
94      * Compares two BSON elements of the same canonical type.
95      *
96      * Returns <0 if 'l' is less than the element 'r'.
97      *         >0 if 'l' is greater than the element 'r'.
98      *          0 if 'l' is equal to the element 'r'.
99      */
100     static int compareElements(const BSONElement& l,
101                                const BSONElement& r,
102                                ComparisonRulesSet rules,
103                                const StringData::ComparatorInterface* comparator);
104 
105 
106     /** These functions, which start with a capital letter, throw if the
107         element is not of the required type. Example:
108 
109         std::string foo = obj["foo"].String(); // std::exception if not a std::string type or DNE
110     */
String()111     std::string String() const {
112         return chk(mongo::String).str();
113     }
checkAndGetStringData()114     const StringData checkAndGetStringData() const {
115         return chk(mongo::String).valueStringData();
116     }
Date()117     Date_t Date() const {
118         return chk(mongo::Date).date();
119     }
Number()120     double Number() const {
121         uassert(13118,
122                 str::stream() << "expected " << fieldName()
123                               << " to have a numeric type, but it is a "
124                               << type(),
125                 isNumber());
126         return number();
127     }
Decimal()128     Decimal128 Decimal() const {
129         return chk(NumberDecimal)._numberDecimal();
130     }
Double()131     double Double() const {
132         return chk(NumberDouble)._numberDouble();
133     }
Long()134     long long Long() const {
135         return chk(NumberLong)._numberLong();
136     }
Int()137     int Int() const {
138         return chk(NumberInt)._numberInt();
139     }
Bool()140     bool Bool() const {
141         return chk(mongo::Bool).boolean();
142     }
143     std::vector<BSONElement> Array() const;  // see implementation for detailed comments
OID()144     mongo::OID OID() const {
145         return chk(jstOID).__oid();
146     }
147 
148     /** @return the embedded object associated with this field.
149         Note the returned object is a reference to within the parent bson object. If that
150         object is out of scope, this pointer will no longer be valid. Call getOwned() on the
151         returned BSONObj if you need your own copy.
152         throws AssertionException if the element is not of type object.
153     */
154     BSONObj Obj() const;
155 
156     /** populate v with the value of the element.  If type does not match, throw exception.
157         useful in templates -- see also BSONObj::Vals().
158     */
Val(Date_t & v)159     void Val(Date_t& v) const {
160         v = Date();
161     }
Val(long long & v)162     void Val(long long& v) const {
163         v = Long();
164     }
Val(Decimal128 & v)165     void Val(Decimal128& v) const {
166         v = Decimal();
167     }
Val(bool & v)168     void Val(bool& v) const {
169         v = Bool();
170     }
171     void Val(BSONObj& v) const;
Val(mongo::OID & v)172     void Val(mongo::OID& v) const {
173         v = OID();
174     }
Val(int & v)175     void Val(int& v) const {
176         v = Int();
177     }
Val(double & v)178     void Val(double& v) const {
179         v = Double();
180     }
Val(std::string & v)181     void Val(std::string& v) const {
182         v = String();
183     }
184 
185     /** Use ok() to check if a value is assigned:
186         if( myObj["foo"].ok() ) ...
187     */
ok()188     bool ok() const {
189         return !eoo();
190     }
191 
192     /**
193      * True if this element has a value (ie not EOO).
194      *
195      * Makes it easier to check for a field's existence and use it:
196      * if (auto elem = myObj["foo"]) {
197      *     // Use elem
198      * }
199      * else {
200      *     // default behavior
201      * }
202      */
203     explicit operator bool() const {
204         return ok();
205     }
206 
207     std::string toString(bool includeFieldName = true, bool full = false) const;
208     void toString(StringBuilder& s,
209                   bool includeFieldName = true,
210                   bool full = false,
211                   bool redactValues = false,
212                   int depth = 0) const;
213     std::string jsonString(JsonStringFormat format,
214                            bool includeFieldNames = true,
215                            int pretty = 0) const;
string()216     operator std::string() const {
217         return toString();
218     }
219 
220     /** Returns the type of the element */
type()221     BSONType type() const {
222         const signed char typeByte = ConstDataView(data).read<signed char>();
223         return static_cast<BSONType>(typeByte);
224     }
225 
226     /** retrieve a field within this element
227         throws exception if *this is not an embedded object
228     */
229     BSONElement operator[](StringData field) const;
230 
231     /** See canonicalizeBSONType in bsontypes.h */
canonicalType()232     int canonicalType() const {
233         return canonicalizeBSONType(type());
234     }
235 
236     /** Indicates if it is the end-of-object element, which is present at the end of
237         every BSON object.
238     */
eoo()239     bool eoo() const {
240         return type() == EOO;
241     }
242 
243     /**
244      * Size of the element.
245      */
size()246     int size() const {
247         return totalSize;
248     }
249 
250     /** Wrap this element up as a singleton object. */
251     BSONObj wrap() const;
252 
253     /** Wrap this element up as a singleton object with a new name. */
254     BSONObj wrap(StringData newName) const;
255 
256     /** field name of the element.  e.g., for
257         name : "Joe"
258         "name" is the fieldname
259     */
fieldName()260     const char* fieldName() const {
261         if (eoo())
262             return "";  // no fieldname for it.
263         return data + 1;
264     }
265 
266     /**
267      * NOTE: size includes the NULL terminator.
268      */
fieldNameSize()269     int fieldNameSize() const {
270         return fieldNameSize_;
271     }
272 
fieldNameStringData()273     const StringData fieldNameStringData() const {
274         return StringData(fieldName(), eoo() ? 0 : fieldNameSize() - 1);
275     }
276 
277     /** raw data of the element's value (so be careful). */
value()278     const char* value() const {
279         return (data + fieldNameSize() + 1);
280     }
281     /** size in bytes of the element's value (when applicable). */
valuesize()282     int valuesize() const {
283         return size() - fieldNameSize() - 1;
284     }
285 
isBoolean()286     bool isBoolean() const {
287         return type() == mongo::Bool;
288     }
289 
290     /** @return value of a boolean element.
291         You must assure element is a boolean before
292         calling. */
boolean()293     bool boolean() const {
294         return *value() ? true : false;
295     }
296 
booleanSafe()297     bool booleanSafe() const {
298         return isBoolean() && boolean();
299     }
300 
301     /** Retrieve a java style date value from the element.
302         Ensure element is of type Date before calling.
303         @see Bool(), trueValue()
304     */
date()305     Date_t date() const {
306         return Date_t::fromMillisSinceEpoch(ConstDataView(value()).read<LittleEndian<long long>>());
307     }
308 
309     /** Convert the value to boolean, regardless of its type, in a javascript-like fashion
310         (i.e., treats zero and null and eoo as false).
311     */
312     bool trueValue() const;
313 
314     /** True if element is of a numeric type. */
315     bool isNumber() const;
316 
317     /** Return double value for this field. MUST be NumberDouble type. */
_numberDouble()318     double _numberDouble() const {
319         return ConstDataView(value()).read<LittleEndian<double>>();
320     }
321 
322     /** Return int value for this field. MUST be NumberInt type. */
_numberInt()323     int _numberInt() const {
324         return ConstDataView(value()).read<LittleEndian<int>>();
325     }
326 
327     /** Return decimal128 value for this field. MUST be NumberDecimal type. */
_numberDecimal()328     Decimal128 _numberDecimal() const {
329         uint64_t low = ConstDataView(value()).read<LittleEndian<long long>>();
330         uint64_t high = ConstDataView(value() + sizeof(long long)).read<LittleEndian<long long>>();
331         return Decimal128(Decimal128::Value({low, high}));
332     }
333 
334     /** Return long long value for this field. MUST be NumberLong type. */
_numberLong()335     long long _numberLong() const {
336         return ConstDataView(value()).read<LittleEndian<long long>>();
337     }
338 
339     /** Retrieve int value for the element safely.  Zero returned if not a number. */
340     int numberInt() const;
341     /** Retrieve long value for the element safely.  Zero returned if not a number.
342      *  Behavior is not defined for double values that are NaNs, or too large/small
343      *  to be represented by long longs */
344     long long numberLong() const;
345 
346     /** Like numberLong() but with well-defined behavior for doubles that
347      *  are NaNs, or too large/small to be represented as long longs.
348      *  NaNs -> 0
349      *  very large doubles -> LLONG_MAX
350      *  very small doubles -> LLONG_MIN  */
351     long long safeNumberLong() const;
352 
353     /** Retrieve decimal value for the element safely. */
354     Decimal128 numberDecimal() const;
355 
356     /** Retrieve the numeric value of the element.  If not of a numeric type, returns 0.
357         Note: casts to double, data loss may occur with large (>52 bit) NumberLong values.
358     */
359     double numberDouble() const;
360     /** Retrieve the numeric value of the element.  If not of a numeric type, returns 0.
361         Note: casts to double, data loss may occur with large (>52 bit) NumberLong values.
362     */
number()363     double number() const {
364         return numberDouble();
365     }
366 
367     /** Retrieve the object ID stored in the object.
368         You must ensure the element is of type jstOID first. */
__oid()369     mongo::OID __oid() const {
370         return OID::from(value());
371     }
372 
373     /** True if element is null. */
isNull()374     bool isNull() const {
375         return type() == jstNULL;
376     }
377 
378     /** Size (length) of a std::string element.
379         You must assure of type std::string first.
380         @return std::string size including terminating null
381     */
valuestrsize()382     int valuestrsize() const {
383         return ConstDataView(value()).read<LittleEndian<int>>();
384     }
385 
386     // for objects the size *includes* the size of the size field
objsize()387     size_t objsize() const {
388         return ConstDataView(value()).read<LittleEndian<uint32_t>>();
389     }
390 
391     /** Get a string's value.  Also gives you start of the real data for an embedded object.
392         You must assure data is of an appropriate type first -- see also valuestrsafe().
393     */
valuestr()394     const char* valuestr() const {
395         return value() + 4;
396     }
397 
398     /** Get the std::string value of the element.  If not a std::string returns "". */
valuestrsafe()399     const char* valuestrsafe() const {
400         return type() == mongo::String ? valuestr() : "";
401     }
402     /** Get the std::string value of the element.  If not a std::string returns "". */
str()403     std::string str() const {
404         return type() == mongo::String ? std::string(valuestr(), valuestrsize() - 1)
405                                        : std::string();
406     }
407 
408     /**
409      * Returns a StringData pointing into this element's data.  Does not validate that the
410      * element is actually of type String.
411      */
valueStringData()412     const StringData valueStringData() const {
413         return StringData(valuestr(), valuestrsize() - 1);
414     }
415 
416     /** Get javascript code of a CodeWScope data element. */
codeWScopeCode()417     const char* codeWScopeCode() const {
418         massert(16177, "not codeWScope", type() == CodeWScope);
419         return value() + 4 + 4;  // two ints precede code (see BSON spec)
420     }
421 
422     /** Get length of the code part of the CodeWScope object
423      *  This INCLUDES the null char at the end */
codeWScopeCodeLen()424     int codeWScopeCodeLen() const {
425         massert(16178, "not codeWScope", type() == CodeWScope);
426         return ConstDataView(value() + 4).read<LittleEndian<int>>();
427     }
428 
429     /** Get the scope SavedContext of a CodeWScope data element.
430      *
431      *  This function is DEPRECATED, since it can error if there are
432      *  null chars in the codeWScopeCode. However, some existing indexes
433      *  may be based on an incorrect ordering derived from this function,
434      *  so it may still need to be used in certain cases.
435      *   */
codeWScopeScopeDataUnsafe()436     const char* codeWScopeScopeDataUnsafe() const {
437         // This can error if there are null chars in the codeWScopeCode
438         return codeWScopeCode() + strlen(codeWScopeCode()) + 1;
439     }
440 
441     /* Get the scope SavedContext of a CodeWScope data element.
442      *
443      * This is the corrected version of codeWScopeScopeDataUnsafe(),
444      * but note that existing uses might rely on the behavior of
445      * that function so be careful in choosing which version to use.
446      */
codeWScopeScopeData()447     const char* codeWScopeScopeData() const {
448         return codeWScopeCode() + codeWScopeCodeLen();
449     }
450 
451     /** Get the embedded object this element holds. */
452     BSONObj embeddedObject() const;
453 
454     /* uasserts if not an object */
455     BSONObj embeddedObjectUserCheck() const;
456 
457     BSONObj codeWScopeObject() const;
458 
459     /** Get raw binary data.  Element must be of type BinData. Doesn't handle type 2 specially */
binData(int & len)460     const char* binData(int& len) const {
461         // BinData: <int len> <byte subtype> <byte[len] data>
462         verify(type() == BinData);
463         len = valuestrsize();
464         return value() + 5;
465     }
466     /** Get binary data.  Element must be of type BinData. Handles type 2 */
binDataClean(int & len)467     const char* binDataClean(int& len) const {
468         // BinData: <int len> <byte subtype> <byte[len] data>
469         if (binDataType() != ByteArrayDeprecated) {
470             return binData(len);
471         } else {
472             // Skip extra size
473             len = valuestrsize() - 4;
474             return value() + 5 + 4;
475         }
476     }
477 
binDataType()478     BinDataType binDataType() const {
479         // BinData: <int len> <byte subtype> <byte[len] data>
480         verify(type() == BinData);
481         unsigned char c = (value() + 4)[0];
482         return (BinDataType)c;
483     }
484 
_binDataVector()485     std::vector<uint8_t> _binDataVector() const {
486         if (binDataType() != ByteArrayDeprecated) {
487             return std::vector<uint8_t>(reinterpret_cast<const uint8_t*>(value()) + 5,
488                                         reinterpret_cast<const uint8_t*>(value()) + 5 +
489                                             valuestrsize());
490         } else {
491             // Skip the extra int32 size
492             return std::vector<uint8_t>(reinterpret_cast<const uint8_t*>(value()) + 4,
493                                         reinterpret_cast<const uint8_t*>(value()) + 4 +
494                                             valuestrsize() - 4);
495         }
496     }
497 
498     /** Retrieve the regex std::string for a Regex element */
regex()499     const char* regex() const {
500         verify(type() == RegEx);
501         return value();
502     }
503 
504     /** Retrieve the regex flags (options) for a Regex element */
regexFlags()505     const char* regexFlags() const {
506         const char* p = regex();
507         return p + strlen(p) + 1;
508     }
509 
510     //
511     // Comparison API.
512     //
513     // BSONElement instances can be compared via a raw bytewise comparison or a logical comparison.
514     //
515     // Logical comparison can be done either using woCompare() or with operator overloads. Most
516     // callers should prefer operator overloads. Note that the operator overloads return a
517     // DeferredComparison, which must subsequently be evaluated by a
518     // BSONElement::ComparatorInterface. See bsonelement_comparator_interface.h for details.
519     //
520 
521     /**
522      * Compares the raw bytes of the two BSONElements, including the field names. This will treat
523      * different types (e.g. integers and doubles) as distinct values, even if they have the same
524      * field name and bit pattern in the value portion of the BSON element.
525      */
526     bool binaryEqual(const BSONElement& rhs) const;
527 
528     /**
529      * Compares the raw bytes of the two BSONElements, excluding the field names. This will treat
530      * different types (e.g integers and doubles) as distinct values, even if they have the same bit
531      * pattern in the value portion of the BSON element.
532      */
533     bool binaryEqualValues(const BSONElement& rhs) const;
534 
535     /**
536      * Compares two BSON Elements using the rules specified by 'rules' and the 'comparator' for
537      * string comparisons.
538      *
539      * Returns <0 if 'this' is less than 'elem'.
540      *         >0 if 'this' is greater than 'elem'.
541      *          0 if 'this' is equal to 'elem'.
542      */
543     int woCompare(const BSONElement& elem,
544                   ComparisonRulesSet rules = ComparisonRules::kConsiderFieldName,
545                   const StringData::ComparatorInterface* comparator = nullptr) const;
546 
547     DeferredComparison operator<(const BSONElement& other) const {
548         return DeferredComparison(DeferredComparison::Type::kLT, *this, other);
549     }
550 
551     DeferredComparison operator<=(const BSONElement& other) const {
552         return DeferredComparison(DeferredComparison::Type::kLTE, *this, other);
553     }
554 
555     DeferredComparison operator>(const BSONElement& other) const {
556         return DeferredComparison(DeferredComparison::Type::kGT, *this, other);
557     }
558 
559     DeferredComparison operator>=(const BSONElement& other) const {
560         return DeferredComparison(DeferredComparison::Type::kGTE, *this, other);
561     }
562 
563     DeferredComparison operator==(const BSONElement& other) const {
564         return DeferredComparison(DeferredComparison::Type::kEQ, *this, other);
565     }
566 
567     DeferredComparison operator!=(const BSONElement& other) const {
568         return DeferredComparison(DeferredComparison::Type::kNE, *this, other);
569     }
570 
rawdata()571     const char* rawdata() const {
572         return data;
573     }
574 
575     /** Constructs an empty element */
576     BSONElement();
577 
578     /** True if this element may contain subobjects. */
mayEncapsulate()579     bool mayEncapsulate() const {
580         switch (type()) {
581             case Object:
582             case mongo::Array:
583             case CodeWScope:
584                 return true;
585             default:
586                 return false;
587         }
588     }
589 
590     /** True if this element can be a BSONObj */
isABSONObj()591     bool isABSONObj() const {
592         switch (type()) {
593             case Object:
594             case mongo::Array:
595                 return true;
596             default:
597                 return false;
598         }
599     }
600 
timestamp()601     Timestamp timestamp() const {
602         if (type() == mongo::Date || type() == bsonTimestamp) {
603             return Timestamp(ConstDataView(value()).read<LittleEndian<unsigned long long>>().value);
604         }
605         return Timestamp();
606     }
607 
isBinData(BinDataType bdt)608     bool isBinData(BinDataType bdt) const {
609         return (type() == BinData) && (binDataType() == bdt);
610     }
611 
uuid()612     const std::array<unsigned char, 16> uuid() const {
613         int len = 0;
614         const char* data = nullptr;
615         if (isBinData(BinDataType::newUUID)) {
616             data = binData(len);
617         }
618         uassert(ErrorCodes::InvalidUUID,
619                 "uuid must be a 16-byte binary field with UUID (4) subtype",
620                 len == 16);
621         std::array<unsigned char, 16> result;
622         memcpy(&result, data, len);
623         return result;
624     }
625 
md5()626     const std::array<unsigned char, 16> md5() const {
627         int len = 0;
628         const char* data = nullptr;
629         if (isBinData(BinDataType::MD5Type)) {
630             data = binData(len);
631         }
632         uassert(40437, "md5 must be a 16-byte binary field with MD5 (5) subtype", len == 16);
633         std::array<unsigned char, 16> result;
634         memcpy(&result, data, len);
635         return result;
636     }
637 
638 
timestampTime()639     Date_t timestampTime() const {
640         unsigned long long t = ConstDataView(value() + 4).read<LittleEndian<unsigned int>>();
641         return Date_t::fromMillisSinceEpoch(t * 1000);
642     }
timestampInc()643     unsigned int timestampInc() const {
644         return ConstDataView(value()).read<LittleEndian<unsigned int>>();
645     }
646 
timestampValue()647     unsigned long long timestampValue() const {
648         return ConstDataView(value()).read<LittleEndian<unsigned long long>>();
649     }
650 
dbrefNS()651     const char* dbrefNS() const {
652         uassert(10063, "not a dbref", type() == DBRef);
653         return value() + 4;
654     }
655 
dbrefOID()656     const mongo::OID dbrefOID() const {
657         uassert(10064, "not a dbref", type() == DBRef);
658         const char* start = value();
659         start += 4 + ConstDataView(start).read<LittleEndian<int>>();
660         return mongo::OID::from(start);
661     }
662 
663     // @param maxLen don't scan more than maxLen bytes
BSONElement(const char * d)664     explicit BSONElement(const char* d) : data(d) {
665         if (eoo()) {
666             fieldNameSize_ = 0;
667             totalSize = 1;
668         } else {
669             fieldNameSize_ = strlen(d + 1 /*skip type*/) + 1 /*include NUL byte*/;
670             totalSize = computeSize();
671         }
672     }
673 
674     struct CachedSizeTag {};  // Opts in to next constructor.
675 
676     /**
677      * Construct a BSONElement where you already know the length of the name and/or the total size
678      * of the element. fieldNameSize includes the null terminator. You may pass -1 for either or
679      * both sizes to indicate that they are unknown and should be computed.
680      */
BSONElement(const char * d,int fieldNameSize,int totalSize,CachedSizeTag)681     BSONElement(const char* d, int fieldNameSize, int totalSize, CachedSizeTag) : data(d) {
682         if (eoo()) {
683             fieldNameSize_ = 0;
684             this->totalSize = 1;
685         } else {
686             if (fieldNameSize == -1) {
687                 fieldNameSize_ = strlen(d + 1 /*skip type*/) + 1 /*include NUL byte*/;
688             } else {
689                 fieldNameSize_ = fieldNameSize;
690             }
691             if (totalSize == -1) {
692                 this->totalSize = computeSize();
693             } else {
694                 this->totalSize = totalSize;
695             }
696         }
697     }
698 
699     std::string _asCode() const;
700 
701     template <typename T>
702     bool coerce(T* out) const;
703 
704 private:
705     const char* data;
706     int fieldNameSize_;  // internal size includes null terminator
707     int totalSize;
708 
709     friend class BSONObjIterator;
710     friend class BSONObjStlIterator;
711     friend class BSONObj;
chk(BSONType t)712     const BSONElement& chk(BSONType t) const {
713         if (t != type()) {
714             StringBuilder ss;
715             if (eoo())
716                 ss << "field not found, expected type " << t;
717             else
718                 ss << "wrong type for field (" << fieldName() << ") " << type() << " != " << t;
719             uasserted(13111, ss.str());
720         }
721         return *this;
722     }
723 
724     // Only called from constructors.
725     int computeSize() const;
726 };
727 
trueValue()728 inline bool BSONElement::trueValue() const {
729     // NOTE Behavior changes must be replicated in Value::coerceToBool().
730     switch (type()) {
731         case NumberLong:
732             return _numberLong() != 0;
733         case NumberDouble:
734             return _numberDouble() != 0;
735         case NumberDecimal:
736             return _numberDecimal().isNotEqual(Decimal128(0));
737         case NumberInt:
738             return _numberInt() != 0;
739         case mongo::Bool:
740             return boolean();
741         case EOO:
742         case jstNULL:
743         case Undefined:
744             return false;
745         default:
746             return true;
747     }
748 }
749 
750 /** @return true if element is of a numeric type. */
isNumber()751 inline bool BSONElement::isNumber() const {
752     switch (type()) {
753         case NumberLong:
754         case NumberDouble:
755         case NumberDecimal:
756         case NumberInt:
757             return true;
758         default:
759             return false;
760     }
761 }
762 
numberDecimal()763 inline Decimal128 BSONElement::numberDecimal() const {
764     switch (type()) {
765         case NumberDouble:
766             return Decimal128(_numberDouble());
767         case NumberInt:
768             return Decimal128(_numberInt());
769         case NumberLong:
770             return Decimal128(static_cast<int64_t>(_numberLong()));
771         case NumberDecimal:
772             return _numberDecimal();
773         default:
774             return Decimal128::kNormalizedZero;
775     }
776 }
777 
numberDouble()778 inline double BSONElement::numberDouble() const {
779     switch (type()) {
780         case NumberDouble:
781             return _numberDouble();
782         case NumberInt:
783             return _numberInt();
784         case NumberLong:
785             return _numberLong();
786         case NumberDecimal:
787             return _numberDecimal().toDouble();
788         default:
789             return 0;
790     }
791 }
792 
793 /** Retrieve int value for the element safely.  Zero returned if not a number. Converted to int if
794  * another numeric type. */
numberInt()795 inline int BSONElement::numberInt() const {
796     switch (type()) {
797         case NumberDouble:
798             return (int)_numberDouble();
799         case NumberInt:
800             return _numberInt();
801         case NumberLong:
802             return (int)_numberLong();
803         case NumberDecimal:
804             return _numberDecimal().toInt();
805         default:
806             return 0;
807     }
808 }
809 
810 /** Retrieve long value for the element safely.  Zero returned if not a number. */
numberLong()811 inline long long BSONElement::numberLong() const {
812     switch (type()) {
813         case NumberDouble:
814             return (long long)_numberDouble();
815         case NumberInt:
816             return _numberInt();
817         case NumberLong:
818             return _numberLong();
819         case NumberDecimal:
820             return _numberDecimal().toLong();
821         default:
822             return 0;
823     }
824 }
825 
826 /** Like numberLong() but with well-defined behavior for doubles and decimals that
827  *  are NaNs, or too large/small to be represented as long longs.
828  *  NaNs -> 0
829  *  very large values -> LLONG_MAX
830  *  very small values -> LLONG_MIN  */
safeNumberLong()831 inline long long BSONElement::safeNumberLong() const {
832     switch (type()) {
833         case NumberDouble: {
834             double d = numberDouble();
835             if (std::isnan(d)) {
836                 return 0;
837             }
838             if (d > (double)std::numeric_limits<long long>::max()) {
839                 return std::numeric_limits<long long>::max();
840             }
841             if (d < std::numeric_limits<long long>::min()) {
842                 return std::numeric_limits<long long>::min();
843             }
844             return numberLong();
845         }
846         case NumberDecimal: {
847             Decimal128 d = numberDecimal();
848             if (d.isNaN()) {
849                 return 0;
850             }
851             if (d.isGreater(Decimal128(std::numeric_limits<int64_t>::max()))) {
852                 return static_cast<long long>(std::numeric_limits<int64_t>::max());
853             }
854             if (d.isLess(Decimal128(std::numeric_limits<int64_t>::min()))) {
855                 return static_cast<long long>(std::numeric_limits<int64_t>::min());
856             }
857             return numberLong();
858         }
859         default:
860             return numberLong();
861     }
862 }
863 
BSONElement()864 inline BSONElement::BSONElement() {
865     // This needs to be 2 elements because we check the strlen of data + 1 and GCC sees that as
866     // accessing beyond the end of a constant string, even though we always check whether the
867     // element is an eoo.
868     static const char kEooElement[2] = {'\0', '\0'};
869     data = kEooElement;
870     fieldNameSize_ = 0;
871     totalSize = 1;
872 }
873 }
874