0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

SERVER-776 NumberLong in sm

This commit is contained in:
Aaron 2010-06-22 17:53:11 -07:00
parent 155e38b679
commit bf36eebd4f
6 changed files with 121 additions and 31 deletions

View File

@ -541,7 +541,7 @@ namespace JSTests {
ASSERT( s->exec( "c = {c:a.a.toString()}", "foo", false, true, false ) );
out = s->getObject( "c" );
stringstream ss;
ss << val;
ss << "NumberLong( \"" << val << "\" )";
ASSERT_EQUALS( ss.str(), out.firstElement().valuestr() );
ASSERT( s->exec( "d = {d:a.a.toNumber()}", "foo", false, true, false ) );

46
jstests/numberlong.js Normal file
View File

@ -0,0 +1,46 @@
n = new NumberLong( 4 );
assert.eq.automsg( "4", "n" );
assert.eq.automsg( "4", "n.toNumber()" );
assert.eq.automsg( "8", "n + 4" );
assert.eq.automsg( "'NumberLong( 4 )'", "n.toString()" );
assert.eq.automsg( "'NumberLong( 4 )'", "tojson( n )" );
a = {}
a.a = n;
p = tojson( a );
assert.eq.automsg( "'{ \"a\" : NumberLong( 4 ) }'", "p" );
n = new NumberLong( -4 );
assert.eq.automsg( "-4", "n" );
assert.eq.automsg( "-4", "n.toNumber()" );
assert.eq.automsg( "0", "n + 4" );
assert.eq.automsg( "'NumberLong( -4 )'", "n.toString()" );
assert.eq.automsg( "'NumberLong( -4 )'", "tojson( n )" );
a = {}
a.a = n;
p = tojson( a );
assert.eq.automsg( "'{ \"a\" : NumberLong( -4 ) }'", "p" );
// too big to fit in double
n = new NumberLong( "11111111111111111" );
assert.eq.automsg( "11111111111111112", "n.toNumber()" );
assert.eq.automsg( "11111111111111116", "n + 4" );
assert.eq.automsg( "'NumberLong( \"11111111111111111\" )'", "n.toString()" );
assert.eq.automsg( "'NumberLong( \"11111111111111111\" )'", "tojson( n )" );
a = {}
a.a = n;
p = tojson( a );
assert.eq.automsg( "'{ \"a\" : NumberLong( \"11111111111111111\" ) }'", "p" );
n = new NumberLong( "-11111111111111111" );
assert.eq.automsg( "-11111111111111112", "n.toNumber()" );
assert.eq.automsg( "-11111111111111108", "n + 4" );
assert.eq.automsg( "'NumberLong( \"-11111111111111111\" )'", "n.toString()" );
assert.eq.automsg( "'NumberLong( \"-11111111111111111\" )'", "tojson( n )" );
a = {}
a.a = n;
p = tojson( a );
assert.eq.automsg( "'{ \"a\" : NumberLong( \"-11111111111111111\" ) }'", "p" );
// parsing
assert.throws.automsg( function() { new NumberLong( "y" ); } );
assert.throws.automsg( function() { new NumberLong( "11111111111111111111" ); } );

View File

@ -452,6 +452,7 @@
937D14AB0F2A225F0071FFA9 /* nonce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nonce.h; sourceTree = "<group>"; };
937D14AC0F2A226E0071FFA9 /* nonce.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nonce.cpp; sourceTree = "<group>"; };
938A748A11D140EC005265E1 /* in4.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = in4.js; sourceTree = "<group>"; };
938A74BF11D17ECE005265E1 /* numberlong.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = numberlong.js; sourceTree = "<group>"; };
938A7A420F54871000FB7A07 /* storage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = storage.cpp; sourceTree = "<group>"; };
938A7A430F54873600FB7A07 /* concurrency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = concurrency.h; sourceTree = "<group>"; };
938A7A440F54873600FB7A07 /* queryutil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = queryutil.cpp; sourceTree = "<group>"; };
@ -822,6 +823,7 @@
934BEB9A10DFFA9600178102 /* jstests */ = {
isa = PBXGroup;
children = (
938A74BF11D17ECE005265E1 /* numberlong.js */,
938A748A11D140EC005265E1 /* in4.js */,
93C529C511D047CF00CF42F7 /* repair2.js */,
937884E811C80B22007E85F5 /* or8.js */,

View File

@ -532,6 +532,24 @@ namespace mongo {
return OBJECT_TO_JSVAL( o );
}
void makeLongObj( long long n, JSObject * o ) {
boost::uint64_t val = (boost::uint64_t)n;
CHECKNEWOBJECT(o,_context,"NumberLong1");
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 ) ) );
}
}
jsval toval( long long n ) {
JSObject * o = JS_NewObject( _context , &numberlong_class , 0 , 0 );
makeLongObj( n, o );
return OBJECT_TO_JSVAL( o );
}
jsval toval( const BSONElement& e ){
switch( e.type() ){
@ -633,17 +651,7 @@ namespace mongo {
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 );
CHECKNEWOBJECT(o,_context,"NumberLong1");
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 );
return toval( e.numberLong() );
}
case DBRef: {
JSObject * o = JS_NewObject( _context , &dbpointer_class , 0 , 0 );
@ -664,8 +672,8 @@ namespace mongo {
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() ) );
setProperty( o , "len" , toval( (double)len ) );
setProperty( o , "type" , toval( (double)e.binDataType() ) );
return OBJECT_TO_JSVAL( o );
}
}

