/* Copyright (C) 2009 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 0 A.D. is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 0 A.D. If not, see . */ #include "precompiled.h" #include "JSConversions.h" #include "simulation/Entity.h" #include "graphics/ObjectManager.h" #include "maths/scripting/JSInterface_Vector3D.h" #include "ps/Parser.h" #include "ps/Player.h" #include "simulation/EntityTemplate.h" #include "lib/sysdep/sysdep.h" // isfinite #include #include #include "scripting/ScriptableComplex.inl" // HEntity template<> HEntity* ToNative( JSContext* cx, JSObject* obj ) { CEntity* e = ToNative( cx, obj ); return( e ? &( e->me ) : NULL ); } template<> JSObject* ToScript( HEntity* Native ) { return( ToScript( &( **Native ) ) ); } // CPlayer* template<> bool ToPrimitive( JSContext* cx, jsval v, CPlayer*& Storage ) { if( !JSVAL_IS_OBJECT( v ) || ( v == JSVAL_NULL ) ) return( false ); CPlayer* Data = (CPlayer*)JS_GetInstancePrivate( cx, JSVAL_TO_OBJECT( v ), &CPlayer::JSI_class, NULL ); if( !Data ) return( false ); Storage = Data; return( true ); } template<> JSObject* ToScript( CPlayer** Native ) { return( ToScript( *Native ) ); } // CEntityTemplate* template<> bool ToPrimitive( JSContext* cx, jsval v, CEntityTemplate*& Storage ) { if( !JSVAL_IS_OBJECT( v ) || ( v == JSVAL_NULL ) ) return( false ); CEntityTemplate* Data = (CEntityTemplate*)JS_GetInstancePrivate( cx, JSVAL_TO_OBJECT( v ), &CEntityTemplate::JSI_class, NULL ); if( !Data ) return( false ); Storage = Data; return( true ); } template<> JSObject* ToScript( CEntityTemplate** Native ) { return( ToScript( *Native ) ); } // CVector3D template<> CVector3D* ToNative( JSContext* cx, JSObject* obj ) { JSI_Vector3D::Vector3D_Info* v = (JSI_Vector3D::Vector3D_Info*)JS_GetInstancePrivate( cx, obj, &JSI_Vector3D::JSI_class, NULL ); return( v ? v->vector : NULL ); } template<> JSObject* ToScript( CVector3D* Native ) { JSObject* Script = JS_NewObject( g_ScriptingHost.GetContext(), &JSI_Vector3D::JSI_class, NULL, NULL ); JS_SetPrivate( g_ScriptingHost.GetContext(), Script, new JSI_Vector3D::Vector3D_Info( *Native ) ); return( Script ); } template<> jsval ToJSVal( const CVector3D& Native ) { JSObject* Script = JS_NewObject( g_ScriptingHost.GetContext(), &JSI_Vector3D::JSI_class, NULL, NULL ); JS_SetPrivate( g_ScriptingHost.GetContext(), Script, new JSI_Vector3D::Vector3D_Info( Native ) ); return( OBJECT_TO_JSVAL( Script ) ); } // CScriptObject template<> jsval ToJSVal( CScriptObject& Native ) { return( OBJECT_TO_JSVAL( Native.GetFunctionObject() ) ); } template<> bool ToPrimitive( JSContext* UNUSED(cx), jsval v, CScriptObject& Storage ) { Storage.SetJSVal( v ); return( true ); } // int template<> jsval ToJSVal( const int& Native ) { return( INT_TO_JSVAL( Native ) ); } template<> jsval ToJSVal( int& Native ) { return( INT_TO_JSVAL( Native ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, int& Storage ) { JSBool ok = JS_ValueToInt32(cx, v, (int32*)&Storage); return ok == JS_TRUE; } // unsigned template<> jsval ToJSVal( const unsigned& Native ) { return( INT_TO_JSVAL( Native ) ); } template<> jsval ToJSVal( unsigned& Native ) { return( INT_TO_JSVAL( Native ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, unsigned& Storage ) { int temp; if(!ToPrimitive(cx, v, temp)) return false; if(temp < 0) return false; Storage = (unsigned)temp; return true; } // long template<> jsval ToJSVal( const long& Native ) { return( INT_TO_JSVAL( (int)Native ) ); } template<> jsval ToJSVal( long& Native ) { return( INT_TO_JSVAL( (int)Native ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, long& Storage ) { int32 tmp; JSBool ok = JS_ValueToInt32(cx, v, &tmp); Storage = (long)tmp; return ok == JS_TRUE; } // unsigned long template<> jsval ToJSVal( const unsigned long& Native ) { return( INT_TO_JSVAL( (int)Native ) ); } template<> jsval ToJSVal( unsigned long& Native ) { return( INT_TO_JSVAL( (int)Native ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, unsigned long& Storage ) { int32 tmp; JSBool ok = JS_ValueToInt32(cx, v, &tmp); Storage = (unsigned long)tmp; return ok == JS_TRUE; } // see comment at declaration of specialization #if !GCC_VERSION #if ARCH_AMD64 template<> jsval ToJSVal( const size_t& Native ) { return( INT_TO_JSVAL( (int)Native ) ); } template<> jsval ToJSVal( size_t& Native ) { return( INT_TO_JSVAL( (int)Native ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, size_t& Storage ) { int temp; if(!ToPrimitive(cx, v, temp)) return false; if(temp < 0) return false; Storage = (size_t)temp; return true; } template<> jsval ToJSVal( const ssize_t& Native ) { return( INT_TO_JSVAL( (int)Native ) ); } template<> jsval ToJSVal( ssize_t& Native ) { return( INT_TO_JSVAL( (int)Native ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, ssize_t& Storage ) { int temp; if(!ToPrimitive(cx, v, temp)) return false; if(temp < 0) return false; Storage = (ssize_t)temp; return true; } #endif // #if ARCH_AMD64 #endif // #if !GCC_VERSION // double template<> jsval ToJSVal( const double& Native ) { return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), Native ) ) ); } template<> jsval ToJSVal( double& Native ) { return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), Native ) ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, double& Storage ) { JSBool ok = JS_ValueToNumber(cx, v, &Storage); if (ok == JS_FALSE || !isfinite( Storage ) ) return false; return true; } // float template<> jsval ToJSVal( const float& Native ) { return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), Native ) ) ); } template<> jsval ToJSVal( float& Native ) { return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), Native ) ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, float& Storage ) { double temp; if(!ToPrimitive(cx, v, temp)) return false; Storage = (float)temp; return true; } // bool template<> jsval ToJSVal( const bool& Native ) { return( BOOLEAN_TO_JSVAL( Native ) ); } template<> jsval ToJSVal( bool& Native ) { return( BOOLEAN_TO_JSVAL( Native ) ); } template<> bool ToPrimitive( JSContext* cx, jsval v, bool& Storage ) { JSBool temp; JSBool ok = JS_ValueToBoolean(cx, v, &temp); if(ok == JS_FALSE) return false; Storage = (temp == JS_TRUE); return true; } // CStrW template<> bool ToPrimitive( JSContext* UNUSED(cx), jsval v, CStrW& Storage ) { try { Storage = g_ScriptingHost.ValueToUCString( v ); } catch( PSERROR_Scripting_ConversionFailed ) { return( false ); } return( true ); } template<> jsval ToJSVal( const CStrW& Native ) { return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( g_ScriptingHost.GetContext(), Native.utf16().c_str() ) ) ); } template<> jsval ToJSVal( CStrW& Native ) { return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( g_ScriptingHost.GetContext(), Native.utf16().c_str() ) ) ); } // CStr/CStr8 template<> bool ToPrimitive( JSContext* UNUSED(cx), jsval v, CStr8& Storage ) { try { Storage = g_ScriptingHost.ValueToString( v ); } catch( PSERROR_Scripting_ConversionFailed ) { return( false ); } return( true ); } template<> jsval ToJSVal( const CStr8& Native ) { return( STRING_TO_JSVAL( JS_NewStringCopyZ( g_ScriptingHost.GetContext(), Native.c_str() ) ) ); } template<> jsval ToJSVal( CStr8& Native ) { return( STRING_TO_JSVAL( JS_NewStringCopyZ( g_ScriptingHost.GetContext(), Native.c_str() ) ) ); } // jsval template<> jsval ToJSVal( const jsval_t& Native ) { return( Native.v ); } // String->JSVal jsval JSParseString( const CStrW& Native ) { CParser stringParser; stringParser.InputTaskType( "string", "_$value_" ); CParserLine result; result.ParseString( stringParser, CStr(Native) ); bool boolResult; int intResult; float floatResult; if( result.GetArgFloat( 0, floatResult ) ) { if( floatResult == floor( floatResult ) ) { intResult = (int)floatResult; if( INT_FITS_IN_JSVAL( intResult ) ) return( ToJSVal( intResult ) ); } return( ToJSVal( floatResult ) ); } if( result.GetArgBool( 0, boolResult ) ) return( BOOLEAN_TO_JSVAL( boolResult ) ); return( ToJSVal( Native ) ); }