MongoDB C++ Driver legacy-1.0.1
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 {
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
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
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}
BSONElement represents an "element" in a BSONObj.
Definition bsonelement.h:55
bool isSimpleType() const
True if number, string, bool, date, OID.
Definition bsonelement.h:558
bool operator<(const BSONElement &other) const
this does not use fieldName in the comparison, just the value
Definition bsonelement.h:449
int valuesize() const
size in bytes of the element's value (when applicable).
Definition bsonelement.h:166
bool ok() const
Use ok() to check if a value is assigned: if( myObj["foo"].ok() ) ...
Definition bsonelement.h:101
long long numberLong() const
Retrieve long value for the element safely.
Definition bsonelement.h:601
bool isABSONObj() const
True if this element can be a BSONObj.
Definition bsonelement.h:419
const char * valuestr() const
Get a string's value.
Definition bsonelement.h:265
const char * codeWScopeScopeDataUnsafe() const
Get the scope SavedContext of a CodeWScope data element.
Definition bsonelement.h:306
const char * regex() const
Retrieve the regex string for a Regex element.
Definition bsonelement.h:357
const char * binData(int &len) const
Get raw binary data.
Definition bsonelement.h:330
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:240
BSONObj wrap() const
Wrap this element up as a singleton object.
const char * binDataClean(int &len) const
Get binary data.
Definition bsonelement.h:337
int canonicalType() const
See canonicalizeBSONType in bsontypes.h.
Definition bsonelement.h:120
int _numberInt() const
Return int value for this field.
Definition bsonelement.h:206
double numberDouble() const
Retrieve the numeric value of the element.
Definition bsonelement.h:573
const char * value() const
raw data of the element's value (so be careful).
Definition bsonelement.h:162
BSONElement()
Constructs an empty element.
Definition bsonelement.h:638
double number() const
Retrieve the numeric value of the element.
Definition bsonelement.h:236
const char * fieldName() const
field name of the element.
Definition bsonelement.h:143
bool mayEncapsulate() const
True if this element may contain subobjects.
Definition bsonelement.h:407
const char * regexFlags() const
Retrieve the regex flags (options) for a Regex element.
Definition bsonelement.h:363
BSONElement(const char *d, int fieldNameSize, FieldNameSizeTag)
Construct a BSONElement where you already know the length of the name.
Definition bsonelement.h:489
bool isNumber() const
True if element is of a numeric type.
Definition bsonelement.h:547
const StringData valueStringData() const
Returns a StringData pointing into this element's data.
Definition bsonelement.h:282
int valuestrsize() const
Size (length) of a string element.
Definition bsonelement.h:253
bool boolean() const
Definition bsonelement.h:175
int fieldNameSize() const
NOTE: size includes the NULL terminator.
Definition bsonelement.h:151
bool isNull() const
True if element is null.
Definition bsonelement.h:245
int size(int maxLen) const
Size of the element.
bool operator!=(const BSONElement &r) const
Returns true if elements are unequal.
Definition bsonelement.h:380
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:270
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:524
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
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
bool operator==(const BSONElement &r) const
Returns true if elements are equal.
Definition bsonelement.h:376
const char * codeWScopeCode() const
Get javascript code of a CodeWScope data element.
Definition bsonelement.h:287
int numberInt() const
Retrieve int value for the element safely.
Definition bsonelement.h:587
BSONObj embeddedObject() const
Get the embedded object this element holds.
double _numberDouble() const
Return double value for this field.
Definition bsonelement.h:201
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 valuesEqual(const BSONElement &r) const
like operator== but doesn't check the fieldname, just the value.
Definition bsonelement.h:371
long long _numberLong() const
Return long long value for this field.
Definition bsonelement.h:211
void Val(Date_t &v) const
populate v with the value of the element.
Definition bsonelement.h:89
BSONType type() const
Returns the type of the element.
Definition bsonelement.h:109
BSONObj Obj() const
Date_t date() const
Retrieve a java style date value from the element.
Definition bsonelement.h:185
std::string str() const
Get the string value of the element.
Definition bsonelement.h:274
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
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:299
Definition timestamp.h:23
the main MongoDB namespace
Definition bulk_operation_builder.h:24
JsonStringFormat
Formatting mode for generating JSON from BSON.
Definition oid.h:204
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:482
Functor compatible with std::hash for std::unordered_{map,set} Warning: The hash function is subject ...
Definition bsonelement.h:394
Definition time_support.h:39