00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #pragma once
00019
00020 #include <map>
00021 #include "util/atomic_int.h"
00022 #include "util/misc.h"
00023 #include "../util/hex.h"
00024
00025 namespace mongo {
00026
00027 inline BSONObjIterator BSONObj::begin() {
00028 return BSONObjIterator(*this);
00029 }
00030
00031 inline BSONObj BSONElement::embeddedObjectUserCheck() const {
00032 if ( isABSONObj() )
00033 return BSONObj(value());
00034 stringstream ss;
00035 ss << "invalid parameter: expected an object (" << fieldName() << ")";
00036 uasserted( 10065 , ss.str() );
00037 return BSONObj();
00038 }
00039
00040 inline BSONObj BSONElement::embeddedObject() const {
00041 assert( isABSONObj() );
00042 return BSONObj(value());
00043 }
00044
00045 inline BSONObj BSONElement::codeWScopeObject() const {
00046 assert( type() == CodeWScope );
00047 int strSizeWNull = *(int *)( value() + 4 );
00048 return BSONObj( value() + 4 + 4 + strSizeWNull );
00049 }
00050
00051 inline NOINLINE_DECL void BSONObj::_assertInvalid() const {
00052 StringBuilder ss;
00053 int os = objsize();
00054 ss << "Invalid BSONObj size: " << os << " (0x" << toHex( &os, 4 ) << ')';
00055 try {
00056 BSONElement e = firstElement();
00057 ss << " first element: " << e.toString();
00058 }
00059 catch ( ... ) { }
00060 massert( 10334 , ss.str() , 0 );
00061 }
00062
00063
00064
00065
00066 inline NOINLINE_DECL BSONObj BSONObj::copy() const {
00067 char *p = (char*) malloc(objsize());
00068 memcpy(p, objdata(), objsize());
00069 return BSONObj(p, true);
00070 }
00071
00072 inline BSONObj BSONObj::getOwned() const {
00073 if ( isOwned() )
00074 return *this;
00075 return copy();
00076 }
00077
00078
00079 inline BSONObj BSONElement::wrap() const {
00080 BSONObjBuilder b(size()+6);
00081 b.append(*this);
00082 return b.obj();
00083 }
00084
00085 inline BSONObj BSONElement::wrap( const char * newName ) const {
00086 BSONObjBuilder b(size()+6+(int)strlen(newName));
00087 b.appendAs(*this,newName);
00088 return b.obj();
00089 }
00090
00091 inline bool BSONObj::hasElement(const char *name) const {
00092 if ( !isEmpty() ) {
00093 BSONObjIterator it(*this);
00094 while ( it.moreWithEOO() ) {
00095 BSONElement e = it.next();
00096 if ( strcmp(name, e.fieldName()) == 0 )
00097 return true;
00098 }
00099 }
00100 return false;
00101 }
00102
00103 inline BSONElement BSONObj::getField(const StringData& name) const {
00104 BSONObjIterator i(*this);
00105 while ( i.more() ) {
00106 BSONElement e = i.next();
00107 if ( strcmp(e.fieldName(), name.data()) == 0 )
00108 return e;
00109 }
00110 return BSONElement();
00111 }
00112
00113
00114 inline BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) {
00115 BSONObjIterator it(x);
00116 while ( it.moreWithEOO() ) {
00117 BSONElement e = it.next();
00118 if ( e.eoo() ) break;
00119 append(e);
00120 }
00121 return *this;
00122 }
00123
00124
00125 inline BSONObjBuilder& BSONObjBuilder::appendElementsUnique(BSONObj x) {
00126 set<string> have;
00127 {
00128 BSONObjIterator i = iterator();
00129 while ( i.more() )
00130 have.insert( i.next().fieldName() );
00131 }
00132
00133 BSONObjIterator it(x);
00134 while ( it.more() ) {
00135 BSONElement e = it.next();
00136 if ( have.count( e.fieldName() ) )
00137 continue;
00138 append(e);
00139 }
00140 return *this;
00141 }
00142
00143
00144 inline bool BSONObj::isValid() {
00145 int x = objsize();
00146 return x > 0 && x <= BSONObjMaxInternalSize;
00147 }
00148
00149 inline bool BSONObj::getObjectID(BSONElement& e) const {
00150 BSONElement f = getField("_id");
00151 if( !f.eoo() ) {
00152 e = f;
00153 return true;
00154 }
00155 return false;
00156 }
00157
00158 inline BSONObjBuilderValueStream::BSONObjBuilderValueStream( BSONObjBuilder * builder ) {
00159 _fieldName = 0;
00160 _builder = builder;
00161 }
00162
00163 template<class T>
00164 inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( T value ) {
00165 _builder->append(_fieldName, value);
00166 _fieldName = 0;
00167 return *_builder;
00168 }
00169
00170 inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( const BSONElement& e ) {
00171 _builder->appendAs( e , _fieldName );
00172 _fieldName = 0;
00173 return *_builder;
00174 }
00175
00176 inline Labeler BSONObjBuilderValueStream::operator<<( const Labeler::Label &l ) {
00177 return Labeler( l, this );
00178 }
00179
00180 inline void BSONObjBuilderValueStream::endField( const char *nextFieldName ) {
00181 if ( _fieldName && haveSubobj() ) {
00182 _builder->append( _fieldName, subobj()->done() );
00183 }
00184 _subobj.reset();
00185 _fieldName = nextFieldName;
00186 }
00187
00188 inline BSONObjBuilder *BSONObjBuilderValueStream::subobj() {
00189 if ( !haveSubobj() )
00190 _subobj.reset( new BSONObjBuilder() );
00191 return _subobj.get();
00192 }
00193
00194 template<class T> inline
00195 BSONObjBuilder& Labeler::operator<<( T value ) {
00196 s_->subobj()->append( l_.l_, value );
00197 return *s_->_builder;
00198 }
00199
00200 inline
00201 BSONObjBuilder& Labeler::operator<<( const BSONElement& e ) {
00202 s_->subobj()->appendAs( e, l_.l_ );
00203 return *s_->_builder;
00204 }
00205
00206
00207 void nested2dotted(BSONObjBuilder& b, const BSONObj& obj, const string& base="");
00208 inline BSONObj nested2dotted(const BSONObj& obj) {
00209 BSONObjBuilder b;
00210 nested2dotted(b, obj);
00211 return b.obj();
00212 }
00213
00214
00215 void dotted2nested(BSONObjBuilder& b, const BSONObj& obj);
00216 inline BSONObj dotted2nested(const BSONObj& obj) {
00217 BSONObjBuilder b;
00218 dotted2nested(b, obj);
00219 return b.obj();
00220 }
00221
00222 inline BSONObjIterator BSONObjBuilder::iterator() const {
00223 const char * s = _b.buf() + _offset;
00224 const char * e = _b.buf() + _b.len();
00225 return BSONObjIterator( s , e );
00226 }
00227
00228 inline bool BSONObjBuilder::hasField( const StringData& name ) const {
00229 BSONObjIterator i = iterator();
00230 while ( i.more() )
00231 if ( strcmp( name.data() , i.next().fieldName() ) == 0 )
00232 return true;
00233 return false;
00234 }
00235
00236
00237
00238
00239
00240
00241 typedef map<string, BSONElement> BSONMap;
00242 inline BSONMap bson2map(const BSONObj& obj) {
00243 BSONMap m;
00244 BSONObjIterator it(obj);
00245 while (it.more()) {
00246 BSONElement e = it.next();
00247 m[e.fieldName()] = e;
00248 }
00249 return m;
00250 }
00251
00252 struct BSONElementFieldNameCmp {
00253 bool operator()( const BSONElement &l, const BSONElement &r ) const {
00254 return strcmp( l.fieldName() , r.fieldName() ) <= 0;
00255 }
00256 };
00257
00258 typedef set<BSONElement, BSONElementFieldNameCmp> BSONSortedElements;
00259 inline BSONSortedElements bson2set( const BSONObj& obj ) {
00260 BSONSortedElements s;
00261 BSONObjIterator it(obj);
00262 while ( it.more() )
00263 s.insert( it.next() );
00264 return s;
00265 }
00266
00267 inline string BSONObj::toString( bool isArray, bool full ) const {
00268 if ( isEmpty() ) return "{}";
00269 StringBuilder s;
00270 toString(s, isArray, full);
00271 return s.str();
00272 }
00273 inline void BSONObj::toString(StringBuilder& s, bool isArray, bool full ) const {
00274 if ( isEmpty() ) {
00275 s << "{}";
00276 return;
00277 }
00278
00279 s << ( isArray ? "[ " : "{ " );
00280 BSONObjIterator i(*this);
00281 bool first = true;
00282 while ( 1 ) {
00283 massert( 10327 , "Object does not end with EOO", i.moreWithEOO() );
00284 BSONElement e = i.next( true );
00285 massert( 10328 , "Invalid element size", e.size() > 0 );
00286 massert( 10329 , "Element too large", e.size() < ( 1 << 30 ) );
00287 int offset = (int) (e.rawdata() - this->objdata());
00288 massert( 10330 , "Element extends past end of object",
00289 e.size() + offset <= this->objsize() );
00290 e.validate();
00291 bool end = ( e.size() + offset == this->objsize() );
00292 if ( e.eoo() ) {
00293 massert( 10331 , "EOO Before end of object", end );
00294 break;
00295 }
00296 if ( first )
00297 first = false;
00298 else
00299 s << ", ";
00300 e.toString(s, !isArray, full );
00301 }
00302 s << ( isArray ? " ]" : " }" );
00303 }
00304
00305 extern unsigned getRandomNumber();
00306
00307 inline void BSONElement::validate() const {
00308 const BSONType t = type();
00309
00310 switch( t ) {
00311 case DBRef:
00312 case Code:
00313 case Symbol:
00314 case mongo::String: {
00315 unsigned x = (unsigned) valuestrsize();
00316 bool lenOk = x > 0 && x < (unsigned) BSONObjMaxInternalSize;
00317 if( lenOk && valuestr()[x-1] == 0 )
00318 return;
00319 StringBuilder buf;
00320 buf << "Invalid dbref/code/string/symbol size: " << x;
00321 if( lenOk )
00322 buf << " strnlen:" << mongo::strnlen( valuestr() , x );
00323 msgasserted( 10321 , buf.str() );
00324 break;
00325 }
00326 case CodeWScope: {
00327 int totalSize = *( int * )( value() );
00328 massert( 10322 , "Invalid CodeWScope size", totalSize >= 8 );
00329 int strSizeWNull = *( int * )( value() + 4 );
00330 massert( 10323 , "Invalid CodeWScope string size", totalSize >= strSizeWNull + 4 + 4 );
00331 massert( 10324 , "Invalid CodeWScope string size",
00332 strSizeWNull > 0 &&
00333 (strSizeWNull - 1) == mongo::strnlen( codeWScopeCode(), strSizeWNull ) );
00334 massert( 10325 , "Invalid CodeWScope size", totalSize >= strSizeWNull + 4 + 4 + 4 );
00335 int objSize = *( int * )( value() + 4 + 4 + strSizeWNull );
00336 massert( 10326 , "Invalid CodeWScope object size", totalSize == 4 + 4 + strSizeWNull + objSize );
00337
00338 }
00339 case Object:
00340
00341 default:
00342 break;
00343 }
00344 }
00345
00346 inline int BSONElement::size( int maxLen ) const {
00347 if ( totalSize >= 0 )
00348 return totalSize;
00349
00350 int remain = maxLen - fieldNameSize() - 1;
00351
00352 int x = 0;
00353 switch ( type() ) {
00354 case EOO:
00355 case Undefined:
00356 case jstNULL:
00357 case MaxKey:
00358 case MinKey:
00359 break;
00360 case mongo::Bool:
00361 x = 1;
00362 break;
00363 case NumberInt:
00364 x = 4;
00365 break;
00366 case Timestamp:
00367 case mongo::Date:
00368 case NumberDouble:
00369 case NumberLong:
00370 x = 8;
00371 break;
00372 case jstOID:
00373 x = 12;
00374 break;
00375 case Symbol:
00376 case Code:
00377 case mongo::String:
00378 massert( 10313 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
00379 x = valuestrsize() + 4;
00380 break;
00381 case CodeWScope:
00382 massert( 10314 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
00383 x = objsize();
00384 break;
00385
00386 case DBRef:
00387 massert( 10315 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
00388 x = valuestrsize() + 4 + 12;
00389 break;
00390 case Object:
00391 case mongo::Array:
00392 massert( 10316 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
00393 x = objsize();
00394 break;
00395 case BinData:
00396 massert( 10317 , "Insufficient bytes to calculate element size", maxLen == -1 || remain > 3 );
00397 x = valuestrsize() + 4 + 1;
00398 break;
00399 case RegEx: {
00400 const char *p = value();
00401 size_t len1 = ( maxLen == -1 ) ? strlen( p ) : mongo::strnlen( p, remain );
00402
00403 p = p + len1 + 1;
00404 size_t len2;
00405 if( maxLen == -1 )
00406 len2 = strlen( p );
00407 else {
00408 size_t x = remain - len1 - 1;
00409 assert( x <= 0x7fffffff );
00410 len2 = mongo::strnlen( p, (int) x );
00411 }
00412
00413 x = (int) (len1 + 1 + len2 + 1);
00414 }
00415 break;
00416 default: {
00417 StringBuilder ss;
00418 ss << "BSONElement: bad type " << (int) type();
00419 string msg = ss.str();
00420 massert( 10320 , msg.c_str(),false);
00421 }
00422 }
00423 totalSize = x + fieldNameSize() + 1;
00424
00425 return totalSize;
00426 }
00427
00428 inline string BSONElement::toString( bool includeFieldName, bool full ) const {
00429 StringBuilder s;
00430 toString(s, includeFieldName, full);
00431 return s.str();
00432 }
00433 inline void BSONElement::toString(StringBuilder& s, bool includeFieldName, bool full ) const {
00434 if ( includeFieldName && type() != EOO )
00435 s << fieldName() << ": ";
00436 switch ( type() ) {
00437 case EOO:
00438 s << "EOO";
00439 break;
00440 case mongo::Date:
00441 s << "new Date(" << date() << ')';
00442 break;
00443 case RegEx: {
00444 s << "/" << regex() << '/';
00445 const char *p = regexFlags();
00446 if ( p ) s << p;
00447 }
00448 break;
00449 case NumberDouble:
00450 s.appendDoubleNice( number() );
00451 break;
00452 case NumberLong:
00453 s << _numberLong();
00454 break;
00455 case NumberInt:
00456 s << _numberInt();
00457 break;
00458 case mongo::Bool:
00459 s << ( boolean() ? "true" : "false" );
00460 break;
00461 case Object:
00462 embeddedObject().toString(s, false, full);
00463 break;
00464 case mongo::Array:
00465 embeddedObject().toString(s, true, full);
00466 break;
00467 case Undefined:
00468 s << "undefined";
00469 break;
00470 case jstNULL:
00471 s << "null";
00472 break;
00473 case MaxKey:
00474 s << "MaxKey";
00475 break;
00476 case MinKey:
00477 s << "MinKey";
00478 break;
00479 case CodeWScope:
00480 s << "CodeWScope( "
00481 << codeWScopeCode() << ", " << codeWScopeObject().toString(false, full) << ")";
00482 break;
00483 case Code:
00484 if ( !full && valuestrsize() > 80 ) {
00485 s.write(valuestr(), 70);
00486 s << "...";
00487 }
00488 else {
00489 s.write(valuestr(), valuestrsize()-1);
00490 }
00491 break;
00492 case Symbol:
00493 case mongo::String:
00494 s << '"';
00495 if ( !full && valuestrsize() > 80 ) {
00496 s.write(valuestr(), 70);
00497 s << "...\"";
00498 }
00499 else {
00500 s.write(valuestr(), valuestrsize()-1);
00501 s << '"';
00502 }
00503 break;
00504 case DBRef:
00505 s << "DBRef('" << valuestr() << "',";
00506 {
00507 mongo::OID *x = (mongo::OID *) (valuestr() + valuestrsize());
00508 s << *x << ')';
00509 }
00510 break;
00511 case jstOID:
00512 s << "ObjectId('";
00513 s << __oid() << "')";
00514 break;
00515 case BinData:
00516 s << "BinData";
00517 if (full) {
00518 int len;
00519 const char* data = binDataClean(len);
00520 s << '(' << binDataType() << ", " << toHex(data, len) << ')';
00521 }
00522 break;
00523 case Timestamp:
00524 s << "Timestamp " << timestampTime() << "|" << timestampInc();
00525 break;
00526 default:
00527 s << "?type=" << type();
00528 break;
00529 }
00530 }
00531
00532
00533
00534
00535 inline BSONElement BSONObj::getFieldDotted(const char *name) const {
00536 BSONElement e = getField( name );
00537 if ( e.eoo() ) {
00538 const char *p = strchr(name, '.');
00539 if ( p ) {
00540 string left(name, p-name);
00541 BSONObj sub = getObjectField(left.c_str());
00542 return sub.isEmpty() ? BSONElement() : sub.getFieldDotted(p+1);
00543 }
00544 }
00545
00546 return e;
00547 }
00548
00549 inline BSONObj BSONObj::getObjectField(const char *name) const {
00550 BSONElement e = getField(name);
00551 BSONType t = e.type();
00552 return t == Object || t == Array ? e.embeddedObject() : BSONObj();
00553 }
00554
00555 inline int BSONObj::nFields() const {
00556 int n = 0;
00557 BSONObjIterator i(*this);
00558 while ( i.moreWithEOO() ) {
00559 BSONElement e = i.next();
00560 if ( e.eoo() )
00561 break;
00562 n++;
00563 }
00564 return n;
00565 }
00566
00567 inline BSONObj::BSONObj() {
00568
00569
00570
00571
00572 static char p[] = { 5, 0, 0, 0, 0 };
00573 _objdata = p;
00574 }
00575
00576 inline BSONObj BSONElement::Obj() const { return embeddedObjectUserCheck(); }
00577
00578 inline BSONElement BSONElement::operator[] (const string& field) const {
00579 BSONObj o = Obj();
00580 return o[field];
00581 }
00582
00583 inline void BSONObj::elems(vector<BSONElement> &v) const {
00584 BSONObjIterator i(*this);
00585 while( i.more() )
00586 v.push_back(i.next());
00587 }
00588
00589 inline void BSONObj::elems(list<BSONElement> &v) const {
00590 BSONObjIterator i(*this);
00591 while( i.more() )
00592 v.push_back(i.next());
00593 }
00594
00595 template <class T>
00596 void BSONObj::Vals(vector<T>& v) const {
00597 BSONObjIterator i(*this);
00598 while( i.more() ) {
00599 T t;
00600 i.next().Val(t);
00601 v.push_back(t);
00602 }
00603 }
00604 template <class T>
00605 void BSONObj::Vals(list<T>& v) const {
00606 BSONObjIterator i(*this);
00607 while( i.more() ) {
00608 T t;
00609 i.next().Val(t);
00610 v.push_back(t);
00611 }
00612 }
00613
00614 template <class T>
00615 void BSONObj::vals(vector<T>& v) const {
00616 BSONObjIterator i(*this);
00617 while( i.more() ) {
00618 try {
00619 T t;
00620 i.next().Val(t);
00621 v.push_back(t);
00622 }
00623 catch(...) { }
00624 }
00625 }
00626 template <class T>
00627 void BSONObj::vals(list<T>& v) const {
00628 BSONObjIterator i(*this);
00629 while( i.more() ) {
00630 try {
00631 T t;
00632 i.next().Val(t);
00633 v.push_back(t);
00634 }
00635 catch(...) { }
00636 }
00637 }
00638
00639 inline ostream& operator<<( ostream &s, const BSONObj &o ) {
00640 return s << o.toString();
00641 }
00642
00643 inline ostream& operator<<( ostream &s, const BSONElement &e ) {
00644 return s << e.toString();
00645 }
00646
00647 inline StringBuilder& operator<<( StringBuilder &s, const BSONObj &o ) {
00648 o.toString( s );
00649 return s;
00650 }
00651 inline StringBuilder& operator<<( StringBuilder &s, const BSONElement &e ) {
00652 e.toString( s );
00653 return s;
00654 }
00655
00656
00657 inline void BSONElement::Val(BSONObj& v) const { v = Obj(); }
00658
00659 template<typename T>
00660 inline BSONFieldValue<BSONObj> BSONField<T>::query( const char * q , const T& t ) const {
00661 BSONObjBuilder b;
00662 b.append( q , t );
00663 return BSONFieldValue<BSONObj>( _name , b.obj() );
00664 }
00665 }