SequoiaDB
 All Classes Namespaces Files Functions Macros Pages
bsonelement.h
Go to the documentation of this file.
1 
6 /* Copyright 2009 10gen Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #pragma once
22 
23 #include <vector>
24 #include <string.h>
25 #include "oid.h"
26 #include "util/builder.h"
27 #include "bsontypes.h"
28 #include "bsonassert.h"
29 #include "util/optime.h"
30 #include "bsonDecimal.h"
34 namespace bson {
35 
36  class BSONElement;
37  class BSONObj;
38  class BSONObjBuilder;
39 
40  typedef bson::BSONElement be;
41  typedef bson::BSONObj bo;
42  typedef bson::BSONObjBuilder bob;
43 
44  /* l and r MUST have same type when called: check that first. */
45  int compareElementValues(const BSONElement& l, const BSONElement& r);
46 
47  inline int getBSONCanonicalType( BSONType t )
48  {
49  switch ( t ) {
50  case MinKey:
51  case MaxKey:
52  return t;
53  case EOO:
54  case Undefined:
55  return 0;
56  case jstNULL:
57  return 5;
58  case NumberDouble:
59  case NumberInt:
60  case NumberLong:
61  case NumberDecimal:
62  return 10;
63  case bson::String:
64  case Symbol:
65  return 15;
66  case Object:
67  return 20;
68  case bson::Array:
69  return 25;
70  case BinData:
71  return 30;
72  case jstOID:
73  return 35;
74  case bson::Bool:
75  return 40;
76  case bson::Date:
77  case Timestamp:
78  return 45;
79  case RegEx:
80  return 50;
81  case DBRef:
82  return 55;
83  case Code:
84  return 60;
85  case CodeWScope:
86  return 65;
87  default:
88  assert(0);
89  return -1;
90  }
91  }
92 
108  class BSONElement {
109  public:
116  string String() const { return chk(bson::String).valuestr(); }
117  Date_t Date() const { return chk(bson::Date).date(); }
118  double Number() const { return chk(isNumber()).number(); }
119  double Double() const { return chk(NumberDouble)._numberDouble(); }
120  long long Long() const { return chk(NumberLong)._numberLong(); }
121  bsonDecimal Decimal() const { return chk(NumberDecimal).numberDecimal(); }
122  int Int() const { return chk(NumberInt)._numberInt(); }
123  bool Bool() const { return chk(bson::Bool).boolean(); }
124  vector<BSONElement> Array() const; // see implementation for detailed comments
125  bson::OID OID() const { return chk(jstOID).__oid(); }
126  void Null() const { chk(isNull()); } // throw UserException if not null
127  void OK() const { chk(ok()); } // throw UserException if element DNE
128 
135  BSONObj Obj() const;
136 
141  void Val(Date_t& v) const { v = Date(); }
142  void Val(long long& v) const { v = Long(); }
143  void Val(bool& v) const { v = Bool(); }
144  void Val(BSONObj& v) const;
145  void Val(bson::OID& v) const { v = OID(); }
146  void Val(int& v) const { v = Int(); }
147  void Val(double& v) const { v = Double(); }
148  void Val(string& v) const { v = String(); }
149  void Val(bsonDecimal& v) const { v = Decimal(); }
150 
154  bool ok() const { return !eoo(); }
155 
156  string toString( bool includeFieldName = true,
157  bool full=false) const;
158  void toString( StringBuilder& s, bool
159  includeFieldName = true,
160  bool full=false) const;
161  string jsonString( JsonStringFormat format,
162  bool includeFieldNames = true,
163  int pretty = 0 ) const;
164  operator string() const { return toString(); }
165 
166 #if defined ( SDB_ENGINE ) || defined ( SDB_FMP ) || defined ( SDB_TOOL )
167  ossPoolString poolString() const { return chk(bson::String).valuestr(); }
168  void Val(ossPoolString& v) const { v = poolString(); }
169 
170  ossPoolString toPoolString( bool includeFieldName = true,
171  bool full=false) const;
172  operator ossPoolString() const { return toPoolString() ; }
173 
175  ossPoolString poolStr() const {
176  return type() == bson::String ?
177  ossPoolString(valuestr(), valuestrsize()-1) : ossPoolString();
178  }
179 #endif //SDB_ENGINE || SDB_FMP || SDB_TOOL
180 
182  BSONType type() const { return (BSONType) (signed char)*data; }
183 
187  BSONElement operator[] (const string& field) const;
188 
196  int canonicalType() const;
197 
201  bool eoo() const { return type() == EOO; }
202 
207  int size( int maxLen ) const;
208  int size() const;
209 
211  BSONObj wrap() const;
212 
214  BSONObj wrap( const char* newName) const;
215 
220  const char * fieldName() const {
221  if ( eoo() ) return ""; // no fieldname for it.
222  return data + 1;
223  }
224 
226  const char * value() const {
227  return (data + fieldNameSize() + 1);
228  }
230  int valuesize() const {
231  return size() - fieldNameSize() - 1;
232  }
233 
234  bool isBoolean() const { return type() == bson::Bool; }
235 
239  bool boolean() const {
240  return *value() ? true : false;
241  }
242 
243  bool booleanSafe() const { return isBoolean() && boolean(); }
244 
249  Date_t date() const {
250  return *reinterpret_cast< const Date_t* >( value() );
251  }
252 
257  bool trueValue() const;
258 
260  bool isSimpleType() const;
261 
263  bool isNumber() const;
264 
266  double _numberDouble() const
267  {return *reinterpret_cast< const double* >( value() ); }
269  int _numberInt() const
270  {return *reinterpret_cast< const int* >( value() ); }
272  long long _numberLong() const
273  {return *reinterpret_cast< const long long* >( value() ); }
274 
277  int numberInt() const;
280  long long numberLong() const;
283  bsonDecimal numberDecimal() const;
289  double numberDouble() const;
295  double number() const { return numberDouble(); }
296 
299  const bson::OID &__oid() const
300  { return *reinterpret_cast< const bson::OID* >( value() ); }
301 
303  bool isNull() const {
304  return type() == jstNULL;
305  }
306 
311  int valuestrsize() const {
312  return *reinterpret_cast< const int* >( value() );
313  }
314 
315  // for objects the size *includes* the size of the size field
316  int objsize() const {
317  return *reinterpret_cast< const int* >( value() );
318  }
319 
324  const char * valuestr() const {
325  return value() + 4;
326  }
327 
329  const char *valuestrsafe() const {
330  return type() == bson::String ? valuestr() : "";
331  }
333  string str() const {
334  return type() == bson::String ?
335  string(valuestr(), valuestrsize()-1) : string();
336  }
337 
339  const char * codeWScopeCode() const {
340  return value() + 8;
341  }
343  const char * codeWScopeScopeData() const {
344  // TODO fix
345  return codeWScopeCode() + strlen( codeWScopeCode() ) + 1;
346  }
347 
349  BSONObj embeddedObject() const;
350 
351  /* uasserts if not an object */
352  BSONObj embeddedObjectUserCheck() const;
353 
354  BSONObj codeWScopeObject() const;
355 
358  const char *binData(int& len) const {
359  // BinData: <int len> <byte subtype> <byte[len] data>
360  assert( type() == BinData );
361  len = valuestrsize();
362  return value() + 5;
363  }
365  const char *binDataClean(int& len) const {
366  // BinData: <int len> <byte subtype> <byte[len] data>
367  if (binDataType() != ByteArrayDeprecated) {
368  return binData(len);
369  }
370  else {
371  // Skip extra size
372  len = valuestrsize() - 4;
373  return value() + 5 + 4;
374  }
375  }
376 
377  BinDataType binDataType() const {
378  // BinData: <int len> <byte subtype> <byte[len] data>
379  assert( type() == BinData );
380  unsigned char c = (value() + 4)[0];
381  return (BinDataType)c;
382  }
383 
385  const char *regex() const {
386  assert(type() == RegEx);
387  return value();
388  }
389 
391  const char *regexFlags() const {
392  const char *p = regex();
393  return p + strlen(p) + 1;
394  }
395 
397  string code() const {
398  assert(type() == Code);
399  return _asCode() ;
400  }
401 
405  bool valuesEqual(const BSONElement& r) const {
406  return woCompare( r , false ) == 0;
407  }
408 
410  bool operator==(const BSONElement& r) const {
411  return woCompare( r , true ) == 0;
412  }
413 
419  int woCompare( const BSONElement &e, bool considerFieldName = true )
420  const;
421 
422  const char * rawdata() const { return data; }
423 
425  int getGtLtOp( int def = 0 ) const;
426 
428  BSONElement();
429 
431  void validate() const;
432 
434  bool mayEncapsulate() const {
435  switch ( type() ) {
436  case Object:
437  case bson::Array:
438  case CodeWScope:
439  return true;
440  default:
441  return false;
442  }
443  }
444 
446  bool isABSONObj() const {
447  switch( type() ) {
448  case Object:
449  case bson::Array:
450  return true;
451  default:
452  return false;
453  }
454  }
455 
456  Date_t timestampTime() const {
457  long long t = ((int*)(value() + 4 ))[0];
458  return t * 1000;
459  }
460  unsigned int timestampInc() const {
461  return ((unsigned int*)(value() ))[0];
462  }
463 
464  const char * dbrefNS() const {
465  uassert( 10063 , "not a dbref" , type() == DBRef );
466  return value() + 4;
467  }
468 
469  const bson::OID& dbrefOID() const {
470  uassert( 10064 , "not a dbref" , type() == DBRef );
471  const char * start = value();
472  start += 4 + *reinterpret_cast< const int* >( start );
473  return *reinterpret_cast< const bson::OID* >( start );
474  }
475 
477  bool operator<( const BSONElement& other ) const {
478  int x = (int)canonicalType() - (int)other.canonicalType();
479  if ( x < 0 ) return true;
480  else if ( x > 0 ) return false;
481  return compareElementValues(*this,other) < 0;
482  }
483 
484  // @param maxLen don't scan more than maxLen bytes
485  explicit BSONElement(const char *d, int maxLen) : data(d) {
486  if ( eoo() ) {
487  totalSize = 1;
488  fieldNameSize_ = 0;
489  }
490  else {
491  totalSize = -1;
492  fieldNameSize_ = -1;
493  if ( maxLen != -1 ) {
494  int size = (int) strnlen( fieldName(), maxLen - 1 );
495  massert( 10333 , "Invalid field name", size != -1 );
496  fieldNameSize_ = size + 1;
497  }
498  }
499  }
500 
501  explicit BSONElement(const char *d) : data(d) {
502  fieldNameSize_ = -1;
503  totalSize = -1;
504  if ( eoo() ) {
505  fieldNameSize_ = 0;
506  totalSize = 1;
507  }
508  }
509 
510  string _asCode() const;
511  OpTime _opTime() const;
512 
513  private:
514  const char *data;
515  mutable int fieldNameSize_; // cached value
516  int fieldNameSize() const {
517  if ( fieldNameSize_ == -1 )
518  fieldNameSize_ = (int)strlen( fieldName() ) + 1;
519  return fieldNameSize_;
520  }
521  mutable int totalSize; /* caches the computed size */
522 
523  friend class BSONObjIterator;
524  friend class BSONObj;
525  const BSONElement& chk(int t) const {
526  if ( t != type() ) {
527  StringBuilder ss;
528  if( eoo() )
529  ss << "field not found, expected type " << t;
530  else
531  ss << "wrong type for field (" << fieldName() << ") "
532  << type() << " != " << t;
533  uasserted(13111, ss.str() );
534  }
535  return *this;
536  }
537  const BSONElement& chk(bool expr) const {
538  uassert(13118, "unexpected or missing type value in BSON object",
539  expr);
540  return *this;
541  }
542 
543  inline string _numberDecimalStr() const ;
544 
545 #if defined ( SDB_ENGINE ) || defined ( SDB_FMP ) || defined ( SDB_TOOL )
546  inline ossPoolString _numberDecimalPoolStr() const ;
547 #endif //SDB_ENGINE || SDB_FMP || SDB_TOOL
548  };
549 
550 
551  inline int BSONElement::canonicalType() const {
552  return getBSONCanonicalType( type() ) ;
553  }
554 
556  inline bool BSONElement::isNumber() const {
557  switch( type() ) {
558  case NumberLong:
559  case NumberDouble:
560  case NumberInt:
561  case NumberDecimal:
562  return true;
563  default:
564  return false;
565  }
566  }
567 
568  inline bool BSONElement::isSimpleType() const {
569  switch( type() ) {
570  case NumberLong:
571  case NumberDouble:
572  case NumberInt:
573  case bson::String:
574  case bson::Bool:
575  case bson::Date:
576  case jstOID:
577  return true;
578  default:
579  return false;
580  }
581  }
582 
583  inline bsonDecimal BSONElement::numberDecimal() const {
584  int rc = 0 ;
585  bsonDecimal decimal ;
586  switch( type() ) {
587  case NumberDouble:
588  rc = decimal.fromDouble( _numberDouble() ) ;
589  uassert( rc, "Failed to parse decimal from double",
590  0 == rc ) ;
591  break ;
592  case NumberInt:
593  rc = decimal.fromInt( _numberInt() ) ;
594  uassert( rc, "Failed to parse decimal from int",
595  0 == rc ) ;
596  break ;
597  case NumberLong:
598  rc = decimal.fromLong( _numberLong() ) ;
599  uassert( rc, "Failed to parse decimal from long",
600  0 == rc ) ;
601  break ;
602  case NumberDecimal:
603  rc = decimal.fromBsonValue( value() ) ;
604  uassert( rc, "Failed to parse decimal from bson value",
605  0 == rc ) ;
606  break ;
607  default:
608  break ;
609  }
610 
611  return decimal ;
612  }
613 
615  static char z = 0;
616  data = &z;
617  fieldNameSize_ = 0;
618  totalSize = 1;
619  }
620 
621  /*
622  BSONDecimalElement define
623  */
625  {
626  public:
627  BSONDecimalElement( const BSONElement &element )
628  : BSONElement( element ),
629  _decimal()
630  {
631  _numberDecimalView( _decimal ) ;
632  }
633 
635  {
636  }
637 
638  const bsonDecimal &numberDecimal() const
639  {
640  return _decimal ;
641  }
642 
643  private:
645  BSONDecimalElement &operator =( const BSONDecimalElement & ) ;
646 
647  protected:
648  inline void _numberDecimalView( bsonDecimal &decimal ) const ;
649 
650  protected:
651  bsonDecimal _decimal ;
652  } ;
653 
654  inline void BSONDecimalElement::_numberDecimalView( bsonDecimal &decimal ) const
655  {
656  int rc = 0 ;
657  switch( type() ) {
658  case NumberDouble:
659  rc = decimal.fromDouble( _numberDouble() ) ;
660  uassert( rc, "Failed to parse decimal from double",
661  0 == rc ) ;
662  break ;
663  case NumberInt:
664  rc = decimal.fromInt( _numberInt() ) ;
665  uassert( rc, "Failed to parse decimal from int",
666  0 == rc ) ;
667  break ;
668  case NumberLong:
669  rc = decimal.fromLong( _numberLong() ) ;
670  uassert( rc, "Failed to parse decimal from long",
671  0 == rc ) ;
672  break ;
673  case NumberDecimal:
674  rc = decimal._fromBsonValue( value(), FALSE ) ;
675  uassert( rc, "Failed to parse decimal from bson value",
676  0 == rc ) ;
677  break ;
678  default:
679  break ;
680  }
681  }
682 
683 }