diff options
Diffstat (limited to 'src/mongo/bson/bsonobjbuilder.cpp')
-rw-r--r-- | src/mongo/bson/bsonobjbuilder.cpp | 328 |
1 files changed, 175 insertions, 153 deletions
diff --git a/src/mongo/bson/bsonobjbuilder.cpp b/src/mongo/bson/bsonobjbuilder.cpp index a9878b28adc..7a5b04a3fa5 100644 --- a/src/mongo/bson/bsonobjbuilder.cpp +++ b/src/mongo/bson/bsonobjbuilder.cpp @@ -38,243 +38,265 @@ namespace mongo { - using std::string; +using std::string; - void BSONObjBuilder::appendMinForType( StringData fieldName , int t ) { - switch ( t ) { - +void BSONObjBuilder::appendMinForType(StringData fieldName, int t) { + switch (t) { // Shared canonical types case NumberInt: case NumberDouble: case NumberLong: - append( fieldName , - std::numeric_limits<double>::max() ); return; + append(fieldName, -std::numeric_limits<double>::max()); + return; case Symbol: case String: - append( fieldName , "" ); return; - case Date: + append(fieldName, ""); + return; + case Date: // min varies with V0 and V1 indexes, so we go one type lower. appendBool(fieldName, true); - //appendDate( fieldName , numeric_limits<long long>::min() ); + // appendDate( fieldName , numeric_limits<long long>::min() ); return; case bsonTimestamp: - appendTimestamp( fieldName , 0 ); return; - case Undefined: // shared with EOO - appendUndefined( fieldName ); return; - + appendTimestamp(fieldName, 0); + return; + case Undefined: // shared with EOO + appendUndefined(fieldName); + return; + // Separate canonical types case MinKey: - appendMinKey( fieldName ); return; + appendMinKey(fieldName); + return; case MaxKey: - appendMaxKey( fieldName ); return; + appendMaxKey(fieldName); + return; case jstOID: { OID o; - appendOID( fieldName , &o); + appendOID(fieldName, &o); return; } case Bool: - appendBool( fieldName , false); return; + appendBool(fieldName, false); + return; case jstNULL: - appendNull( fieldName ); return; + appendNull(fieldName); + return; case Object: - append( fieldName , BSONObj() ); return; + append(fieldName, BSONObj()); + return; case Array: - appendArray( fieldName , BSONObj() ); return; + appendArray(fieldName, BSONObj()); + return; case BinData: - appendBinData( fieldName , 0 , BinDataGeneral , (const char *) 0 ); return; + appendBinData(fieldName, 0, BinDataGeneral, (const char*)0); + return; case RegEx: - appendRegex( fieldName , "" ); return; + appendRegex(fieldName, ""); + return; case DBRef: { OID o; - appendDBRef( fieldName , "" , o ); + appendDBRef(fieldName, "", o); return; } case Code: - appendCode( fieldName , "" ); return; + appendCode(fieldName, ""); + return; case CodeWScope: - appendCodeWScope( fieldName , "" , BSONObj() ); return; - }; - log() << "type not supported for appendMinElementForType: " << t; - uassert( 10061 , "type not supported for appendMinElementForType" , false ); - } + appendCodeWScope(fieldName, "", BSONObj()); + return; + }; + log() << "type not supported for appendMinElementForType: " << t; + uassert(10061, "type not supported for appendMinElementForType", false); +} - void BSONObjBuilder::appendMaxForType( StringData fieldName , int t ) { - switch ( t ) { - +void BSONObjBuilder::appendMaxForType(StringData fieldName, int t) { + switch (t) { // Shared canonical types case NumberInt: case NumberDouble: case NumberLong: - append( fieldName , std::numeric_limits<double>::max() ); return; + append(fieldName, std::numeric_limits<double>::max()); + return; case Symbol: case String: - appendMinForType( fieldName, Object ); return; + appendMinForType(fieldName, Object); + return; case Date: appendDate(fieldName, Date_t::fromMillisSinceEpoch(std::numeric_limits<long long>::max())); return; case bsonTimestamp: - append( fieldName , Timestamp::max() ); return; - case Undefined: // shared with EOO - appendUndefined( fieldName ); return; + append(fieldName, Timestamp::max()); + return; + case Undefined: // shared with EOO + appendUndefined(fieldName); + return; // Separate canonical types case MinKey: - appendMinKey( fieldName ); return; + appendMinKey(fieldName); + return; case MaxKey: - appendMaxKey( fieldName ); return; + appendMaxKey(fieldName); + return; case jstOID: { OID o = OID::max(); - appendOID( fieldName , &o); + appendOID(fieldName, &o); return; } case Bool: - appendBool( fieldName , true ); return; + appendBool(fieldName, true); + return; case jstNULL: - appendNull( fieldName ); return; + appendNull(fieldName); + return; case Object: - appendMinForType( fieldName, Array ); return; + appendMinForType(fieldName, Array); + return; case Array: - appendMinForType( fieldName, BinData ); return; + appendMinForType(fieldName, BinData); + return; case BinData: - appendMinForType( fieldName, jstOID ); return; + appendMinForType(fieldName, jstOID); + return; case RegEx: - appendMinForType( fieldName, DBRef ); return; + appendMinForType(fieldName, DBRef); + return; case DBRef: - appendMinForType( fieldName, Code ); return; + appendMinForType(fieldName, Code); + return; case Code: - appendMinForType( fieldName, CodeWScope ); return; + appendMinForType(fieldName, CodeWScope); + return; case CodeWScope: // This upper bound may change if a new bson type is added. - appendMinForType( fieldName , MaxKey ); return; - } - log() << "type not supported for appendMaxElementForType: " << t; - uassert( 14853 , "type not supported for appendMaxElementForType" , false ); + appendMinForType(fieldName, MaxKey); + return; } + log() << "type not supported for appendMaxElementForType: " << t; + uassert(14853, "type not supported for appendMaxElementForType", false); +} - bool BSONObjBuilder::appendAsNumber( StringData fieldName , const string& data ) { - if ( data.size() == 0 || data == "-" || data == ".") - return false; - - unsigned int pos=0; - if ( data[0] == '-' ) - pos++; - - bool hasDec = false; - - for ( ; pos<data.size(); pos++ ) { - if ( isdigit(data[pos]) ) - continue; +bool BSONObjBuilder::appendAsNumber(StringData fieldName, const string& data) { + if (data.size() == 0 || data == "-" || data == ".") + return false; - if ( data[pos] == '.' ) { - if ( hasDec ) - return false; - hasDec = true; - continue; - } + unsigned int pos = 0; + if (data[0] == '-') + pos++; - return false; - } + bool hasDec = false; - if ( hasDec ) { - double d = atof( data.c_str() ); - append( fieldName , d ); - return true; - } + for (; pos < data.size(); pos++) { + if (isdigit(data[pos])) + continue; - if ( data.size() < 8 ) { - append( fieldName , atoi( data.c_str() ) ); - return true; + if (data[pos] == '.') { + if (hasDec) + return false; + hasDec = true; + continue; } - try { - long long num = boost::lexical_cast<long long>( data ); - append( fieldName , num ); - return true; - } - catch(boost::bad_lexical_cast &) { - return false; - } + return false; } - BSONObjBuilder& BSONObjBuilder::appendDate(StringData fieldName, Date_t dt) { - _b.appendNum((char) Date); - _b.appendStr(fieldName); - _b.appendNum(dt.toMillisSinceEpoch()); - return *this; + if (hasDec) { + double d = atof(data.c_str()); + append(fieldName, d); + return true; } - /* add all the fields from the object specified to this object */ - BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) { - if (!x.isEmpty()) - _b.appendBuf( - x.objdata() + 4, // skip over leading length - x.objsize() - 5); // ignore leading length and trailing \0 - return *this; + if (data.size() < 8) { + append(fieldName, atoi(data.c_str())); + return true; } - /* add all the fields from the object specified to this object if they don't exist */ - BSONObjBuilder& BSONObjBuilder::appendElementsUnique(BSONObj x) { - std::set<std::string> have; - { - BSONObjIterator i = iterator(); - while ( i.more() ) - have.insert( i.next().fieldName() ); - } - - BSONObjIterator it(x); - while ( it.more() ) { - BSONElement e = it.next(); - if ( have.count( e.fieldName() ) ) - continue; - append(e); - } - return *this; + try { + long long num = boost::lexical_cast<long long>(data); + append(fieldName, num); + return true; + } catch (boost::bad_lexical_cast&) { + return false; } +} - void BSONObjBuilder::appendKeys( const BSONObj& keyPattern , const BSONObj& values ) { - BSONObjIterator i(keyPattern); - BSONObjIterator j(values); +BSONObjBuilder& BSONObjBuilder::appendDate(StringData fieldName, Date_t dt) { + _b.appendNum((char)Date); + _b.appendStr(fieldName); + _b.appendNum(dt.toMillisSinceEpoch()); + return *this; +} - while ( i.more() && j.more() ) { - appendAs( j.next() , i.next().fieldName() ); - } +/* add all the fields from the object specified to this object */ +BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) { + if (!x.isEmpty()) + _b.appendBuf(x.objdata() + 4, // skip over leading length + x.objsize() - 5); // ignore leading length and trailing \0 + return *this; +} - verify( ! i.more() ); - verify( ! j.more() ); +/* add all the fields from the object specified to this object if they don't exist */ +BSONObjBuilder& BSONObjBuilder::appendElementsUnique(BSONObj x) { + std::set<std::string> have; + { + BSONObjIterator i = iterator(); + while (i.more()) + have.insert(i.next().fieldName()); } - BSONObjIterator BSONObjBuilder::iterator() const { - const char * s = _b.buf() + _offset; - const char * e = _b.buf() + _b.len(); - return BSONObjIterator( s , e ); + BSONObjIterator it(x); + while (it.more()) { + BSONElement e = it.next(); + if (have.count(e.fieldName())) + continue; + append(e); } + return *this; +} - bool BSONObjBuilder::hasField( StringData name ) const { - BSONObjIterator i = iterator(); - while ( i.more() ) - if ( name == i.next().fieldName() ) - return true; - return false; +void BSONObjBuilder::appendKeys(const BSONObj& keyPattern, const BSONObj& values) { + BSONObjIterator i(keyPattern); + BSONObjIterator j(values); + + while (i.more() && j.more()) { + appendAs(j.next(), i.next().fieldName()); } - const string BSONObjBuilder::numStrs[] = { - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", - "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", - "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", - "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", - "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", - "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", - "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", - "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", - "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", - }; + verify(!i.more()); + verify(!j.more()); +} + +BSONObjIterator BSONObjBuilder::iterator() const { + const char* s = _b.buf() + _offset; + const char* e = _b.buf() + _b.len(); + return BSONObjIterator(s, e); +} + +bool BSONObjBuilder::hasField(StringData name) const { + BSONObjIterator i = iterator(); + while (i.more()) + if (name == i.next().fieldName()) + return true; + return false; +} + +const string BSONObjBuilder::numStrs[] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", + "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", + "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", + "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", +}; - // This is to ensure that BSONObjBuilder doesn't try to use numStrs before the strings have - // been constructed I've tested just making numStrs a char[][], but the overhead of - // constructing the strings each time was too high numStrsReady will be 0 until after - // numStrs is initialized because it is a static variable - bool BSONObjBuilder::numStrsReady = (numStrs[0].size() > 0); +// This is to ensure that BSONObjBuilder doesn't try to use numStrs before the strings have +// been constructed I've tested just making numStrs a char[][], but the overhead of +// constructing the strings each time was too high numStrsReady will be 0 until after +// numStrs is initialized because it is a static variable +bool BSONObjBuilder::numStrsReady = (numStrs[0].size() > 0); -} // namespace mongo +} // namespace mongo |