|
MongoDB
2.1.1-pre-
|
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 }
1.8.0