Commit d97efe9f authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Replace old type utils by new ones.

This should help reduce the amount of leaks, as the new npapi::Variant
class handles the memory management automatically.
This also fixes at least a memory leak when converting from string to
anything else
parent aff97d49
This diff is collapsed.
...@@ -164,7 +164,7 @@ protected: ...@@ -164,7 +164,7 @@ protected:
InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result); InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result);
void parseOptions(const NPString &s, int *i_options, char*** ppsz_options); void parseOptions(const NPString& s, int *i_options, char*** ppsz_options);
void parseOptions(NPObject *obj, int *i_options, char*** ppsz_options); void parseOptions(NPObject *obj, int *i_options, char*** ppsz_options);
private: private:
......
...@@ -32,27 +32,6 @@ ...@@ -32,27 +32,6 @@
#include "nporuntime.h" #include "nporuntime.h"
char* RuntimeNPObject::stringValue(const NPString &s)
{
NPUTF8 *val = static_cast<NPUTF8*>(malloc((s.UTF8Length+1) * sizeof(*val)));
if( val )
{
strncpy(val, s.UTF8Characters, s.UTF8Length);
val[s.UTF8Length] = '\0';
}
return val;
}
char* RuntimeNPObject::stringValue(const NPVariant &v)
{
char *s = NULL;
if( NPVARIANT_IS_STRING(v) )
{
return stringValue(NPVARIANT_TO_STRING(v));
}
return s;
}
RuntimeNPObject::InvokeResult RuntimeNPObject::getProperty(int, NPVariant &) RuntimeNPObject::InvokeResult RuntimeNPObject::getProperty(int, NPVariant &)
{ {
/* default behaviour */ /* default behaviour */
......
...@@ -51,71 +51,6 @@ public: ...@@ -51,71 +51,6 @@ public:
// ownership problems with firefox. // ownership problems with firefox.
template<class T> void InstantObj( NPObject *&obj ); template<class T> void InstantObj( NPObject *&obj );
/*
** utility functions
*/
static bool isBoolValue(const NPVariant &v)
{
return NPVARIANT_IS_BOOLEAN(v)
|| isNumberValue(v);
};
static bool boolValue(const NPVariant &v)
{
if( NPVARIANT_IS_BOOLEAN(v) )
{
return NPVARIANT_TO_BOOLEAN(v);
}
if( NPVARIANT_IS_STRING(v) )
{
if(!strcasecmp(stringValue(NPVARIANT_TO_STRING(v)), "true"))
return true;
}
if( isNumberValue(v) )
{
return doubleValue(v) != 0;
}
return false;
};
static bool isNumberValue(const NPVariant &v)
{
return NPVARIANT_IS_INT32(v)
|| NPVARIANT_IS_DOUBLE(v)
|| NPVARIANT_IS_STRING(v);
};
static int intValue(const NPVariant &v)
{
switch( v.type ) {
case NPVariantType_Int32:
return NPVARIANT_TO_INT32(v);
case NPVariantType_Double:
return(int)NPVARIANT_TO_DOUBLE(v);
case NPVariantType_String:
return atoi( stringValue(NPVARIANT_TO_STRING(v)) );
default:
return 0;
}
};
static double doubleValue(const NPVariant &v)
{
switch( v.type ) {
case NPVariantType_Int32:
return(double)NPVARIANT_TO_INT32(v);
case NPVariantType_Double:
return NPVARIANT_TO_DOUBLE(v);
case NPVariantType_String:
return atof( stringValue(NPVARIANT_TO_STRING(v)) );
default:
return 0;
}
};
static char* stringValue(const NPString &v);
static char* stringValue(const NPVariant &v);
bool isValid() bool isValid()
{ {
return _instance != NULL; return _instance != NULL;
......
...@@ -29,9 +29,132 @@ ...@@ -29,9 +29,132 @@
#include <type_traits> #include <type_traits>
#include <cstring> #include <cstring>
using CStr = std::unique_ptr<char, void(*)(void*)>;
namespace npapi namespace npapi
{ {
// We want to handle both NPObject* and NPObject, though
// we don't want const char* to be converted to char.
// char* should be considered as const char*, const int as int...
namespace details
{
// Remove the first pointer to allow std::remove_cv to process the type
// instead of the pointer
template <typename T>
using PointerLess = typename std::remove_pointer<T>::type;
// Remove the const & volatile
template <typename T>
using Decayed = typename std::remove_cv<PointerLess<T>>::type;
}
template <typename T>
using TraitsType = typename std::conditional<
std::is_same<
details::Decayed<T>,
NPObject
>::value,
// Keep NPObject as this. The traits is using the raw pointerless type.
NPObject,
// Re-add the pointer if the type isn't NPObject & T was a pointer type
typename std::conditional<
std::is_pointer<T>::value,
typename std::add_pointer<details::Decayed<T>>::type,
details::Decayed<T>
>::type
>::type;
using NPStringPtr = std::unique_ptr<NPUTF8, void(*)(void*)>;
inline bool is_null( const NPVariant& v )
{
return NPVARIANT_IS_NULL( v );
}
inline bool is_number( const NPVariant& v )
{
return NPVARIANT_IS_INT32(v)
|| NPVARIANT_IS_DOUBLE(v)
|| NPVARIANT_IS_STRING(v);
}
inline bool is_bool( const NPVariant &v )
{
return NPVARIANT_IS_BOOLEAN( v ) ||
is_number( v );
}
inline bool to_bool( const NPVariant& v )
{
if( NPVARIANT_IS_BOOLEAN(v) )
{
return NPVARIANT_TO_BOOLEAN(v);
}
else if( NPVARIANT_IS_STRING(v) )
{
if(!strcasecmp(NPVARIANT_TO_STRING(v).UTF8Characters, "true"))
return true;
}
else if ( NPVARIANT_IS_INT32(v) )
{
return NPVARIANT_TO_INT32(v) != 0;
}
else if ( NPVARIANT_IS_DOUBLE(v) )
{
return NPVARIANT_TO_DOUBLE(v) != .0;
}
return false;
}
inline bool is_string( const NPVariant& v )
{
return NPVARIANT_IS_STRING( v );
}
inline NPStringPtr to_string( const NPVariant& v )
{
auto s = NPVARIANT_TO_STRING( v );
NPUTF8* buff = (NPUTF8*)NPN_MemAlloc(s.UTF8Length + 1);
memcpy( buff, s.UTF8Characters, s.UTF8Length + 1 );
return NPStringPtr( buff, NPN_MemFree );
}
// Returns the raw string, uncopied.
// The pointer becomes invalid as soon as "v" is destroyed
inline const NPUTF8* to_tmp_string( const NPVariant& v )
{
return NPVARIANT_TO_STRING(v).UTF8Characters;
}
inline int32_t to_int( const NPVariant& v )
{
if ( NPVARIANT_IS_INT32( v ) )
return NPVARIANT_TO_INT32( v );
else if ( NPVARIANT_IS_DOUBLE( v ) )
return (int32_t)NPVARIANT_TO_DOUBLE( v );
else if ( NPVARIANT_IS_STRING( v ) )
{
auto& s = NPVARIANT_TO_STRING( v );
return atoi( s.UTF8Characters );
}
return 0;
}
inline double to_double( const NPVariant& v )
{
if ( NPVARIANT_IS_DOUBLE( v ) )
return NPVARIANT_TO_DOUBLE( v );
else if ( NPVARIANT_IS_INT32( v ) )
return (double)NPVARIANT_TO_INT32( v );
else if ( NPVARIANT_IS_STRING( v ) )
{
auto& s = NPVARIANT_TO_STRING( v );
return atof( s.UTF8Characters );
}
return .0;
}
// We don't want conversion of unknown types to work like any other types. // We don't want conversion of unknown types to work like any other types.
// This returns void, so if ( traits<std::vector<...>>::is() ) will fail to build. // This returns void, so if ( traits<std::vector<...>>::is() ) will fail to build.
// This is also true for conversions to & from types we don't support // This is also true for conversions to & from types we don't support
...@@ -43,7 +166,7 @@ struct traits<std::nullptr_t> ...@@ -43,7 +166,7 @@ struct traits<std::nullptr_t>
{ {
static bool is( const NPVariant& v ) static bool is( const NPVariant& v )
{ {
return NPVARIANT_IS_NULL( v ); return is_null( v );
} }
static void from( std::nullptr_t, NPVariant& v ) static void from( std::nullptr_t, NPVariant& v )
...@@ -57,12 +180,12 @@ struct traits<bool> ...@@ -57,12 +180,12 @@ struct traits<bool>
{ {
static bool is( const NPVariant& v ) static bool is( const NPVariant& v )
{ {
return NPVARIANT_IS_BOOLEAN( v ); return is_bool( v );
} }
static bool to( const NPVariant& v ) static bool to( const NPVariant& v )
{ {
return NPVARIANT_TO_BOOLEAN( v ); return to_bool( v );
} }
static void from( bool b, NPVariant& v ) static void from( bool b, NPVariant& v )
...@@ -79,12 +202,12 @@ struct traits<T, typename std::enable_if< ...@@ -79,12 +202,12 @@ struct traits<T, typename std::enable_if<
{ {
static bool is( const NPVariant& v ) static bool is( const NPVariant& v )
{ {
return NPVARIANT_IS_INT32( v ); return is_number( v );
} }
static int to( const NPVariant& v ) static int to( const NPVariant& v )
{ {
return NPVARIANT_TO_INT32( v ); return to_int( v );
} }
static void from( T i, NPVariant& v ) static void from( T i, NPVariant& v )
...@@ -94,7 +217,7 @@ struct traits<T, typename std::enable_if< ...@@ -94,7 +217,7 @@ struct traits<T, typename std::enable_if<
}; };
template <> template <>
struct traits<NPObject*> struct traits<NPObject>
{ {
static bool is( const NPVariant& v ) static bool is( const NPVariant& v )
{ {
...@@ -120,12 +243,12 @@ struct traits<T, typename std::enable_if< ...@@ -120,12 +243,12 @@ struct traits<T, typename std::enable_if<
{ {
static bool is( const NPVariant& v ) static bool is( const NPVariant& v )
{ {
return NPVARIANT_IS_DOUBLE( v ); return is_number( v );
} }
static double to( const NPVariant& v ) static double to( const NPVariant& v )
{ {
return NPVARIANT_TO_DOUBLE( v ); return to_double( v );
} }
static void from( T d, NPVariant& v ) static void from( T d, NPVariant& v )
...@@ -139,7 +262,7 @@ struct traits<NPString> ...@@ -139,7 +262,7 @@ struct traits<NPString>
{ {
static bool is( const NPVariant& v ) static bool is( const NPVariant& v )
{ {
return NPVARIANT_IS_STRING( v ); return is_string( v );
} }
static NPString to( const NPVariant& v ) static NPString to( const NPVariant& v )
...@@ -149,9 +272,48 @@ struct traits<NPString> ...@@ -149,9 +272,48 @@ struct traits<NPString>
static void from( NPString s, NPVariant& v ) static void from( NPString s, NPVariant& v )
{ {
NPUTF8* buff = (NPUTF8*)NPN_MemAlloc(s.UTF8Length); auto raw = strdup( s.UTF8Characters );
strcpy( buff, s.UTF8Characters ); STRINGZ_TO_NPVARIANT( raw, v );
STRINGZ_TO_NPVARIANT( buff, v ); }
};
template <>
struct traits<NPUTF8*>
{
static bool is( const NPVariant& v )
{
return is_string( v );
}
static const NPUTF8* to( const NPVariant& v )
{
return to_tmp_string( v );
}
static void from( const char* str, NPVariant& v )
{
auto copy = strdup( str );
STRINGZ_TO_NPVARIANT( copy, v );
}
};
template <>
struct traits<std::string>
{
static bool is( const NPVariant& v )
{
return is_string( v );
}
static std::string to( const NPVariant& v )
{
return std::string( to_tmp_string( v ) );
}
static void from( const std::string& str, NPVariant& v )
{
auto copy = strdup( str.c_str() );
STRINGZ_TO_NPVARIANT( copy, v );
} }
}; };
...@@ -170,6 +332,10 @@ public: ...@@ -170,6 +332,10 @@ public:
Variant( const NPVariant& v ) Variant( const NPVariant& v )
: m_variant( v ) : m_variant( v )
{ {
if (is<NPString>() )
traits<NPString>::from( (NPString)*this, m_variant );
else if ( is<NPObject>() )
traits<NPObject>::from( (NPObject*)*this, m_variant );
} }
Variant(const Variant& v) Variant(const Variant& v)
...@@ -182,7 +348,7 @@ public: ...@@ -182,7 +348,7 @@ public:
Variant(const T& t) Variant(const T& t)
{ {
memset( &m_variant, 0, sizeof( m_variant ) ); memset( &m_variant, 0, sizeof( m_variant ) );
traits<T>::from( t, m_variant ); traits<TraitsType<T>>::from( t, m_variant );
} }
Variant& operator=(const Variant& v) Variant& operator=(const Variant& v)
...@@ -196,7 +362,7 @@ public: ...@@ -196,7 +362,7 @@ public:
return *this; return *this;
} }
m_variant = v.m_variant; m_variant = v.m_variant;
if (v.is<NPObject*>()) if (v.is<NPObject>())
NPN_RetainObject( *this ); NPN_RetainObject( *this );
return *this; return *this;
} }
...@@ -204,20 +370,21 @@ public: ...@@ -204,20 +370,21 @@ public:
Variant(Variant&& v) Variant(Variant&& v)
{ {
m_variant = v.m_variant; m_variant = v.m_variant;
memset( &v.m_variant, 0, sizeof( m_variant ) ); memset( &v.m_variant, 0, sizeof( v.m_variant ) );
} }
Variant& operator=(Variant&& v) Variant& operator=(Variant&& v)
{ {
release(); release();
m_variant = v.m_variant; m_variant = v.m_variant;
memset( &v.m_variant, 0, sizeof( m_variant ) ); memset( &v.m_variant, 0, sizeof( v.m_variant ) );
} }
template <typename T> template <typename T>
bool is() const bool is() const
{ {
return traits<T>::is( m_variant ); return traits<TraitsType<T>>::is( m_variant );
} }
// /!\ Warning /!\ This does not retain the value for strings & objects // /!\ Warning /!\ This does not retain the value for strings & objects
...@@ -226,8 +393,8 @@ public: ...@@ -226,8 +393,8 @@ public:
template <typename T> template <typename T>
operator T() const operator T() const
{ {
assert(traits<T>::is( m_variant )); assert(traits<TraitsType<T>>::is( m_variant ));
return traits<T>::to( m_variant ); return traits<TraitsType<T>>::to( m_variant );
} }
operator const NPVariant() const operator const NPVariant() const
...@@ -240,6 +407,11 @@ public: ...@@ -240,6 +407,11 @@ public:
return &m_variant; return &m_variant;
} }
operator NPVariant*()
{
return &m_variant;
}
~Variant() ~Variant()
{ {
release(); release();
...@@ -247,8 +419,7 @@ public: ...@@ -247,8 +419,7 @@ public:
void release() void release()
{ {
if ( is<NPString>() || is<NPObject*>() ) NPN_ReleaseVariantValue( &m_variant );
NPN_ReleaseVariantValue( &m_variant );
} }
private: private:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment