MongoDB  2.1.1-pre-
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 #include "oid.h"
00025 
00026 namespace mongo {
00027     class OpTime;
00028     class BSONObj;
00029     class BSONElement;
00030     class BSONObjBuilder;
00031 }
00032 
00033 namespace bson {
00034     typedef mongo::BSONElement be;
00035     typedef mongo::BSONObj bo;
00036     typedef mongo::BSONObjBuilder bob;
00037 }
00038 
00039 namespace mongo {
00040 
00041     /* l and r MUST have same type when called: check that first. */
00042     int compareElementValues(const BSONElement& l, const BSONElement& r);
00043 
00044 
00058     class BSONElement {
00059     public:
00065         string String()             const { return chk(mongo::String).valuestr(); }
00066         Date_t Date()               const { return chk(mongo::Date).date(); }
00067         double Number()             const { return chk(isNumber()).number(); }
00068         double Double()             const { return chk(NumberDouble)._numberDouble(); }
00069         long long Long()            const { return chk(NumberLong)._numberLong(); }
00070         int Int()                   const { return chk(NumberInt)._numberInt(); }
00071         bool Bool()                 const { return chk(mongo::Bool).boolean(); }
00072         vector<BSONElement> Array() const; // see implementation for detailed comments
00073         mongo::OID OID()            const { return chk(jstOID).__oid(); }
00074         void Null()                 const { chk(isNull()); } // throw UserException if not null
00075         void OK()                   const { chk(ok()); }     // throw UserException if element DNE
00076 
00083         BSONObj Obj()               const;
00084 
00088         void Val(Date_t& v)         const { v = Date(); }
00089         void Val(long long& v)      const { v = Long(); }
00090         void Val(bool& v)           const { v = Bool(); }
00091         void Val(BSONObj& v)        const;
00092         void Val(mongo::OID& v)     const { v = OID(); }
00093         void Val(int& v)            const { v = Int(); }
00094         void Val(double& v)         const { v = Double(); }
00095         void Val(string& v)         const { v = String(); }
00096 
00100         bool ok() const { return !eoo(); }
00101 
00102         string toString( bool includeFieldName = true, bool full=false) const;
00103         void toString(StringBuilder& s, bool includeFieldName = true, bool full=false) const;
00104         string jsonString( JsonStringFormat format, bool includeFieldNames = true, int pretty = 0 ) const;
00105         operator string() const { return toString(); }
00106 
00108         BSONType type() const { return (BSONType) *data; }
00109 
00113         BSONElement operator[] (const string& field) const;
00114 
00119         int canonicalType() const;
00120 
00124         bool eoo() const { return type() == EOO; }
00125 
00129         int size( int maxLen ) const;
00130         int size() const;
00131 
00133         BSONObj wrap() const;
00134 
00136         BSONObj wrap( const char* newName) const;
00137 
00142         const char * fieldName() const {
00143             if ( eoo() ) return ""; // no fieldname for it.
00144             return data + 1;
00145         }
00146 
00148         const char * value() const {
00149             return (data + fieldNameSize() + 1);
00150         }
00152         int valuesize() const {
00153             return size() - fieldNameSize() - 1;
00154         }
00155 
00156         bool isBoolean() const { return type() == mongo::Bool; }
00157 
00161         bool boolean() const {
00162             return *value() ? true : false;
00163         }
00164 
00165         bool booleanSafe() const { return isBoolean() && boolean(); }
00166 
00171         Date_t date() const {
00172             return *reinterpret_cast< const Date_t* >( value() );
00173         }
00174 
00178         bool trueValue() const;
00179 
00181         bool isSimpleType() const;
00182 
00184         bool isNumber() const;
00185 
00187         double _numberDouble() const {return *reinterpret_cast< const double* >( value() ); }
00189         int _numberInt() const {return *reinterpret_cast< const int* >( value() ); }
00191         long long _numberLong() const {return *reinterpret_cast< const long long* >( value() ); }
00192 
00194         int numberInt() const;
00196         long long numberLong() const;
00200         double numberDouble() const;
00204         double number() const { return numberDouble(); }
00205 
00208         const mongo::OID &__oid() const { return *reinterpret_cast< const mongo::OID* >( value() ); }
00209 
00211         bool isNull() const {
00212             return type() == jstNULL;
00213         }
00214 
00219         int valuestrsize() const {
00220             return *reinterpret_cast< const int* >( value() );
00221         }
00222 
00223         // for objects the size *includes* the size of the size field
00224         int objsize() const {
00225             return *reinterpret_cast< const int* >( value() );
00226         }
00227 
00231         const char * valuestr() const {
00232             return value() + 4;
00233         }
00234 
00236         const char *valuestrsafe() const {
00237             return type() == mongo::String ? valuestr() : "";
00238         }
00240         string str() const {
00241             return type() == mongo::String ? string(valuestr(), valuestrsize()-1) : string();
00242         }
00243 
00245         const char * codeWScopeCode() const {
00246             return value() + 8;
00247         }
00249         const char * codeWScopeScopeData() const {
00250             // TODO fix
00251             return codeWScopeCode() + strlen( codeWScopeCode() ) + 1;
00252         }
00253 
00255         BSONObj embeddedObject() const;
00256 
00257         /* uasserts if not an object */
00258         BSONObj embeddedObjectUserCheck() const;
00259 
00260         BSONObj codeWScopeObject() const;
00261 
00263         const char *binData(int& len) const {
00264             // BinData: <int len> <byte subtype> <byte[len] data>
00265             assert( type() == BinData );
00266             len = valuestrsize();
00267             return value() + 5;
00268         }
00270         const char *binDataClean(int& len) const {
00271             // BinData: <int len> <byte subtype> <byte[len] data>
00272             if (binDataType() != ByteArrayDeprecated) {
00273                 return binData(len);
00274             }
00275             else {
00276                 // Skip extra size
00277                 len = valuestrsize() - 4;
00278                 return value() + 5 + 4;
00279             }
00280         }
00281 
00282         BinDataType binDataType() const {
00283             // BinData: <int len> <byte subtype> <byte[len] data>
00284             assert( type() == BinData );
00285             unsigned char c = (value() + 4)[0];
00286             return (BinDataType)c;
00287         }
00288 
00290         const char *regex() const {
00291             assert(type() == RegEx);
00292             return value();
00293         }
00294 
00296         const char *regexFlags() const {
00297             const char *p = regex();
00298             return p + strlen(p) + 1;
00299         }
00300 
00304         bool valuesEqual(const BSONElement& r) const {
00305             return woCompare( r , false ) == 0;
00306         }
00307 
00309         bool operator==(const BSONElement& r) const {
00310             return woCompare( r , true ) == 0;
00311         }
00313         bool operator!=(const BSONElement& r) const { return !operator==(r); }
00314 
00320         int woCompare( const BSONElement &e, bool considerFieldName = true ) const;
00321 
00322         const char * rawdata() const { return data; }
00323 
00325         int getGtLtOp( int def = 0 ) const;
00326 
00328         BSONElement();
00329 
00331         void validate() const;
00332 
00334         bool mayEncapsulate() const {
00335             switch ( type() ) {
00336             case Object:
00337             case mongo::Array:
00338             case CodeWScope:
00339                 return true;
00340             default:
00341                 return false;
00342             }
00343         }
00344 
00346         bool isABSONObj() const {
00347             switch( type() ) {
00348             case Object:
00349             case mongo::Array:
00350                 return true;
00351             default:
00352                 return false;
00353             }
00354         }
00355 
00356         Date_t timestampTime() const {
00357             unsigned long long t = ((unsigned int*)(value() + 4 ))[0];
00358             return t * 1000;
00359         }
00360         unsigned int timestampInc() const {
00361             return ((unsigned int*)(value() ))[0];
00362         }
00363 
00364         const char * dbrefNS() const {
00365             uassert( 10063 ,  "not a dbref" , type() == DBRef );
00366             return value() + 4;
00367         }
00368 
00369         const mongo::OID& dbrefOID() const {
00370             uassert( 10064 ,  "not a dbref" , type() == DBRef );
00371             const char * start = value();
00372             start += 4 + *reinterpret_cast< const int* >( start );
00373             return *reinterpret_cast< const mongo::OID* >( start );
00374         }
00375 
00377         bool operator<( const BSONElement& other ) const {
00378             int x = (int)canonicalType() - (int)other.canonicalType();
00379             if ( x < 0 ) return true;
00380             else if ( x > 0 ) return false;
00381             return compareElementValues(*this,other) < 0;
00382         }
00383 
00384         // @param maxLen don't scan more than maxLen bytes
00385         explicit BSONElement(const char *d, int maxLen) : data(d) {
00386             if ( eoo() ) {
00387                 totalSize = 1;
00388                 fieldNameSize_ = 0;
00389             }
00390             else {
00391                 totalSize = -1;
00392                 fieldNameSize_ = -1;
00393                 if ( maxLen != -1 ) {
00394                     int size = (int) strnlen( fieldName(), maxLen - 1 );
00395                     uassert( 10333 ,  "Invalid field name", size != -1 );
00396                     fieldNameSize_ = size + 1;
00397                 }
00398             }
00399         }
00400 
00401         explicit BSONElement(const char *d) : data(d) {
00402             fieldNameSize_ = -1;
00403             totalSize = -1;
00404             if ( eoo() ) {
00405                 fieldNameSize_ = 0;
00406                 totalSize = 1;
00407             }
00408         }
00409 
00410         string _asCode() const;
00411         OpTime _opTime() const;
00412 
00413     private:
00414         const char *data;
00415         mutable int fieldNameSize_; // cached value
00416         int fieldNameSize() const {
00417             if ( fieldNameSize_ == -1 )
00418                 fieldNameSize_ = (int)strlen( fieldName() ) + 1;
00419             return fieldNameSize_;
00420         }
00421         mutable int totalSize; /* caches the computed size */
00422 
00423         friend class BSONObjIterator;
00424         friend class BSONObj;
00425         const BSONElement& chk(int t) const {
00426             if ( t != type() ) {
00427                 StringBuilder ss;
00428                 if( eoo() )
00429                     ss << "field not found, expected type " << t;
00430                 else
00431                     ss << "wrong type for field (" << fieldName() << ") " << type() << " != " << t;
00432                 msgasserted(13111, ss.str() );
00433             }
00434             return *this;
00435         }
00436         const BSONElement& chk(bool expr) const {
00437             massert(13118, "unexpected or missing type value in BSON object", expr);
00438             return *this;
00439         }
00440     };
00441 
00442 
00443     inline int BSONElement::canonicalType() const {
00444         BSONType t = type();
00445         switch ( t ) {
00446         case MinKey:
00447         case MaxKey:
00448             return t;
00449         case EOO:
00450         case Undefined:
00451             return 0;
00452         case jstNULL:
00453             return 5;
00454         case NumberDouble:
00455         case NumberInt:
00456         case NumberLong:
00457             return 10;
00458         case mongo::String:
00459         case Symbol:
00460             return 15;
00461         case Object:
00462             return 20;
00463         case mongo::Array:
00464             return 25;
00465         case BinData:
00466             return 30;
00467         case jstOID:
00468             return 35;
00469         case mongo::Bool:
00470             return 40;
00471         case mongo::Date:
00472         case Timestamp:
00473             return 45;
00474         case RegEx:
00475             return 50;
00476         case DBRef:
00477             return 55;
00478         case Code:
00479             return 60;
00480         case CodeWScope:
00481             return 65;
00482         default:
00483             assert(0);
00484             return -1;
00485         }
00486     }
00487 
00488     inline bool BSONElement::trueValue() const {
00489         switch( type() ) {
00490         case NumberLong:
00491             return *reinterpret_cast< const long long* >( value() ) != 0;
00492         case NumberDouble:
00493             return *reinterpret_cast< const double* >( value() ) != 0;
00494         case NumberInt:
00495             return *reinterpret_cast< const int* >( value() ) != 0;
00496         case mongo::Bool:
00497             return boolean();
00498         case EOO:
00499         case jstNULL:
00500         case Undefined:
00501             return false;
00502 
00503         default:
00504             ;
00505         }
00506         return true;
00507     }
00508 
00510     inline bool BSONElement::isNumber() const {
00511         switch( type() ) {
00512         case NumberLong:
00513         case NumberDouble:
00514         case NumberInt:
00515             return true;
00516         default:
00517             return false;
00518         }
00519     }
00520 
00521     inline bool BSONElement::isSimpleType() const {
00522         switch( type() ) {
00523         case NumberLong:
00524         case NumberDouble:
00525         case NumberInt:
00526         case mongo::String:
00527         case mongo::Bool:
00528         case mongo::Date:
00529         case jstOID:
00530             return true;
00531         default:
00532             return false;
00533         }
00534     }
00535 
00536     inline double BSONElement::numberDouble() const {
00537         switch( type() ) {
00538         case NumberDouble:
00539             return _numberDouble();
00540         case NumberInt:
00541             return *reinterpret_cast< const int* >( value() );
00542         case NumberLong:
00543             return (double) *reinterpret_cast< const long long* >( value() );
00544         default:
00545             return 0;
00546         }
00547     }
00548 
00550     inline int BSONElement::numberInt() const {
00551         switch( type() ) {
00552         case NumberDouble:
00553             return (int) _numberDouble();
00554         case NumberInt:
00555             return _numberInt();
00556         case NumberLong:
00557             return (int) _numberLong();
00558         default:
00559             return 0;
00560         }
00561     }
00562 
00564     inline long long BSONElement::numberLong() const {
00565         switch( type() ) {
00566         case NumberDouble:
00567             return (long long) _numberDouble();
00568         case NumberInt:
00569             return _numberInt();
00570         case NumberLong:
00571             return _numberLong();
00572         default:
00573             return 0;
00574         }
00575     }
00576 
00577     inline BSONElement::BSONElement() {
00578         static char z = 0;
00579         data = &z;
00580         fieldNameSize_ = 0;
00581         totalSize = 1;
00582     }
00583 
00584 }