Status saslExtractPayload(const BSONObj& cmdObj, std::string* payload, BSONType* type) { BSONElement payloadElement; Status status = bsonExtractField(cmdObj, saslCommandPayloadFieldName, &payloadElement); if (!status.isOK()) return status; *type = payloadElement.type(); if (payloadElement.type() == BinData) { const char* payloadData; int payloadLen; payloadData = payloadElement.binData(payloadLen); if (payloadLen < 0) return Status(ErrorCodes::InvalidLength, "Negative payload length"); *payload = std::string(payloadData, payloadData + payloadLen); } else if (payloadElement.type() == String) { try { *payload = base64::decode(payloadElement.str()); } catch (UserException& e) { return Status(ErrorCodes::FailedToParse, e.what()); } } else { return Status(ErrorCodes::TypeMismatch, (str::stream() << "Wrong type for field; expected BinData or String for " << payloadElement)); } return Status::OK(); }
void pp( const char * s , BSONElement e ){ int len; const char * data = e.binData( len ); cout << s << ":" << e.binDataType() << "\t" << len << endl; cout << "\t"; for ( int i=0; i<len; i++ ) cout << (int)(data[i]) << " "; cout << endl; }
StatusWith<LogicalTimeMetadata> LogicalTimeMetadata::readFromMetadata( const BSONElement& metadataElem) { if (metadataElem.eoo()) { return LogicalTimeMetadata(); } const auto& obj = metadataElem.Obj(); Timestamp ts; Status status = bsonExtractTimestampField(obj, kClusterTimeFieldName, &ts); if (!status.isOK()) { return status; } BSONElement signatureElem; status = bsonExtractTypedField(obj, kSignatureFieldName, Object, &signatureElem); if (!status.isOK()) { return status; } const auto& signatureObj = signatureElem.Obj(); // Extract BinData type signature hash and construct a SHA1Block instance from it. BSONElement hashElem; status = bsonExtractTypedField(signatureObj, kSignatureHashFieldName, BinData, &hashElem); if (!status.isOK()) { return status; } int hashLength = 0; auto rawBinSignature = hashElem.binData(hashLength); BSONBinData proofBinData(rawBinSignature, hashLength, hashElem.binDataType()); auto proofStatus = SHA1Block::fromBinData(proofBinData); if (!proofStatus.isOK()) { return proofStatus.getStatus(); } long long keyId; status = bsonExtractIntegerField(signatureObj, kSignatureKeyIdFieldName, &keyId); if (!status.isOK()) { return status; } return LogicalTimeMetadata( SignedLogicalTime(LogicalTime(ts), std::move(proofStatus.getValue()), keyId)); }
bool BitTestMatchExpression::matchesSingleElement(const BSONElement& e, MatchDetails* details) const { // Validate 'e' is a number or a BinData. if (!e.isNumber() && e.type() != BSONType::BinData) { return false; } if (e.type() == BSONType::BinData) { int eBinaryLen; // Length of eBinary (in bytes). const char* eBinary = e.binData(eBinaryLen); return performBitTest(eBinary, eBinaryLen); } invariant(e.isNumber()); if (e.type() == BSONType::NumberDouble) { double eDouble = e.numberDouble(); // NaN doubles are rejected. if (std::isnan(eDouble)) { return false; } // Integral doubles that are too large or small to be represented as a 64-bit signed // integer are treated as 0. We use 'kLongLongMaxAsDouble' because if we just did // eDouble > 2^63-1, it would be compared against 2^63. eDouble=2^63 would not get caught // that way. if (eDouble >= BSONElement::kLongLongMaxPlusOneAsDouble || eDouble < std::numeric_limits<long long>::min()) { return false; } // This checks if e is an integral double. if (eDouble != static_cast<double>(static_cast<long long>(eDouble))) { return false; } } long long eValue = e.numberLong(); return performBitTest(eValue); }
StatusWith<std::vector<BSONObj>> getMetricsFromMetricDoc(const BSONObj& obj, FTDCDecompressor* decompressor) { if (kDebugBuild) { auto swType = getBSONDocumentType(obj); dassert(swType.isOK() && swType.getValue() == FTDCType::kMetricChunk); } BSONElement element; Status status = bsonExtractTypedField(obj, kFTDCDataField, BSONType::BinData, &element); if (!status.isOK()) { return {status}; } int length; const char* buffer = element.binData(length); if (length < 0) { return {ErrorCodes::BadValue, str::stream() << "Field " << std::string(kFTDCTypeField) << " is not a BinData."}; } return decompressor->uncompress({buffer, static_cast<std::size_t>(length)}); }
int main() { cout << "build bits: " << 8 * sizeof(char *) << '\n' << endl; /* a bson object defaults on construction to { } */ bo empty; cout << "empty: " << empty << endl; /* make a simple { name : 'joe', age : 33.7 } object */ { bob b; b.append("name", "joe"); b.append("age", 33.7); bo c = b.obj(); cout << "c: " << c << endl; } /* make { name : 'joe', age : 33.7 } with a more compact notation. */ bo x = bob().append("name", "joe").append("age", 33.7).obj(); /* convert from bson to json */ string json = x.toString(); cout << "json for x:" << json << endl; /* access some fields of bson object x */ cout << "Some x things: " << x["name"] << ' ' << x["age"].Number() << ' ' << x.isEmpty() << endl; /* make a bit more complex object with some nesting { x : 'asdf', y : true, subobj : { z : 3, q : 4 } } */ bo y = BSON( "x" << "asdf" << "y" << true << "subobj" << BSON( "z" << 3 << "q" << 4 ) ); /* print it */ cout << "y: " << y << endl; /* reach in and get subobj.z */ cout << "subobj.z: " << y.getFieldDotted("subobj.z").Number() << endl; /* alternate syntax: */ cout << "subobj.z: " << y["subobj"]["z"].Number() << endl; /* fetch all *top level* elements from object y into a vector */ vector<be> v; y.elems(v); cout << v[0] << endl; /* into an array */ list<be> L; y.elems(L); // --------------- MYTEST mytest -------------------- { bob b; b.append("name", "joe"); b.append("age", 33); // bo c = b.obj(); // cout << "c.isOwned: " << c.isOwned() << endl; // cout << "c.isEmpty: " << c.isEmpty() << endl; // cout << "c.isValid: " << c.isValid() << endl; // cout << "c: " << c << endl; char binbuf[128]; unsigned int* plen = (unsigned int* )binbuf; unsigned char* ptype = (unsigned char*)(&binbuf[1]); unsigned int* puint = (unsigned int*)(&ptype[1]); for (int i=0; i<10; i++) { puint[i] = i; } for (int i=0; i<10; i++) { puint[i+10] = i; } *plen = 10*sizeof(unsigned int); *ptype = BinData; bo bbtest(binbuf); printf("---size: %u orig-len: %u valid:%u\n", bbtest.objsize(), 10*sizeof(unsigned int), bbtest.isValid()); const char* pstr = bbtest.objdata(); unsigned int* pplen = (unsigned int* )pstr; unsigned char* pptype = (unsigned char*)(&pplen[1]); unsigned int* ppuint = (unsigned int*)(&pplen[1]); printf("bin-data-len: %u olen: %u type: %u\n", *pplen, *plen, *pptype); // assert(*pptype == BinData); // bo sbb = bob().append("bbtest", bbtest).obj(); // bo sbbb = bob().append("bbbtest", bbtest).obj(); // sbb.getOwned(); // cout << "sbb.isOwned: " << sbb.isOwned() << endl; // cout << "sbb.isEmpty: " << sbb.isEmpty() << endl; // cout << "sbb.isValid: " << sbb.isValid() << endl; // set<string> sss; // sss.insert("bbtest"); // // set<string> ssss; // ssss.insert("bbbtest"); // b.append("bbtest", bbtest); b.appendBinData("bbtest", (int)(20*sizeof(unsigned int)), BinDataGeneral, (char*)puint); bo c = b.obj(); cout << "c.isOwned: " << c.isOwned() << endl; cout << "c.isEmpty: " << c.isEmpty() << endl; cout << "c.isValid: " << c.isValid() << endl; cout << "c[\"age\"]: " << c["age"].Number() << endl; char tmpbuf[1280]; printf("--- c -size: %u valid:%u\n", c.objsize(), c.isValid()); memmove(tmpbuf, c.objdata(), c.objsize()); bo cc(tmpbuf); cout << "bbtest size: " << cc["bbtest"].objsize() << endl; BSONElement be = cc.getField("bbtest"); printf("be.eoo() = [%u]\n", be.eoo()); int len = 0; const int* pdata = (const int*)be.binData(len); printf("len = [%u]\n", len); for(int i=0; i<len/sizeof(int); i++) { printf("[%d] [%d]\n", i, pdata[i]); } } // --------------- MYTEST mytest -------- END ------- bo sub = y["subobj"].Obj(); /* grab all the int's that were in subobj. if it had elements that were not ints, we throw an exception (capital V on Vals() means exception if wrong type found */ vector<int> myints; sub.Vals(myints); cout << "my ints: " << myints[0] << ' ' << myints[1] << endl; /* grab all the string values from x. if the field isn't of string type, just skip it -- lowercase v on vals() indicates skip don't throw. */ vector<string> strs; x.vals(strs); cout << strs.size() << " strings, first one: " << strs[0] << endl; iter(y); return 0; }
// fromBSON to Key format KeyV1Owned::KeyV1Owned(const BSONObj& obj) { BSONObj::iterator i(obj); unsigned char bits = 0; while( 1 ) { BSONElement e = i.next(); if( i.more() ) bits |= cHASMORE; switch( e.type() ) { case MinKey: b.appendUChar(cminkey|bits); break; case jstNULL: b.appendUChar(cnull|bits); break; case MaxKey: b.appendUChar(cmaxkey|bits); break; case Bool: b.appendUChar( (e.boolean()?ctrue:cfalse) | bits ); break; case jstOID: b.appendUChar(coid|bits); b.appendBuf(&e.__oid(), sizeof(OID)); break; case BinData: { int t = e.binDataType(); // 0-7 and 0x80 to 0x87 are supported by Key if( (t & 0x78) == 0 && t != ByteArrayDeprecated ) { int len; const char * d = e.binData(len); if( len <= BinDataLenMax ) { int code = BinDataLengthToCode[len]; if( code >= 0 ) { if( t >= 128 ) t = (t-128) | 0x08; dassert( (code&t) == 0 ); b.appendUChar( cbindata|bits ); b.appendUChar( code | t ); b.appendBuf(d, len); break; } } } traditional(obj); return; } case Date: b.appendUChar(cdate|bits); b.appendStruct(e.date()); break; case String: { b.appendUChar(cstring|bits); // note we do not store the terminating null, to save space. unsigned x = (unsigned) e.valuestrsize() - 1; if( x > 255 ) { traditional(obj); return; } b.appendUChar(x); b.appendBuf(e.valuestr(), x); break; } case NumberInt: b.appendUChar(cint|bits); b.appendNum((double) e._numberInt()); break; case NumberLong: { long long n = e._numberLong(); long long m = 2LL << 52; DEV { long long d = m-1; verify( ((long long) ((double) -d)) == -d ); } if( n >= m || n <= -m ) { // can't represent exactly as a double traditional(obj); return; } b.appendUChar(clong|bits); b.appendNum((double) n); break; } case NumberDouble: { double d = e._numberDouble(); if( isNaN(d) ) { traditional(obj); return; } b.appendUChar(cdouble|bits); b.appendNum(d); break; } default: // if other types involved, store as traditional BSON traditional(obj); return; } if( !i.more() ) break; bits = 0; } _keyData = (const unsigned char *) b.buf(); dassert( b.len() == dataSize() ); // check datasize method is correct dassert( (*_keyData & cNOTUSED) == 0 ); }
Local<v8::Object> mongoToV8( BSONObj & m , bool array ){ Local<v8::Object> o; if ( array ) o = v8::Array::New(); else o = v8::Object::New(); mongo::BSONObj sub; for ( BSONObjIterator i(m); i.more(); ) { BSONElement f = i.next(); if ( f.eoo() ) break; Local<Value> v; switch ( f.type() ){ case mongo::Code: cout << "warning, code saved in database just turned into string right now" << endl; case mongo::String: o->Set( v8::String::New( f.fieldName() ) , v8::String::New( f.valuestr() ) ); break; case mongo::jstOID: { v8::Function * idCons = getObjectIdCons(); v8::Handle<v8::Value> argv[1]; argv[0] = v8::String::New( f.__oid().str().c_str() ); o->Set( v8::String::New( f.fieldName() ) , idCons->NewInstance( 1 , argv ) ); break; } case mongo::NumberDouble: case mongo::NumberInt: o->Set( v8::String::New( f.fieldName() ) , v8::Number::New( f.number() ) ); break; case mongo::Array: case mongo::Object: sub = f.embeddedObject(); o->Set( v8::String::New( f.fieldName() ) , mongoToV8( sub , f.type() == mongo::Array ) ); break; case mongo::Date: o->Set( v8::String::New( f.fieldName() ) , v8::Date::New( f.date() ) ); break; case mongo::Bool: o->Set( v8::String::New( f.fieldName() ) , v8::Boolean::New( f.boolean() ) ); break; case mongo::jstNULL: o->Set( v8::String::New( f.fieldName() ) , v8::Null() ); break; case mongo::RegEx: { v8::Function * regex = getNamedCons( "RegExp" ); v8::Handle<v8::Value> argv[2]; argv[0] = v8::String::New( f.regex() ); argv[1] = v8::String::New( f.regexFlags() ); o->Set( v8::String::New( f.fieldName() ) , regex->NewInstance( 2 , argv ) ); break; } case mongo::BinData: { Local<v8::Object> b = v8::Object::New(); int len; f.binData( len ); b->Set( v8::String::New( "subtype" ) , v8::Number::New( f.binDataType() ) ); b->Set( v8::String::New( "length" ) , v8::Number::New( len ) ); o->Set( v8::String::New( f.fieldName() ) , b ); break; }; case mongo::Timestamp: { Local<v8::Object> sub = v8::Object::New(); sub->Set( v8::String::New( "time" ) , v8::Date::New( f.timestampTime() ) ); sub->Set( v8::String::New( "i" ) , v8::Number::New( f.timestampInc() ) ); o->Set( v8::String::New( f.fieldName() ) , sub ); break; } default: cout << "can't handle type: "; cout << f.type() << " "; cout << f.toString(); cout << endl; break; } } return o; }
static void bson2bamboo(const dclass::DistributedType *type, const BSONElement &element, Datagram &dg) { switch(type->get_type()) { case dclass::Type::T_INT8: { dg.add_int8(element.Int()); } break; case dclass::Type::T_INT16: { dg.add_int16(element.Int()); } break; case dclass::Type::T_INT32: { dg.add_int32(element.Int()); } break; case dclass::Type::T_INT64: { dg.add_int64(element.Int()); } break; case dclass::Type::T_UINT8: { dg.add_uint8(element.Int()); } break; case dclass::Type::T_UINT16: { dg.add_uint16(element.Int()); } break; case dclass::Type::T_UINT32: { dg.add_uint32(element.Int()); } break; case dclass::Type::T_UINT64: { dg.add_uint64(element.Int()); } break; case dclass::Type::T_CHAR: { string str = element.String(); if(str.size() != 1) { throw mongo::DBException("Expected single-length string for char field", 0); } dg.add_uint8(str[0]); } break; case dclass::Type::T_FLOAT32: { dg.add_float32(element.Number()); } break; case dclass::Type::T_FLOAT64: { dg.add_float64(element.Number()); } break; case dclass::Type::T_STRING: { dg.add_data(element.String()); } break; case dclass::Type::T_VARSTRING: { dg.add_string(element.String()); } break; case dclass::Type::T_BLOB: { int len; const uint8_t *rawdata = (const uint8_t *)element.binData(len); dg.add_data(rawdata, len); } break; case dclass::Type::T_VARBLOB: { int len; const uint8_t *rawdata = (const uint8_t *)element.binData(len); dg.add_blob(rawdata, len); } break; case dclass::Type::T_ARRAY: { const dclass::ArrayType *array = type->as_array(); std::vector<BSONElement> data = element.Array(); for(auto it = data.begin(); it != data.end(); ++it) { bson2bamboo(array->get_element_type(), *it, dg); } } break; case dclass::Type::T_VARARRAY: { const dclass::ArrayType *array = type->as_array(); std::vector<BSONElement> data = element.Array(); DatagramPtr newdg = Datagram::create(); for(auto it = data.begin(); it != data.end(); ++it) { bson2bamboo(array->get_element_type(), *it, *newdg); } dg.add_blob(newdg->get_data(), newdg->size()); } break; case dclass::Type::T_STRUCT: { const dclass::Struct *s = type->as_struct(); size_t fields = s->get_num_fields(); for(unsigned int i = 0; i < fields; ++i) { const dclass::Field *field = s->get_field(i); bson2bamboo(field->get_type(), element[field->get_name()], dg); } } break; case dclass::Type::T_METHOD: { const dclass::Method *m = type->as_method(); size_t parameters = m->get_num_parameters(); for(unsigned int i = 0; i < parameters; ++i) { const dclass::Parameter *parameter = m->get_parameter(i); string name = parameter->get_name(); if(name.empty() || element[name].eoo()) { stringstream n; n << "_" << i; name = n.str(); } bson2bamboo(parameter->get_type(), element[name], dg); } } break; case dclass::Type::T_INVALID: default: assert(false); break; } }
Handle<v8::Value> mongoToV8Element( const BSONElement &f ) { assert( !f.eoo() ); switch ( f.type() ){ case mongo::Code: cout << "warning, code saved in database just turned into string right now" << endl; case mongo::String: return v8::String::New( f.valuestr() ); case mongo::jstOID: { v8::Function * idCons = getObjectIdCons(); v8::Handle<v8::Value> argv[1]; argv[0] = v8::String::New( f.__oid().str().c_str() ); return idCons->NewInstance( 1 , argv ); } case mongo::NumberDouble: case mongo::NumberInt: return v8::Number::New( f.number() ); case mongo::Array: case mongo::Object: return mongoToV8( f.embeddedObject() , f.type() == mongo::Array ); case mongo::Date: return v8::Date::New( f.date() ); case mongo::Bool: return v8::Boolean::New( f.boolean() ); case mongo::jstNULL: return v8::Null(); case mongo::RegEx: { v8::Function * regex = getNamedCons( "RegExp" ); v8::Handle<v8::Value> argv[2]; argv[0] = v8::String::New( f.regex() ); argv[1] = v8::String::New( f.regexFlags() ); return regex->NewInstance( 2 , argv ); break; } case mongo::BinData: { Local<v8::Object> b = v8::Object::New(); int len; f.binData( len ); b->Set( v8::String::New( "subtype" ) , v8::Number::New( f.binDataType() ) ); b->Set( v8::String::New( "length" ) , v8::Number::New( len ) ); return b; }; case mongo::Timestamp: { Local<v8::Object> sub = v8::Object::New(); sub->Set( v8::String::New( "time" ) , v8::Date::New( f.timestampTime() ) ); sub->Set( v8::String::New( "i" ) , v8::Number::New( f.timestampInc() ) ); return sub; } case mongo::MinKey: // TODO: make a special type return v8::String::New( "MinKey" ); case mongo::MaxKey: // TODO: make a special type return v8::String::New( "MaxKey" ); case mongo::Undefined: return v8::Undefined(); default: cout << "can't handle type: "; cout << f.type() << " "; cout << f.toString(); cout << endl; break; } return v8::Undefined(); }
void lua_push_value(lua_State *L, const BSONElement &elem) { lua_checkstack(L, 2); int type = elem.type(); switch(type) { case mongo::Undefined: lua_pushnil(L); break; case mongo::NumberInt: lua_pushinteger(L, elem.numberInt()); break; case mongo::NumberLong: case mongo::NumberDouble: lua_pushnumber(L, elem.number()); break; case mongo::Bool: lua_pushboolean(L, elem.boolean()); break; case mongo::String: lua_pushstring(L, elem.valuestr()); break; case mongo::Array: bson_to_array(L, elem.embeddedObject()); break; case mongo::Object: bson_to_table(L, elem.embeddedObject()); break; case mongo::Date: push_bsontype_table(L, mongo::Date); lua_pushnumber(L, elem.date()); lua_rawseti(L, -2, 1); break; case mongo::Timestamp: push_bsontype_table(L, mongo::Date); lua_pushnumber(L, elem.timestampTime()); lua_rawseti(L, -2, 1); break; case mongo::Symbol: push_bsontype_table(L, mongo::Symbol); lua_pushstring(L, elem.valuestr()); lua_rawseti(L, -2, 1); break; case mongo::BinData: { push_bsontype_table(L, mongo::BinData); int l; const char* c = elem.binData(l); lua_pushlstring(L, c, l); lua_rawseti(L, -2, 1); break; } case mongo::RegEx: push_bsontype_table(L, mongo::RegEx); lua_pushstring(L, elem.regex()); lua_rawseti(L, -2, 1); lua_pushstring(L, elem.regexFlags()); lua_rawseti(L, -2, 2); break; case mongo::jstOID: push_bsontype_table(L, mongo::jstOID); lua_pushstring(L, elem.__oid().str().c_str()); lua_rawseti(L, -2, 1); break; case mongo::jstNULL: push_bsontype_table(L, mongo::jstNULL); break; case mongo::EOO: break; /*default: luaL_error(L, LUAMONGO_UNSUPPORTED_BSON_TYPE, bson_name(type));*/ } }
Handle<v8::Value> mongoToV8Element( const BSONElement &f ) { Local< v8::ObjectTemplate > internalFieldObjects = v8::ObjectTemplate::New(); internalFieldObjects->SetInternalFieldCount( 1 ); switch ( f.type() ){ case mongo::Code: return newFunction( f.valuestr() ); case CodeWScope: if ( f.codeWScopeObject().isEmpty() ) log() << "warning: CodeWScope doesn't transfer to db.eval" << endl; return newFunction( f.codeWScopeCode() ); case mongo::String: return v8::String::New( f.valuestr() ); case mongo::jstOID: return newId( f.__oid() ); case mongo::NumberDouble: case mongo::NumberInt: return v8::Number::New( f.number() ); case mongo::Array: case mongo::Object: return mongoToV8( f.embeddedObject() , f.type() == mongo::Array ); case mongo::Date: return v8::Date::New( f.date() ); case mongo::Bool: return v8::Boolean::New( f.boolean() ); case mongo::EOO: case mongo::jstNULL: case mongo::Undefined: // duplicate sm behavior return v8::Null(); case mongo::RegEx: { v8::Function * regex = getNamedCons( "RegExp" ); v8::Handle<v8::Value> argv[2]; argv[0] = v8::String::New( f.regex() ); argv[1] = v8::String::New( f.regexFlags() ); return regex->NewInstance( 2 , argv ); break; } case mongo::BinData: { int len; const char *data = f.binData( len ); v8::Function* binData = getNamedCons( "BinData" ); v8::Handle<v8::Value> argv[3]; argv[0] = v8::Number::New( len ); argv[1] = v8::Number::New( f.binDataType() ); argv[2] = v8::String::New( data, len ); return binData->NewInstance( 3, argv ); }; case mongo::Timestamp: { Local<v8::Object> sub = internalFieldObjects->NewInstance(); sub->Set( v8::String::New( "time" ) , v8::Date::New( f.timestampTime() ) ); sub->Set( v8::String::New( "i" ) , v8::Number::New( f.timestampInc() ) ); sub->SetInternalField( 0, v8::Uint32::New( f.type() ) ); return sub; } case mongo::NumberLong: { Local<v8::Object> sub = internalFieldObjects->NewInstance(); unsigned long long val = f.numberLong(); v8::Function* numberLong = getNamedCons( "NumberLong" ); v8::Handle<v8::Value> argv[2]; argv[0] = v8::Integer::New( val >> 32 ); argv[1] = v8::Integer::New( (unsigned long)(val & 0x00000000ffffffff) ); return numberLong->NewInstance( 2, argv ); } case mongo::MinKey: { Local<v8::Object> sub = internalFieldObjects->NewInstance(); sub->Set( v8::String::New( "$MinKey" ), v8::Boolean::New( true ) ); sub->SetInternalField( 0, v8::Uint32::New( f.type() ) ); return sub; } case mongo::MaxKey: { Local<v8::Object> sub = internalFieldObjects->NewInstance(); sub->Set( v8::String::New( "$MaxKey" ), v8::Boolean::New( true ) ); sub->SetInternalField( 0, v8::Uint32::New( f.type() ) ); return sub; } case mongo::DBRef: { v8::Function* dbPointer = getNamedCons( "DBPointer" ); v8::Handle<v8::Value> argv[2]; argv[0] = v8::String::New( f.dbrefNS() ); argv[1] = newId( f.dbrefOID() ); return dbPointer->NewInstance(2, argv); } default: cout << "can't handle type: "; cout << f.type() << " "; cout << f.toString(); cout << endl; break; } return v8::Undefined(); }
// fromBSON to Key format KeyV1Owned::KeyV1Owned(const BSONObj& obj) { BSONObj::iterator i(obj); assert( i.more() ); unsigned char bits = 0; while( 1 ) { BSONElement e = i.next(); if( i.more() ) bits |= cHASMORE; switch( e.type() ) { case MinKey: b.appendUChar(cminkey|bits); break; case jstNULL: b.appendUChar(cnull|bits); break; case MaxKey: b.appendUChar(cmaxkey|bits); break; case Bool: b.appendUChar( (e.boolean()?ctrue:cfalse) | bits ); break; case jstOID: b.appendUChar(coid|bits); b.appendBuf(&e.__oid(), sizeof(OID)); break; case BinData: { int t = e.binDataType(); // 0-7 and 0x80 to 0x87 are supported by Key if( (t & 0x78) == 0 && t != ByteArrayDeprecated ) { int len; const char * d = e.binData(len); int code = BinDataLengthToCode[len]; if( code >= 0 ) { if( t >= 128 ) t = (t-128) | 0x08; dassert( (code&t) == 0 ); b.appendUChar( cbindata|bits ); b.appendUChar( code | t ); b.appendBuf(d, len); break; } } traditional(obj); return; } case Date: b.appendUChar(cdate|bits); b.appendStruct(e.date()); break; case String: { b.appendUChar(cstring|bits); // note we do not store the terminating null, to save space. unsigned x = (unsigned) e.valuestrsize() - 1; if( x > 255 ) { traditional(obj); return; } b.appendUChar(x); b.appendBuf(e.valuestr(), x); break; } case NumberInt: b.appendUChar(cint|bits); b.appendNum((double) e._numberInt()); break; case NumberLong: { long long n = e._numberLong(); double d = (double) n; if( d != n ) { traditional(obj); return; } b.appendUChar(clong|bits); b.appendNum(d); break; } case NumberDouble: { double d = e._numberDouble(); bool nan = !( d <= numeric_limits< double >::max() && d >= -numeric_limits< double >::max() ); if( !nan ) { b.appendUChar(cdouble|bits); b.appendNum(d); break; } // else fall through and return a traditional BSON obj so our compressed keys need not check for nan } default: // if other types involved, store as traditional BSON traditional(obj); return; } if( !i.more() ) break; bits = 0; } _keyData = (const unsigned char *) b.buf(); dassert( b.len() == dataSize() ); // check datasize method is correct dassert( (*_keyData & cNOTUSED) == 0 ); }
jsval toval( const BSONElement& e ) { switch( e.type() ) { case EOO: case jstNULL: case Undefined: return JSVAL_NULL; case NumberDouble: case NumberInt: return toval( e.number() ); case Symbol: // TODO: should we make a special class for this case String: return toval( e.valuestr() ); case Bool: return e.boolean() ? JSVAL_TRUE : JSVAL_FALSE; case Object: { BSONObj embed = e.embeddedObject().getOwned(); return toval( &embed ); } case Array: { BSONObj embed = e.embeddedObject().getOwned(); if ( embed.isEmpty() ) { return OBJECT_TO_JSVAL( JS_NewArrayObject( _context , 0 , 0 ) ); } int n = embed.nFields(); JSObject * array = JS_NewArrayObject( _context , n , 0 ); assert( array ); jsval myarray = OBJECT_TO_JSVAL( array ); for ( int i=0; i<n; i++ ) { jsval v = toval( embed[i] ); assert( JS_SetElement( _context , array , i , &v ) ); } return myarray; } case jstOID: { OID oid = e.__oid(); JSObject * o = JS_NewObject( _context , &object_id_class , 0 , 0 ); setProperty( o , "str" , toval( oid.str().c_str() ) ); return OBJECT_TO_JSVAL( o ); } case RegEx: { const char * flags = e.regexFlags(); uintN flagNumber = 0; while ( *flags ) { switch ( *flags ) { case 'g': flagNumber |= JSREG_GLOB; break; case 'i': flagNumber |= JSREG_FOLD; break; case 'm': flagNumber |= JSREG_MULTILINE; break; //case 'y': flagNumber |= JSREG_STICKY; break; default: log() << "warning: unknown regex flag:" << *flags << endl; } flags++; } JSObject * r = JS_NewRegExpObject( _context , (char*)e.regex() , strlen( e.regex() ) , flagNumber ); assert( r ); return OBJECT_TO_JSVAL( r ); } case Code: { JSFunction * func = compileFunction( e.valuestr() ); return OBJECT_TO_JSVAL( JS_GetFunctionObject( func ) ); } case CodeWScope: { JSFunction * func = compileFunction( e.codeWScopeCode() ); BSONObj extraScope = e.codeWScopeObject(); if ( ! extraScope.isEmpty() ) { log() << "warning: CodeWScope doesn't transfer to db.eval" << endl; } return OBJECT_TO_JSVAL( JS_GetFunctionObject( func ) ); } case Date: return OBJECT_TO_JSVAL( js_NewDateObjectMsec( _context , (jsdouble) e.date().millis ) ); case MinKey: return OBJECT_TO_JSVAL( JS_NewObject( _context , &minkey_class , 0 , 0 ) ); case MaxKey: return OBJECT_TO_JSVAL( JS_NewObject( _context , &maxkey_class , 0 , 0 ) ); case Timestamp: { JSObject * o = JS_NewObject( _context , ×tamp_class , 0 , 0 ); setProperty( o , "t" , toval( (double)(e.timestampTime()) ) ); setProperty( o , "i" , toval( (double)(e.timestampInc()) ) ); return OBJECT_TO_JSVAL( o ); } case NumberLong: { boost::uint64_t val = (boost::uint64_t)e.numberLong(); JSObject * o = JS_NewObject( _context , &numberlong_class , 0 , 0 ); setProperty( o , "floatApprox" , toval( (double)(boost::int64_t)( val ) ) ); if ( (boost::int64_t)val != (boost::int64_t)(double)(boost::int64_t)( val ) ) { // using 2 doubles here instead of a single double because certain double // bit patterns represent undefined values and sm might trash them setProperty( o , "top" , toval( (double)(boost::uint32_t)( val >> 32 ) ) ); setProperty( o , "bottom" , toval( (double)(boost::uint32_t)( val & 0x00000000ffffffff ) ) ); } return OBJECT_TO_JSVAL( o ); } case DBRef: { JSObject * o = JS_NewObject( _context , &dbpointer_class , 0 , 0 ); setProperty( o , "ns" , toval( e.dbrefNS() ) ); JSObject * oid = JS_NewObject( _context , &object_id_class , 0 , 0 ); setProperty( oid , "str" , toval( e.dbrefOID().str().c_str() ) ); setProperty( o , "id" , OBJECT_TO_JSVAL( oid ) ); return OBJECT_TO_JSVAL( o ); } case BinData: { JSObject * o = JS_NewObject( _context , &bindata_class , 0 , 0 ); int len; const char * data = e.binData( len ); assert( JS_SetPrivate( _context , o , new BinDataHolder( data ) ) ); setProperty( o , "len" , toval( len ) ); setProperty( o , "type" , toval( (int)e.binDataType() ) ); return OBJECT_TO_JSVAL( o ); } }