MongoDB  2.0.3
bsonelement.h
00001 // BSONElement
00002 
00003 /*    Copyright 2009 10gen Inc.
00004  *
00005  *    Licensed under the Apache License, Version 2.0 (the "License");
00006  *    you may not use this file except in compliance with the License.
00007  *    You may obtain a copy of the License at
00008  *
00009  *    http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  *    Unless required by applicable law or agreed to in writing, software
00012  *    distributed under the License is distributed on an "AS IS" BASIS,
00013  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  *    See the License for the specific language governing permissions and
00015  *    limitations under the License.
00016  */
00017 
00018 #pragma once
00019 
00020 #include <vector>
00021 #include <string.h>
00022 #include "util/builder.h"
00023 #include "bsontypes.h"
00024 
00025 namespace mongo {
00026     class OpTime;
00027     class BSONObj;
00028     class BSONElement;
00029     class BSONObjBuilder;
00030 }
00031 
00032 namespace bson {
00033     typedef mongo::BSONElement be;
00034     typedef mongo::BSONObj bo;
00035     typedef mongo::BSONObjBuilder bob;
00036 }
00037 
00038 namespace mongo {
00039 
00040     /* l and r MUST have same type when called: check that first. */
00041     int compareElementValues(const BSONElement& l, const BSONElement& r);
00042 
00043 
00057     class BSONElement {
00058     public:
00064         string String()             const { return chk(mongo::String).valuestr(); }
00065         Date_t Date()               const { return chk(mongo::Date).date(); }
00066         double Number()             const { return chk(isNumber()).number(); }
00067         double Double()             const { return chk(NumberDouble)._numberDouble(); }
00068         long long Long()            const { return chk(NumberLong)._numberLong(); }
00069         int Int()                   const { return chk(NumberInt)._numberInt(); }
00070         bool Bool()                 const { return chk(mongo::Bool).boolean(); }
00071         vector<BSONElement> Array() const; // see implementation for detailed comments
00072         mongo::OID OID()            const { return chk(jstOID).__oid(); }
00073         void Null()                 const { chk(isNull()); } // throw UserException if not null
00074         void OK()                   const { chk(ok()); }     // throw UserException if element DNE
00075 
00082         BSONObj Obj()               const;
00083 
00087         void Val(Date_t& v)         const { v = Date(); }
00088         void Val(long long& v)      const { v = Long(); }
00089         void Val(bool& v)           const { v = Bool(); }
00090         void Val(BSONObj& v)        const;
00091         void Val(mongo::OID& v)     const { v = OID(); }
00092         void Val(int& v)            const { v = Int(); }
00093         void Val(double& v)         const { v = Double(); }
00094         void Val(string& v)         const { v = String(); }
00095 
00099         bool ok() const { return !eoo(); }
00100 
00101         string toString( bool includeFieldName = true, bool full=false) const;
00102         void toString(StringBuilder& s, bool includeFieldName = true, bool full=false) const;
00103         string jsonString( JsonStringFormat format, bool includeFieldNames = true, int pretty = 0 ) const;
00104         operator string() const { return toString(); }
00105 
00107         BSONType type() const { return (BSONType) *data; }
00108 
00112         BSONElement operator[] (const string& field) const;
00113 
00118         int canonicalType() const;
00119 
00123         bool eoo() const { return type() == EOO; }
00124 
00128         int size( int maxLen ) const;
00129         int size() const;
00130 
00132         BSONObj wrap() const;
00133 
00135         BSONObj wrap( const char* newName) const;
00136 
00141         const char * fieldName() const {
00142             if ( eoo() ) return ""; // no fieldname for it.
00143             return data + 1;
00144         }
00145 
00147         const char * value() const {
00148             return (data + fieldNameSize() + 1);
00149         }
00151         int valuesize() const {
00152             return size() - fieldNameSize() - 1;
00153         }
00154 
00155         bool isBoolean() const { return type() == mongo::Bool; }
00156 
00160         bool boolean() const {
00161             return *value() ? true : false;
00162         }
00163 
00164         bool booleanSafe() const { return isBoolean() && boolean(); }
00165 
00170         Date_t date() const {
00171             return *reinterpret_cast< const Date_t* >( value() );
00172         }
00173 
00177         bool trueValue() const;
00178 
00180         bool isSimpleType() const;
00181 
00183         bool isNumber() const;
00184 
00186         double _numberDouble() const {return *reinterpret_cast< const double* >( value() ); }
00188         int _numberInt() const {return *reinterpret_cast< const int* >( value() ); }
00190         long long _numberLong() const {return *reinterpret_cast< const long long* >( value() ); }
00191 
00193         int numberInt() const;
00195         long long numberLong() const;
00199         double numberDouble() const;
00203         double number() const { return numberDouble(); }
00204 
00207         const mongo::OID &__oid() const { return *reinterpret_cast< const mongo::OID* >( value() ); }
00208 
00210         bool isNull() const {
00211             return type() == jstNULL;
00212         }
00213 
00218         int valuestrsize() const {
00219             return *reinterpret_cast< const int* >( value() );
00220         }
00221 
00222         // for objects the size *includes* the size of the size field
00223         int objsize() const {
00224             return *reinterpret_cast< const int* >( value() );
00225         }
00226 
00230         const char * valuestr() const {
00231             return value() + 4;
00232         }
00233 
00235         const char *valuestrsafe() const {
00236             return type() == mongo::String ? valuestr() : "";
00237         }
00239         string str() const {
00240             return type() == mongo::String ? string(valuestr(), valuestrsize()-1) : string();
00241         }
00242 
00244         const char * codeWScopeCode() const {
00245             return value() + 8;
00246         }
00248         const char * codeWScopeScopeData() const {
00249             // TODO fix
00250             return codeWScopeCode() + strlen( codeWScopeCode() ) + 1;
00251         }
00252 
00254         BSONObj embeddedObject() const;
00255 
00256         /* uasserts if not an object */
00257         BSONObj embeddedObjectUserCheck() const;
00258 
00259         BSONObj codeWScopeObject() const;
00260 
00262         const char *binData(int& len) const {
00263             // BinData: <int len> <byte subtype> <byte[len] data>
00264             assert( type() == BinData );
00265             len = valuestrsize();
00266             return value() + 5;
00267         }
00269         const char *binDataClean(int& len) const {
00270             // BinData: <int len> <byte subtype> <byte[len] data>
00271             if (binDataType() != ByteArrayDeprecated) {
00272                 return binData(len);
00273             }
00274             else {
00275                 // Skip extra size
00276                 len = valuestrsize() - 4;
00277                 return value() + 5 + 4;
00278             }
00279         }
00280 
00281         BinDataType binDataType() const {
00282             // BinData: <int len> <byte subtype> <byte[len] data>
00283             assert( type() == BinData );
00284             unsigned char c = (value() + 4)[0];
00285             return (BinDataType)c;
00286         }
00287 
00289         const char *regex() const {
00290             assert(type() == RegEx);
00291             return value();
00292         }
00293 
00295         const char *regexFlags() const {
00296             const char *p = regex();
00297             return p + strlen(p) + 1;
00298         }
00299 
00303         bool valuesEqual(const BSONElement& r) const {
00304             return woCompare( r , false ) == 0;
00305         }
00306 
00308         bool operator==(const BSONElement& r) const {
00309             return woCompare( r , true ) == 0;
00310         }
00312         bool operator!=(const BSONElement& r) const { return !operator==(r); }
00313 
00319         int woCompare( const BSONElement &e, bool considerFieldName = true ) const;
00320 
00321         const char * rawdata() const { return data; }
00322 
00324         int getGtLtOp( int def = 0 ) const;
00325 
00327         BSONElement();
00328 
00330         void validate() const;
00331 
00333         bool mayEncapsulate() const {
00334             switch ( type() ) {
00335             case Object:
00336             case mongo::Array:
00337             case CodeWScope:
00338                 return true;
00339             default:
00340                 return false;
00341             }
00342         }
00343 
00345         bool isABSONObj() const {
00346             switch( type() ) {
00347             case Object:
00348             case mongo::Array:
00349                 return true;
00350             default:
00351                 return false;
00352             }
00353         }
00354 
00355         Date_t timestampTime() const {
00356             unsigned long long t = ((unsigned int*)(value() + 4 ))[0];
00357             return t * 1000;
00358         }
00359         unsigned int timestampInc() const {
00360             return ((unsigned int*)(value() ))[0];
00361         }
00362 
00363         const char * dbrefNS() const {
00364             uassert( 10063 ,  "not a dbref" , type() == DBRef );
00365             return value() + 4;
00366         }
00367 
00368         const mongo::OID& dbrefOID() const {
00369             uassert( 10064 ,  "not a dbref" , type() == DBRef );
00370             const char * start = value();
00371             start += 4 + *reinterpret_cast< const int* >( start );
00372             return *reinterpret_cast< const mongo::OID* >( start );
00373         }
00374 
00376         bool operator<( const BSONElement& other ) const {
00377             int x = (int)canonicalType() - (int)other.canonicalType();
00378             if ( x < 0 ) return true;
00379             else if ( x > 0 ) return false;
00380             return compareElementValues(*this,other) < 0;
00381         }
00382 
00383         // @param maxLen don't scan more than maxLen bytes
00384         explicit BSONElement(const char *d, int maxLen) : data(d) {
00385             if ( eoo() ) {
00386                 totalSize = 1;
00387                 fieldNameSize_ = 0;
00388             }
00389             else {
00390                 totalSize = -1;
00391                 fieldNameSize_ = -1;
00392                 if ( maxLen != -1 ) {
00393                     int size = (int) strnlen( fieldName(), maxLen - 1 );
00394                     massert( 10333 ,  "Invalid field name", size != -1 );
00395                     fieldNameSize_ = size + 1;
00396                 }
00397             }
00398         }
00399 
00400         explicit BSONElement(const char *d) : data(d) {
00401             fieldNameSize_ = -1;
00402             totalSize = -1;
00403             if ( eoo() ) {
00404                 fieldNameSize_ = 0;
00405                 totalSize = 1;
00406             }
00407         }
00408 
00409         string _asCode() const;
00410         OpTime _opTime() const;
00411 
00412     private:
00413         const char *data;
00414         mutable int fieldNameSize_; // cached value
00415         int fieldNameSize() const {
00416             if ( fieldNameSize_ == -1 )
00417                 fieldNameSize_ = (int)strlen( fieldName() ) + 1;
00418             return fieldNameSize_;
00419         }
00420         mutable int totalSize; /* caches the computed size */
00421 
00422         friend class BSONObjIterator;
00423         friend class BSONObj;
00424         const BSONElement& chk(int t) const {
00425             if ( t != type() ) {
00426                 StringBuilder ss;
00427                 if( eoo() )
00428                     ss << "field not found, expected type " << t;
00429                 else
00430                     ss << "wrong type for field (" << fieldName() << ") " << type() << " != " << t;
00431                 uasserted(13111, ss.str() );
00432             }
00433             return *this;
00434         }
00435         const BSONElement& chk(bool expr) const {
00436             uassert(13118, "unexpected or missing type value in BSON object", expr);
00437             return *this;
00438         }
00439     };
00440 
00441 
00442     inline int BSONElement::canonicalType() const {
00443         BSONType t = type();
00444         switch ( t ) {
00445         case MinKey:
00446         case MaxKey:
00447             return t;
00448         case EOO:
00449         case Undefined:
00450             return 0;
00451         case jstNULL:
00452             return 5;
00453         case NumberDouble:
00454         case NumberInt:
00455         case NumberLong:
00456             return 10;
00457         case mongo::String:
00458         case Symbol:
00459             return 15;
00460         case Object:
00461             return 20;
00462         case mongo::Array:
00463             return 25;
00464         case BinData:
00465             return 30;
00466         case jstOID:
00467             return 35;
00468         case mongo::Bool:
00469             return 40;
00470         case mongo::Date:
00471         case Timestamp:
00472             return 45;
00473         case RegEx:
00474             return 50;
00475         case DBRef:
00476             return 55;
00477         case Code:
00478             return 60;
00479         case CodeWScope:
00480             return 65;
00481         default:
00482             assert(0);
00483             return -1;
00484         }
00485     }
00486 
00487     inline bool BSONElement::trueValue() const {
00488         switch( type() ) {
00489         case NumberLong:
00490             return *reinterpret_cast< const long long* >( value() ) != 0;
00491         case NumberDouble:
00492             return *reinterpret_cast< const double* >( value() ) != 0;
00493         case NumberInt:
00494             return *reinterpret_cast< const int* >( value() ) != 0;
00495         case mongo::Bool:
00496             return boolean();
00497         case EOO:
00498         case jstNULL:
00499         case Undefined:
00500             return false;
00501 
00502         default:
00503             ;
00504         }
00505         return true;
00506     }
00507 
00509     inline bool BSONElement::isNumber() const {
00510         switch( type() ) {
00511         case NumberLong:
00512         case NumberDouble:
00513         case NumberInt:
00514             return true;
00515         default:
00516             return false;
00517         }
00518     }
00519 
00520     inline bool BSONElement::isSimpleType() const {
00521         switch( type() ) {
00522         case NumberLong:
00523         case NumberDouble:
00524         case NumberInt:
00525         case mongo::String:
00526         case mongo::Bool:
00527         case mongo::Date:
00528         case jstOID:
00529             return true;
00530         default:
00531             return false;
00532         }
00533     }
00534 
00535     inline double BSONElement::numberDouble() const {
00536         switch( type() ) {
00537         case NumberDouble:
00538             return _numberDouble();
00539         case NumberInt:
00540             return *reinterpret_cast< const int* >( value() );
00541         case NumberLong:
00542             return (double) *reinterpret_cast< const long long* >( value() );
00543         default:
00544             return 0;
00545         }
00546     }
00547 
00549     inline int BSONElement::numberInt() const {
00550         switch( type() ) {
00551         case NumberDouble:
00552             return (int) _numberDouble();
00553         case NumberInt:
00554             return _numberInt();
00555         case NumberLong:
00556             return (int) _numberLong();
00557         default:
00558             return 0;
00559         }
00560     }
00561 
00563     inline long long BSONElement::numberLong() const {
00564         switch( type() ) {
00565         case NumberDouble:
00566             return (long long) _numberDouble();
00567         case NumberInt:
00568             return _numberInt();
00569         case NumberLong:
00570             return _numberLong();
00571         default:
00572             return 0;
00573         }
00574     }
00575 
00576     inline BSONElement::BSONElement() {
00577         static char z = 0;
00578         data = &z;
00579         fieldNameSize_ = 0;
00580         totalSize = 1;
00581     }
00582 
00583 }