/* 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 .
*/
// A general system of converting between native objects and their JavaScript representations
#ifndef INCLUDED_JSCONVERSIONS
#define INCLUDED_JSCONVERSIONS
#include "scripting/ScriptingHost.h"
class CStrW;
class CScriptObject;
class CObjectEntry;
class CVector3D;
// -----
//
// Defaults
//
// -----
template T* ToNative( JSContext* cx, JSObject* obj )
{
return( (T*)JS_GetInstancePrivate( cx, obj, &T::JSI_class, NULL ) );
}
template JSObject* ToScript( T* Native )
{
if( !Native )
return( (JSObject*)NULL );
return( Native->GetScript() );
}
template T* ToNative( jsval v )
{
if( !JSVAL_IS_OBJECT( v ) ) return( NULL );
if( v == JSVAL_NULL ) return( NULL );
return( ToNative( g_ScriptingHost.GetContext(), JSVAL_TO_OBJECT( v ) ) );
}
template bool ToPrimitive( JSContext* UNUSED(cx), jsval v, T& Storage )
{
T* Native = ToNative( v );
if( !Native ) return( false );
Storage = *Native;
return( true );
}
// Handle pointer-to-objects sensibly (by automatically dereferencing them one level)
template bool ToPrimitive( JSContext* UNUSED(cx), jsval v, T*& Storage )
{
T* Native = ToNative( v );
if( !Native ) return( false );
Storage = Native;
return( true );
}
// Throws PSERROR_Scripting_ConversionFailed on failure.
template inline T ToPrimitive( JSContext* cx, jsval v )
{
T Temp;
bool ok = ToPrimitive( cx, v, Temp );
if( !ok ) throw PSERROR_Scripting_ConversionFailed();
return( Temp );
}
// Throws PSERROR_Scripting_ConversionFailed on failure.
template inline T ToPrimitive( jsval v )
{
return( ToPrimitive( g_ScriptingHost.GetContext(), v ) );
}
template jsval ToJSVal( T& Native )
{
return( OBJECT_TO_JSVAL( ToScript( &Native ) ) );
}
template jsval ToJSVal( T*& Native )
{
return( OBJECT_TO_JSVAL( ToScript( Native ) ) );
}
template jsval ToJSVal( const T& Native );
// -----
//
// Overrides
//
// -----
// CVector3D
template<> CVector3D* ToNative( JSContext* cx, JSObject* obj );
template<> JSObject* ToScript( CVector3D* Native );
template<> jsval ToJSVal( const CVector3D& Native );
// CObjectEntry
template<> bool ToPrimitive( JSContext* cx, jsval v, CObjectEntry*& Storage );
template<> jsval ToJSVal( CObjectEntry*& Native );
// CScriptObject
template<> bool ToPrimitive( JSContext* cx, jsval v, CScriptObject& Storage );
template<> jsval ToJSVal( CScriptObject& Native );
// int
template<> bool ToPrimitive( JSContext* cx, jsval v, int& Storage );
template<> jsval ToJSVal( const int& Native );
template<> jsval ToJSVal( int& Native );
// unsigned
template<> bool ToPrimitive( JSContext* cx, jsval v, unsigned& Storage );
template<> jsval ToJSVal( const unsigned& Native );
template<> jsval ToJSVal( unsigned& Native );
// long int
template<> bool ToPrimitive( JSContext* cx, jsval v, long& Storage );
template<> jsval ToJSVal( const long& Native );
template<> jsval ToJSVal( long& Native );
// unsigned long int
template<> bool ToPrimitive( JSContext* cx, jsval v, unsigned long& Storage );
template<> jsval ToJSVal( const unsigned long& Native );
template<> jsval ToJSVal( unsigned long& Native );
// (s)size_t are considered to be identical to (unsigned) int by GCC and
// their specializations would cause conflicts there. On x86_64 GCC, s/size_t
// is equivalent to (unsigned) long, but the same solution applies; use the
// long and unsigned long specializations instead of s/size_t.
#if !GCC_VERSION
// for some reason, x64 MSC treats size_t as distinct from unsigned long:
#if ARCH_AMD64
// size_t
template<> bool ToPrimitive( JSContext* cx, jsval v, size_t& Storage );
template<> jsval ToJSVal( const size_t& Native );
template<> jsval ToJSVal( size_t& Native );
// ssize_t
template<> bool ToPrimitive( JSContext* cx, jsval v, ssize_t& Storage );
template<> jsval ToJSVal( const ssize_t& Native );
template<> jsval ToJSVal( ssize_t& Native );
#endif
#endif
// double
template<> bool ToPrimitive( JSContext* cx, jsval v, double& Storage );
template<> jsval ToJSVal( const double& Native );
template<> jsval ToJSVal( double& Native );
// float
template<> bool ToPrimitive( JSContext* cx, jsval v, float& Storage );
template<> jsval ToJSVal( const float& Native );
template<> jsval ToJSVal( float& Native );
// bool
template<> bool ToPrimitive( JSContext* cx, jsval v, bool& Storage );
template<> jsval ToJSVal( const bool& Native );
template<> jsval ToJSVal( bool& Native );
/*
// char*
template<> bool ToPrimitive( JSContext* cx, jsval v, char*& Storage );
template<> jsval ToJSVal( const char* Native );
template<> jsval ToJSVal( char* Native );
*/
// CStrW
template<> bool ToPrimitive( JSContext* cx, jsval v, CStrW& Storage );
template<> jsval ToJSVal( const CStrW& Native );
template<> jsval ToJSVal( CStrW& Native );
// CStr(8)
template<> bool ToPrimitive( JSContext* cx, jsval v, CStr8& Storage );
template<> jsval ToJSVal( const CStr8& Native );
template<> jsval ToJSVal( CStr8& Native );
// jsval
// Don't want to just use jsval directly, because it's equivalent to long and
// can cause conflicts or confusion. So create a simple wrapper class for it,
// so it's a real distinguishable type.
struct jsval_t
{
jsval v;
jsval_t(jsval v) : v(v) {}
};
template<> jsval ToJSVal( const jsval_t& Native );
// Intelligent CStrW->JSVal conversion
jsval JSParseString( const CStrW& String );
/* MT: Maybe:
#define JSCOPY_CAST( For, Use ) \
template<> bool ToPrimitive( JSContext* cx, jsval v, For& Storage ) \
{ \
Use temp; \
if( !ToPrimitive