MongoDB C++ Driver legacy-1.1.2
Loading...
Searching...
No Matches
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
33namespace mongo {
34class BSONObj;
35class BSONElement;
36class BSONObjBuilder;
37
38/* l and r MUST have same type when called: check that first. */
39int compareElementValues(const BSONElement& l, const BSONElement& r);
40
41
55class MONGO_CLIENT_API BSONElement {
56public:
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
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
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
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
561private:
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
586inline 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
609inline 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
620inline 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
635inline 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
650inline 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
664inline 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
682inline 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.
709std::string escape(const std::string& s, bool escape_slash = false);
710}
BSONElement represents an "element" in a BSONObj.
Definition bsonelement.h:55
bool isSimpleType() const
True if number, string, bool, date, OID.
Definition bsonelement.h:620
bool operator<(const BSONElement &other) const
this does not use fieldName in the comparison, just the value
Definition bsonelement.h:509
int valuesize() const
size in bytes of the element's value (when applicable).
Definition bsonelement.h:216
bool ok() const
Use ok() to check if a value is assigned: if( myObj["foo"].ok() ) ...
Definition bsonelement.h:137
long long numberLong() const
Retrieve long value for the element safely.
Definition bsonelement.h:664
bool isABSONObj() const
True if this element can be a BSONObj.
Definition bsonelement.h:479
const char * valuestr() const
Get a string's value.
Definition bsonelement.h:321
const char * codeWScopeScopeDataUnsafe() const
Get the scope SavedContext of a CodeWScope data element.
Definition bsonelement.h:363
const char * regex() const
Retrieve the regex string for a Regex element.
Definition bsonelement.h:413
const char * binData(int &len) const
Get raw binary data.
Definition bsonelement.h:387
BSONObj wrap(const StringData &newName) const
Wrap this element up as a singleton object with a new name.
mongo::OID __oid() const
Retrieve the object ID stored in the object.
Definition bsonelement.h:296
BSONObj wrap() const
Wrap this element up as a singleton object.
const char * binDataClean(int &len) const
Get binary data.
Definition bsonelement.h:394
int canonicalType() const
See canonicalizeBSONType in bsontypes.h.
Definition bsonelement.h:165
int _numberInt() const
Return int value for this field.
Definition bsonelement.h:260
double numberDouble() const
Retrieve the numeric value of the element.
Definition bsonelement.h:635
const char * value() const
raw data of the element's value (so be careful).
Definition bsonelement.h:212
BSONElement()
Constructs an empty element.
Definition bsonelement.h:701
double number() const
Retrieve the numeric value of the element.
Definition bsonelement.h:290
const char * fieldName() const
field name of the element.
Definition bsonelement.h:192
bool mayEncapsulate() const
True if this element may contain subobjects.
Definition bsonelement.h:467
const char * regexFlags() const
Retrieve the regex flags (options) for a Regex element.
Definition bsonelement.h:419
BSONElement(const char *d, int fieldNameSize, FieldNameSizeTag)
Construct a BSONElement where you already know the length of the name.
Definition bsonelement.h:550
bool isNumber() const
True if element is of a numeric type.
Definition bsonelement.h:609
const StringData valueStringData() const
Returns a StringData pointing into this element's data.
Definition bsonelement.h:339
int valuestrsize() const
Size (length) of a string element.
Definition bsonelement.h:309
bool boolean() const
Definition bsonelement.h:227
int fieldNameSize() const
NOTE: size includes the NULL terminator.
Definition bsonelement.h:201
bool isNull() const
True if element is null.
Definition bsonelement.h:301
int size(int maxLen) const
Size of the element.
bool operator!=(const BSONElement &r) const
Returns true if elements are unequal.
Definition bsonelement.h:436
int getGtLtOp(int def=0) const
0 == Equality, just not defined yet
const char * valuestrsafe() const
Get the string value of the element.
Definition bsonelement.h:326
int woCompare(const BSONElement &e, bool considerFieldName=true) const
Well ordered comparison.
bool trueValue() const
Convert the value to boolean, regardless of its type, in a javascript-like fashion (i....
Definition bsonelement.h:586
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
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
bool operator==(const BSONElement &r) const
Returns true if elements are equal.
Definition bsonelement.h:432
const char * codeWScopeCode() const
Get javascript code of a CodeWScope data element.
Definition bsonelement.h:344
int numberInt() const
Retrieve int value for the element safely.
Definition bsonelement.h:650
BSONObj embeddedObject() const
Get the embedded object this element holds.
double _numberDouble() const
Return double value for this field.
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:172
bool valuesEqual(const BSONElement &r) const
like operator== but doesn't check the fieldname, just the value.
Definition bsonelement.h:427
BSONElement operator[](const std::string &field) const
retrieve a field within this element throws exception if *this is not an embedded object
long long _numberLong() const
Return long long value for this field.
Definition bsonelement.h:265
void Val(Date_t &v) const
populate v with the value of the element.
Definition bsonelement.h:111
BSONType type() const
Returns the type of the element.
Definition bsonelement.h:154
BSONObj Obj() const
Date_t date() const
Retrieve a java style date value from the element.
Definition bsonelement.h:239
std::string str() const
Get the string value of the element.
Definition bsonelement.h:330
std::string String() const
These functions, which start with a capital letter, throw a MsgAssertionException if the element is n...
Definition bsonelement.h:62
iterator for a BSONObj
Definition bsonobjiterator.h:37
C++ representation of a "BSON" object – that is, an extended JSON-style object in a binary representa...
Definition bsonobj.h:78
Definition data_cursor.h:26
Definition data_view.h:30
Object ID type.
Definition oid.h:60
std::stringstream deals with locale so this is a lot faster than std::stringstream for UTF8
Definition builder.h:325
A StringData object wraps a 'const string&' or a 'const char*' without copying its contents.
Definition string_data.h:43
Definition timestamp.h:23
Utility functions for parsing numbers from strings.
Definition compare_numbers.h:20
JsonStringFormat
Formatting mode for generating JSON from BSON.
Definition oid.h:205
int canonicalizeBSONType(BSONType type)
Returns a number for where a given type falls in the sort order.
Definition bsontypes.h:109
BSONType
the complete list of valid BSON types see also bsonspec.org
Definition bsontypes.h:38
@ CodeWScope
javascript code that can execute on the database server, with SavedContext
Definition bsontypes.h:72
@ String
character string, stored in utf8
Definition bsontypes.h:46
@ BinData
binary data
Definition bsontypes.h:52
@ Array
an embedded array
Definition bsontypes.h:50
@ Bool
boolean type
Definition bsontypes.h:58
@ Timestamp
Updated to a Date with value next OpTime on insert.
Definition bsontypes.h:76
@ RegEx
regular expression, a pattern with options
Definition bsontypes.h:64
@ jstOID
ObjectId.
Definition bsontypes.h:56
@ Undefined
Undefined type.
Definition bsontypes.h:54
@ EOO
end of object
Definition bsontypes.h:42
@ Object
an embedded object
Definition bsontypes.h:48
@ NumberLong
64 bit integer
Definition bsontypes.h:78
@ jstNULL
null type
Definition bsontypes.h:62
@ NumberInt
32 bit signed integer
Definition bsontypes.h:74
@ NumberDouble
double precision floating point value
Definition bsontypes.h:44
@ Date
date type
Definition bsontypes.h:60
Definition bsonelement.h:543
Functor compatible with std::hash for std::unordered_{map,set} Warning: The hash function is subject ...
Definition bsonelement.h:452
Definition time_support.h:39