|
MongoDB
2.0.3
|
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 }
1.8.0