diff options
author | agirbal <antoine@10gen.com> | 2011-07-03 18:47:14 -0700 |
---|---|---|
committer | agirbal <antoine@10gen.com> | 2011-07-03 18:47:14 -0700 |
commit | 5dcc4f9d49173b5e67909714f3bf39f918d2398a (patch) | |
tree | 7a412611a9b4d00cea2791aec7ec3dc6b646b35e /scripting | |
parent | 758a9c734164ecda21cdc5f96436fed88bdfd24f (diff) | |
download | mongo-5dcc4f9d49173b5e67909714f3bf39f918d2398a.tar.gz |
SERVER-854: NumberInt implemented in SM
Diffstat (limited to 'scripting')
-rw-r--r-- | scripting/engine_spidermonkey.cpp | 20 | ||||
-rw-r--r-- | scripting/engine_spidermonkey.h | 1 | ||||
-rw-r--r-- | scripting/sm_db.cpp | 73 |
3 files changed, 93 insertions, 1 deletions
diff --git a/scripting/engine_spidermonkey.cpp b/scripting/engine_spidermonkey.cpp index 9189153d12a..01aacbe49ca 100644 --- a/scripting/engine_spidermonkey.cpp +++ b/scripting/engine_spidermonkey.cpp @@ -242,6 +242,10 @@ namespace mongo { return val; } + int toNumberInt( JSObject *o ) { + return (boost::uint32_t)(boost::int32_t) getNumber( o, "floatApprox" ); + } + double toNumber( jsval v ) { double d; uassert( 10214 , "not a number" , JS_ValueToNumber( _context , v , &d ) ); @@ -566,6 +570,19 @@ namespace mongo { return OBJECT_TO_JSVAL( o ); } + void makeIntObj( int n, JSObject * o ) { + boost::uint32_t val = (boost::uint32_t)n; + CHECKNEWOBJECT(o,_context,"NumberInt1"); + double floatApprox = (double)(boost::int32_t)val; + setProperty( o , "floatApprox" , toval( floatApprox ) ); + } + + jsval toval( int n ) { + JSObject * o = JS_NewObject( _context , &numberint_class , 0 , 0 ); + makeIntObj( n, o ); + return OBJECT_TO_JSVAL( o ); + } + jsval toval( const BSONElement& e ) { switch( e.type() ) { @@ -574,8 +591,9 @@ namespace mongo { case Undefined: return JSVAL_NULL; case NumberDouble: - case NumberInt: return toval( e.number() ); + case NumberInt: + return toval( e.numberInt() ); case Symbol: // TODO: should we make a special class for this case String: return toval( e.valuestr() ); diff --git a/scripting/engine_spidermonkey.h b/scripting/engine_spidermonkey.h index 3ee74953444..0554adbf836 100644 --- a/scripting/engine_spidermonkey.h +++ b/scripting/engine_spidermonkey.h @@ -95,6 +95,7 @@ namespace mongo { extern JSClass bindata_class; extern JSClass timestamp_class; extern JSClass numberlong_class; + extern JSClass numberint_class; extern JSClass minkey_class; extern JSClass maxkey_class; diff --git a/scripting/sm_db.cpp b/scripting/sm_db.cpp index 189c81b454f..c2e4bd42984 100644 --- a/scripting/sm_db.cpp +++ b/scripting/sm_db.cpp @@ -938,6 +938,73 @@ zzz { 0 } }; + JSClass numberint_class = { + "NumberInt" , JSCLASS_HAS_PRIVATE , + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub, + JSCLASS_NO_OPTIONAL_MEMBERS + }; + + JSBool numberint_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ) { + smuassert( cx , "NumberInt needs 0 or 1 args" , argc == 0 || argc == 1 ); + + if ( ! JS_InstanceOf( cx , obj , &numberint_class , 0 ) ) { + obj = JS_NewObject( cx , &numberint_class , 0 , 0 ); + CHECKNEWOBJECT( obj, cx, "numberint_constructor" ); + *rval = OBJECT_TO_JSVAL( obj ); + } + + 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 ] ); + //PRINT(num); + const char *numStr = num.c_str(); + int n; + try { + n = (int) parseLL( numStr ); + //PRINT(n); + } + catch ( const AssertionException & ) { + smuassert( cx , "could not convert string to integer" , false ); + } + c.makeIntObj( n, obj ); + } + + return JS_TRUE; + } + + JSBool numberint_valueof(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + Convertor c(cx); + return *rval = c.toval( double( c.toNumberInt( obj ) ) ); + } + + JSBool numberint_tonumber(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + return numberint_valueof( cx, obj, argc, argv, rval ); + } + + JSBool numberint_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + Convertor c(cx); + stringstream ss; + int val = c.toNumberInt( obj ); + ss << "NumberInt(" << val << ")"; + + string ret = ss.str(); + return *rval = c.toval( ret.c_str() ); + } + + JSFunctionSpec numberint_functions[] = { + { "valueOf" , numberint_valueof , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "toNumber" , numberint_tonumber , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "toString" , numberint_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { 0 } + }; + JSClass minkey_class = { "MinKey" , JSCLASS_HAS_PRIVATE , JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, @@ -1044,6 +1111,7 @@ zzz assert( JS_InitClass( cx , global , 0 , ×tamp_class , timestamp_constructor , 0 , 0 , 0 , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , &numberlong_class , numberlong_constructor , 0 , 0 , numberlong_functions , 0 , 0 ) ); + assert( JS_InitClass( cx , global , 0 , &numberint_class , numberint_constructor , 0 , 0 , numberint_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 ) ); @@ -1088,6 +1156,11 @@ zzz return true; } + if ( JS_InstanceOf( c->_context , o , &numberint_class , 0 ) ) { + b.append( name , c->toNumberInt( o ) ); + return true; + } + if ( JS_InstanceOf( c->_context , o , &dbpointer_class , 0 ) ) { b.appendDBRef( name , c->getString( o , "ns" ) , c->toOID( c->getProperty( o , "id" ) ) ); return true; |