View File

@ -593,8 +593,8 @@ namespace mongo {
string decoded = base64::decode( encoded );
assert( JS_SetPrivate( cx, obj, new BinDataHolder( decoded.data(), decoded.length() ) ) );
c.setProperty( obj, "len", c.toval( decoded.length() ) );
c.setProperty( obj, "type", c.toval( type ) );
c.setProperty( obj, "len", c.toval( (double)decoded.length() ) );
c.setProperty( obj, "type", c.toval( (double)type ) );
return JS_TRUE;
}
@ -699,6 +699,27 @@ namespace mongo {
JSCLASS_NO_OPTIONAL_MEMBERS
};
JSBool numberlong_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
smuassert( cx , "NumberLong needs 0 or 1 args" , argc == 0 || argc == 1 );
Convertor c( cx );
if ( argc == 0 ) {
c.setProperty( obj, "floatApprox", c.toval( 0.0 ) );
} else if ( JSVAL_IS_NUMBER( argv[ 0 ] ) ) {
c.setProperty( obj, "floatApprox", argv[ 0 ] );
} else {
string num = c.toString( argv[ 0 ] );
const char *numStr = num.c_str();
char *endPtr = 0;
errno = 0;
long long n = strtoll( numStr, &endPtr, 10 );
smuassert( cx , "could not convert numeric representation of string to long" , *endPtr == 0 && errno != ERANGE );
c.makeLongObj( n, obj );
}
return JS_TRUE;
}
JSBool numberlong_valueof(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
Convertor c(cx);
return *rval = c.toval( double( c.toNumberLongUnsafe( obj ) ) );
@ -711,7 +732,12 @@ namespace mongo {
JSBool numberlong_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
Convertor c(cx);
stringstream ss;
ss << c.toNumberLongUnsafe( obj );
long long val = c.toNumberLongUnsafe( obj );
if ( val == (long long)(double)( val ) ) {
ss << "NumberLong( " << double( val ) << " )";
} else {
ss << "NumberLong( \"" << val << "\" )";
}
string ret = ss.str();
return *rval = c.toval( ret.c_str() );
}
@ -821,7 +847,7 @@ namespace mongo {
assert( JS_InitClass( cx , global , 0 , &bindata_class , bindata_constructor , 0 , 0 , bindata_functions , 0 , 0 ) );
assert( JS_InitClass( cx , global , 0 , &timestamp_class , 0 , 0 , 0 , 0 , 0 , 0 ) );
assert( JS_InitClass( cx , global , 0 , &numberlong_class , 0 , 0 , 0 , numberlong_functions , 0 , 0 ) );
assert( JS_InitClass( cx , global , 0 , &numberlong_class , numberlong_constructor , 0 , 0 , numberlong_functions , 0 , 0 ) );
assert( JS_InitClass( cx , global , 0 , &minkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) );
assert( JS_InitClass( cx , global , 0 , &maxkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) );

View File

@ -15,15 +15,15 @@ friendlyEqual = function( a , b ){
return true;
return false;
}
doassert = function (msg) {
if (msg.indexOf("assert") == 0)
print(msg);
else
print("assert: " + msg);
throw msg;
}
doassert = function (msg) {
if (msg.indexOf("assert") == 0)
print(msg);
else
print("assert: " + msg);
throw msg;
}
assert = function( b , msg ){
@ -344,6 +344,14 @@ Object.keySet = function( o ) {
return ret;
}
if ( ! NumberLong.prototype ) {
NumberLong.prototype = {}
}
NumberLong.prototype.tojson = function() {
return this.toString();
}
if ( ! ObjectId.prototype )
ObjectId.prototype = {}
@ -816,10 +824,10 @@ shellHelper = function( command , rest , shouldPrint ){
help = shellHelper.help = function (x) {
if (x == "admin") {
print("\tls([path]) list files");
print("\tpwd() returns current directory");
print("\tlistFiles([path]) returns file list");
print("\thostname() returns name of this host");
print("\tcat(fname) returns contents of text file as a string");
print("\tpwd() returns current directory");
print("\tlistFiles([path]) returns file list");
print("\thostname() returns name of this host");
print("\tcat(fname) returns contents of text file as a string");
print("\tremoveFile(f) delete a file");
print("\tload(jsfilename) load and execute a .js file");
print("\trun(program[, args...]) spawn a program and wait for its completion");