[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r12171: A first attempt at an owners
From: |
Bastiaan Jacques |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r12171: A first attempt at an ownership model for NPVariants. Also simplify APIs, |
Date: |
Thu, 22 Apr 2010 18:22:57 +0200 |
User-agent: |
Bazaar (2.0.3) |
------------------------------------------------------------
revno: 12171
committer: Bastiaan Jacques <address@hidden>
branch nick: trunk
timestamp: Thu 2010-04-22 18:22:57 +0200
message:
A first attempt at an ownership model for NPVariants. Also simplify APIs,
fix quite a few bugs and introduce a small measure of const-correctness.
added:
plugin/npapi/GnashNPVariant.h
modified:
plugin/npapi/Makefile.am
plugin/npapi/callbacks.cpp
plugin/npapi/external.cpp
plugin/npapi/external.h
plugin/npapi/plugin.cpp
plugin/npapi/plugin.h
plugin/npapi/pluginScriptObject.cpp
plugin/npapi/pluginScriptObject.h
plugin/npapi/test.cpp
=== added file 'plugin/npapi/GnashNPVariant.h'
--- a/plugin/npapi/GnashNPVariant.h 1970-01-01 00:00:00 +0000
+++ b/plugin/npapi/GnashNPVariant.h 2010-04-22 16:22:57 +0000
@@ -0,0 +1,139 @@
+//
+// Copyright (C) 2010 Free Software Foundation, Inc
+//
+// This program 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 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef GNASH_NPVARIANT_H
+#define GNASH_NPVARIANT_H
+
+#include "npapi.h"
+#include "npruntime.h"
+
+namespace gnash {
+
+/// Makes a deep copy of a NPVariant.
+/// @param from The source NPVariant to copy values from.
+/// @param to The destination NPVariant.
+inline void
+CopyVariantValue(const NPVariant& from, NPVariant& to)
+{
+ // First, we'll make a shallow copy, which is fine for most variant types.
+ to = from;
+
+ // For deep copies for strings we obviously have to duplicate the string,
+ // and object pointer copies need to have their reference count increased.
+ switch(from.type) {
+ case NPVariantType_String:
+ {
+ const NPString& fromstr = NPVARIANT_TO_STRING(from);
+ const uint32_t& len = fromstr.UTF8Length;
+
+ NPUTF8* tostr = static_cast<NPUTF8*>(NPN_MemAlloc(len));
+ std::copy(fromstr.UTF8Characters, fromstr.UTF8Characters+len,
tostr);
+
+ STRINGN_TO_NPVARIANT(tostr, len, to);
+ break;
+ }
+ case NPVariantType_Object:
+ NPN_RetainObject(NPVARIANT_TO_OBJECT(to));
+ break;
+ default:
+ {}
+ }
+}
+
+/// Construct a std::string from an NPString.
+//
+/// NPStrings are not guaranteed to be NULL-terminated.
+inline std::string
+NPStringToString(const NPString& str)
+{
+ return std::string(str.UTF8Characters, str.UTF8Length);
+}
+
+
+/// This class holds ownership of (a copy of) an NPVariant.
+//
+/// The user of this class must keep in mind that it does not take
+/// ownership of already-allocated resources. The user must supply
+/// an NPVariant to construct a GnashNPVariant, and must subsequently
+/// release any resources associated with the original NPVariant.
+///
+/// When an object of type GnashNPVariant goes out of scope, the resources
+/// associated with the copied NPVariant will be released.
+class GnashNPVariant
+{
+public:
+ GnashNPVariant()
+ {
+ NULL_TO_NPVARIANT(_variant);
+ }
+
+ GnashNPVariant(const GnashNPVariant& var)
+ {
+ CopyVariantValue(var._variant, _variant);
+ }
+
+ /// Construct a GnashNPVariant by copying an NPVariant.
+ /// @param var The NPVariant to copy from.
+ GnashNPVariant(const NPVariant& var)
+ {
+ CopyVariantValue(var, _variant);
+ }
+
+ GnashNPVariant& operator= (const GnashNPVariant& var)
+ {
+ NPN_ReleaseVariantValue(&_variant);
+
+ CopyVariantValue(var._variant, _variant);
+
+ return *this;
+ }
+
+ /// Copy the contained NPVariant into another NPVariant.
+ //
+ /// This is useful to return a GnashNPVariant to an external API.
+ /// @param dest The NPVariant to copy the value into.
+ void
+ copy(NPVariant& dest) const
+ {
+ CopyVariantValue(_variant, dest);
+ }
+
+ /// Obtain a reference to the contained NPVariant.
+ //
+ /// This method returns a const reference to avoid the temptation
+ /// to modify ownership, which could lead to memory errors. Use copy() if
+ /// you want to alter the contained NPVariant.
+ const NPVariant& get() const { return _variant; }
+
+ ~GnashNPVariant()
+ {
+ NPN_ReleaseVariantValue(&_variant);
+ }
+
+private:
+ NPVariant _variant;
+};
+
+} // namespace gnash
+
+#endif // GNASH_NPVARIANT_H
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
=== modified file 'plugin/npapi/Makefile.am'
--- a/plugin/npapi/Makefile.am 2010-04-15 00:40:40 +0000
+++ b/plugin/npapi/Makefile.am 2010-04-22 16:22:57 +0000
@@ -76,8 +76,9 @@
external.cpp
noinst_HEADERS += pluginScriptObject.h \
- callbacks.h \
- external.h
+ callbacks.h \
+ external.h \
+ GnashNPVariant.h
libgnashplugin_la_SOURCES += pluginScriptObject.cpp \
callbacks.cpp \
external.cpp
=== modified file 'plugin/npapi/callbacks.cpp'
--- a/plugin/npapi/callbacks.cpp 2010-04-21 19:46:03 +0000
+++ b/plugin/npapi/callbacks.cpp 2010-04-22 16:22:57 +0000
@@ -105,8 +105,8 @@
std::string varname;
if (argCount == 2) {
- varname = NPVARIANT_TO_STRING(args[0]).UTF8Characters;
- NPVariant *value = const_cast<NPVariant *>(&args[1]);
+ varname = NPStringToString(NPVARIANT_TO_STRING(args[0]));
+ const NPVariant& value = args[1];
// log_debug("Setting Variable \"%s\"", varname);
gpso->SetVariable(varname, value);
BOOLEAN_TO_NPVARIANT(true, *result);
@@ -136,23 +136,18 @@
log_debug(__PRETTY_FUNCTION__);
GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
- NPVariant *value = 0;
std::string varname;
// This method only takes one argument
if (argCount == 1) {
- varname = NPVARIANT_TO_STRING(args[0]).UTF8Characters;
- value = gpso->GetVariable(varname);
- if (value == 0) {
- NULL_TO_NPVARIANT(*result);
- } else {
- CopyVariantValue(*value, *result);
-
- NPN_MemFree(value);
- return true;
- }
+ varname = NPStringToString(NPVARIANT_TO_STRING(args[0]));
+
+ GnashNPVariant value = gpso->GetVariable(varname);
+ value.copy(*result);
+
+ return true;
}
- NPVARIANT_IS_NULL(*result);
+ NULL_TO_NPVARIANT(*result);
return false;
}
@@ -232,20 +227,18 @@
BOOLEAN_TO_NPVARIANT(false, *result);
return false;
}
- const char *data = 0;
- ret = gpso->readPlayer(gpso->getControlFD(), &data, 0);
- if (ret == 0) {
+ std::string data = gpso->readPlayer(gpso->getControlFD());
+ if (data.empty()) {
BOOLEAN_TO_NPVARIANT(false, *result);
return false;
}
- NPVariant *value = ei.parseXML(data);
- if (NPVARIANT_TO_BOOLEAN(*value) == true) {
+
+ GnashNPVariant value = ei.parseXML(data);
+ if (NPVARIANT_TO_BOOLEAN(value.get()) == true) {
BOOLEAN_TO_NPVARIANT(true, *result);
} else {
BOOLEAN_TO_NPVARIANT(false, *result);
}
- // free the memory used for the data, as it was allocated in
readPlayer().
- NPN_MemFree(value);
return true;
}
@@ -277,7 +270,7 @@
if (argCount == 2) {
ExternalInterface ei;
// int layer = NPVARIANT_TO_INT32(args[0]);
- // std::string url = NPVARIANT_TO_STRING(args[1]).UTF8Characters;
+ // std::string url = NPStringToString(NPVARIANT_TO_STRING(args[1]));
std::string str = ei.convertNPVariant(&args[0]);
std::vector<std::string> iargs;
iargs.push_back(str);
@@ -392,9 +385,8 @@
BOOLEAN_TO_NPVARIANT(false, *result);
return false;
}
- const char *data = 0;
- ret = gpso->readPlayer(gpso->getControlFD(), &data, 0);
- if (ret == 0) {
+ std::string data = gpso->readPlayer(gpso->getControlFD());
+ if (data.empty()) {
BOOLEAN_TO_NPVARIANT(false, *result);
return false;
}
@@ -405,8 +397,6 @@
} else {
INT32_TO_NPVARIANT(0, *result);
}
- // free the memory used for the data, as it was allocated in
readPlayer().
- NPN_MemFree(value);
return true;
}
@@ -656,20 +646,18 @@
BOOLEAN_TO_NPVARIANT(false, *result);
return false;
}
- const char *data = 0;
- ret = gpso->readPlayer(gpso->getControlFD(), &data, 0);
- if (ret == 0) {
+ std::string data = gpso->readPlayer(gpso->getControlFD());
+ if (data.empty()) {
BOOLEAN_TO_NPVARIANT(false, *result);
return false;
}
- NPVariant *value = ei.parseXML(data);
- if (NPVARIANT_IS_INT32(*value)) {
- INT32_TO_NPVARIANT(NPVARIANT_TO_INT32(*value), *result);
+
+ GnashNPVariant value = ei.parseXML(data);
+ if (NPVARIANT_IS_INT32(value.get())) {
+ value.copy(*result);
} else {
INT32_TO_NPVARIANT(0, *result);
}
- // free the memory used for the data, as it was allocated in
readPlayer().
- NPN_MemFree(value);
return true;
}
=== modified file 'plugin/npapi/external.cpp'
--- a/plugin/npapi/external.cpp 2010-04-21 19:46:03 +0000
+++ b/plugin/npapi/external.cpp 2010-04-22 16:22:57 +0000
@@ -34,6 +34,8 @@
#include <boost/algorithm/string/erase.hpp>
+namespace gnash {
+
ExternalInterface::ExternalInterface ()
{
}
@@ -250,11 +252,11 @@
return invoke;
}
-NPVariant *
+GnashNPVariant
ExternalInterface::parseXML(const std::string &xml)
{
- NPVariant *value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
- NULL_TO_NPVARIANT(*value);
+ NPVariant value;
+ NULL_TO_NPVARIANT(value);
if (xml.empty()) {
return value;
@@ -270,23 +272,23 @@
tag = xml.substr(start, end);
// Look for the easy ones first
if (tag == "<null/>") {
- NULL_TO_NPVARIANT(*value);
+ NULL_TO_NPVARIANT(value);
} else if (tag == "<void/>") {
- VOID_TO_NPVARIANT(*value);
+ VOID_TO_NPVARIANT(value);
} else if (tag == "<true/>") {
- BOOLEAN_TO_NPVARIANT(true, *value);
+ BOOLEAN_TO_NPVARIANT(true, value);
} else if (tag == "<false/>") {
- BOOLEAN_TO_NPVARIANT(false, *value);
+ BOOLEAN_TO_NPVARIANT(false, value);
} else if (tag == "<number>") {
start = end;
end = xml.find("</number>");
std::string str = xml.substr(start, end-start);
if (str.find(".") != std::string::npos) {
double num = strtod(str.c_str(), NULL);
- DOUBLE_TO_NPVARIANT(num, *value);
+ DOUBLE_TO_NPVARIANT(num, value);
} else {
int num = strtol(str.c_str(), NULL, 0);
- INT32_TO_NPVARIANT(num, *value);
+ INT32_TO_NPVARIANT(num, value);
}
} else if (tag == "<string>") {
start = end;
@@ -298,37 +300,41 @@
data[length] = 0; // terminate the new string or bad things happen
// When an NPVariant becomes a string object, it *does not* make a
copy.
// Instead it stores the pointer (and length) we just allocated.
- STRINGN_TO_NPVARIANT(data, length, *value);
+ STRINGN_TO_NPVARIANT(data, length, value);
} else if (tag == "<array>") {
NPObject *obj = (NPObject *)NPN_MemAlloc(sizeof(NPObject));
start = end;
end = xml.find("</array");
std::string str = xml.substr(start, end-start);
- std::map<std::string, NPVariant *> props = parseProperties(str);
- std::map<std::string, NPVariant *>::iterator it;
+ std::map<std::string, GnashNPVariant> props = parseProperties(str);
+ std::map<std::string, GnashNPVariant>::iterator it;
for (it=props.begin(); it != props.end(); ++it) {
NPIdentifier id = NPN_GetStringIdentifier(it->first.c_str());
- NPVariant *value = it->second;
- NPN_SetProperty(NULL, obj, id, value);
+ GnashNPVariant& value = it->second;
+ NPN_SetProperty(NULL, obj, id, &value.get());
}
- OBJECT_TO_NPVARIANT(obj, *value);
+ OBJECT_TO_NPVARIANT(obj, value);
+ NPN_RetainObject(obj);
} else if (tag == "<object>") {
NPObject *obj = (NPObject *)NPN_MemAlloc(sizeof(NPObject));
start = end;
end = xml.find("</object");
std::string str = xml.substr(start, end-start);
- std::map<std::string, NPVariant *> props = parseProperties(str);
- std::map<std::string, NPVariant *>::iterator it;
+ std::map<std::string, GnashNPVariant> props = parseProperties(str);
+ std::map<std::string, GnashNPVariant>::iterator it;
for (it=props.begin(); it != props.end(); ++it) {
NPIdentifier id = NPN_GetStringIdentifier(it->first.c_str());
- NPVariant *value = it->second;
- NPN_SetProperty(NULL, obj, id, value);
+ GnashNPVariant& value = it->second;
+ NPN_SetProperty(NULL, obj, id, &value.get());
}
- OBJECT_TO_NPVARIANT(obj, *value);
+ OBJECT_TO_NPVARIANT(obj, value);
+ NPN_RetainObject(obj);
}
}
- return value;
+ GnashNPVariant rv(value);
+ NPN_ReleaseVariantValue(&value);
+ return rv;
}
std::string
@@ -340,7 +346,7 @@
double num = NPVARIANT_TO_DOUBLE(*value);
ss << "<number>" << num << "</number>";
} else if (NPVARIANT_IS_STRING(*value)) {
- std::string str(NPVARIANT_TO_STRING(*value).UTF8Characters);
+ std::string str = NPStringToString(NPVARIANT_TO_STRING(*value));
ss << "<string>" << str << "</string>";
} else if (NPVARIANT_IS_BOOLEAN(*value)) {
bool flag = NPVARIANT_TO_BOOLEAN(*value);
@@ -363,10 +369,10 @@
return ss.str();
}
-std::map<std::string, NPVariant *>
+std::map<std::string, GnashNPVariant>
ExternalInterface::parseProperties(const std::string &xml)
{
- std::map<std::string, NPVariant *> props;
+ std::map<std::string, GnashNPVariant> props;
std::string::size_type start = 0;
std::string::size_type end;
@@ -391,10 +397,10 @@
return props;
}
-std::vector<NPVariant *>
+std::vector<GnashNPVariant>
ExternalInterface::parseArguments(const std::string &xml)
{
- std::vector<NPVariant *> args;
+ std::vector<GnashNPVariant> args;
std::string::size_type start = 0;
std::string::size_type end;
@@ -414,14 +420,15 @@
if (data == "</arguments>") {
break;
}
- NPVariant *value = parseXML(sub);
- args.push_back(value);
+ args.push_back(parseXML(sub));
data.erase(0, end);
}
return args;
}
+} // namespace gnash
+
// local Variables:
// mode: C++
// indent-tabs-mode: nil
=== modified file 'plugin/npapi/external.h'
--- a/plugin/npapi/external.h 2010-04-18 00:32:42 +0000
+++ b/plugin/npapi/external.h 2010-04-22 16:22:57 +0000
@@ -31,13 +31,17 @@
#include "npapi.h"
#include "npruntime.h"
+#include "GnashNPVariant.h"
+
+namespace gnash {
+
class ExternalInterface
{
public:
typedef struct {
std::string name;
std::string type;
- std::vector<NPVariant *> args;
+ std::vector<GnashNPVariant> args;
} invoke_t;
ExternalInterface ();
@@ -59,14 +63,16 @@
std::string makeArray (std::vector<std::string> &args);
std::string makeObject (std::map<std::string, std::string> &args);
- NPVariant *parseXML(const std::string &xml);
+ GnashNPVariant parseXML(const std::string &xml);
invoke_t *parseInvoke(const std::string &xml);
- std::map<std::string, NPVariant *> parseProperties(const std::string &xml);
- std::vector<NPVariant *> parseArguments(const std::string &xml);
+ std::map<std::string, GnashNPVariant> parseProperties(const std::string
&xml);
+ std::vector<GnashNPVariant> parseArguments(const std::string &xml);
std::string convertNPVariant (const NPVariant *npv);
};
+}
+
#endif // GNASH_PLUGIN_EXTERNAL_H
// local Variables:
=== modified file 'plugin/npapi/plugin.cpp'
--- a/plugin/npapi/plugin.cpp 2010-04-21 20:24:32 +0000
+++ b/plugin/npapi/plugin.cpp 2010-04-22 16:22:57 +0000
@@ -860,7 +860,7 @@
}
void
-create_standalone_launcher(const char* page_url, const std::string& swf_url,
+create_standalone_launcher(const std::string& page_url, const std::string&
swf_url,
const std::map<std::string, std::string>& params)
{
#ifdef CREATE_STANDALONE_GNASH_LAUNCHER
@@ -884,7 +884,7 @@
saLauncher << "#!/bin/sh" << std::endl
<< getGnashExecutable() << " ";
- if (page_url) {
+ if (!page_url.empty()) {
saLauncher << "-U '" << page_url << "' ";
}
@@ -918,8 +918,8 @@
arg_vec.push_back("-u");
arg_vec.push_back(_swf_url);
- const char* pageurl = getCurrentPageURL();
- if (!pageurl) {
+ std::string pageurl = getCurrentPageURL();
+ if (pageurl.empty()) {
gnash::log_error("Could not get current page URL!");
} else {
arg_vec.push_back("-U");
@@ -1126,7 +1126,7 @@
exit (-1);
}
-const char*
+std::string
nsPluginInstance::getCurrentPageURL() const
{
NPP npp = _instance;
@@ -1171,7 +1171,7 @@
const NPString& propValue = NPVARIANT_TO_STRING(vProp);
- return propValue.UTF8Characters; // const char *
+ return NPStringToString(propValue);
}
void
=== modified file 'plugin/npapi/plugin.h'
--- a/plugin/npapi/plugin.h 2010-04-22 08:05:01 +0000
+++ b/plugin/npapi/plugin.h 2010-04-22 16:22:57 +0000
@@ -132,7 +132,7 @@
GnashPluginScriptObject *_scriptObject;
//#endif
- const char* getCurrentPageURL() const;
+ std::string getCurrentPageURL() const;
};
// Define the following to make the plugin verbose
=== modified file 'plugin/npapi/pluginScriptObject.cpp'
--- a/plugin/npapi/pluginScriptObject.cpp 2010-04-21 23:14:08 +0000
+++ b/plugin/npapi/pluginScriptObject.cpp 2010-04-22 16:22:57 +0000
@@ -117,27 +117,21 @@
void
GnashPluginScriptObject::AddProperty(const std::string &name,
- const std::string &str)
+ const std::string &val)
{
NPIdentifier id = NPN_GetStringIdentifier(name.c_str());
- NPVariant *value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
- int length = str.size();;
- char *bar = (char *)NPN_MemAlloc(length+1);
- std::copy(str.begin(), str.end(), bar);
- bar[length] = 0; // terminate the new string or bad things happen
-
- // When an NPVariant becomes a string object, it *does not* make a copy.
- // Instead it stores the pointer (and length) we just allocated.
- STRINGN_TO_NPVARIANT(bar, length, *value);
- SetProperty(id, value);
+
+ NPVariant strvar;
+ STRINGN_TO_NPVARIANT(val.c_str(), val.size(), strvar);
+ SetProperty(id, strvar);
}
void
GnashPluginScriptObject::AddProperty(const std::string &name, double num)
{
NPIdentifier id = NPN_GetStringIdentifier(name.c_str());
- NPVariant *value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
- DOUBLE_TO_NPVARIANT(num, *value);
+ NPVariant value;
+ DOUBLE_TO_NPVARIANT(num, value);
SetProperty(id, value);
}
@@ -145,8 +139,8 @@
GnashPluginScriptObject::AddProperty(const std::string &name, int num)
{
NPIdentifier id = NPN_GetStringIdentifier(name.c_str());
- NPVariant *value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
- INT32_TO_NPVARIANT(num, *value);
+ NPVariant value;
+ INT32_TO_NPVARIANT(num, value);
SetProperty(id, value);
}
@@ -419,7 +413,7 @@
// log_debug(__PRETTY_FUNCTION__);
GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
- return gpso->SetProperty(name, value);
+ return gpso->SetProperty(name, *value);
}
bool
@@ -483,20 +477,20 @@
log_debug("Getting Property %d\"...", NPN_IntFromIdentifier(name));
}
- std::map<NPIdentifier, const NPVariant *>::iterator it;
+ std::map<NPIdentifier, GnashNPVariant>::const_iterator it;
it = _properties.find(name);
if (it == _properties.end()) {
return false;
}
- const NPVariant *value = it->second;
- CopyVariantValue(*value, *result);
+ const GnashNPVariant& val = it->second;
+ val.copy(*result);
return true;
};
bool
-GnashPluginScriptObject::SetProperty(NPIdentifier name, const NPVariant *value)
+GnashPluginScriptObject::SetProperty(NPIdentifier name, const NPVariant& value)
{
// log_debug(__PRETTY_FUNCTION__);
@@ -510,13 +504,13 @@
{
// log_debug(__PRETTY_FUNCTION__);
- std::map<NPIdentifier, const NPVariant *>::iterator it;
+ std::map<NPIdentifier, GnashNPVariant>::iterator it;
it = _properties.find(name);
if (it != _properties.end()) {
_properties.erase(it);
return true;
- }
-
+ }
+
return false;
}
@@ -618,7 +612,7 @@
// "Command Name Type value\n", ie... "SetVariable var1 string value1\n"
bool
GnashPluginScriptObject::SetVariable(const std::string &name,
- NPVariant *value)
+ const NPVariant& value)
{
log_debug(__PRETTY_FUNCTION__);
@@ -627,7 +621,7 @@
std::vector<std::string> iargs;
std::string str = ei.makeString(name);
iargs.push_back(str);
- str = ei.convertNPVariant(value);
+ str = ei.convertNPVariant(&value);
iargs.push_back(str);
str = ei.makeInvoke("SetVariable", iargs);
@@ -646,7 +640,7 @@
// GetVariable sends a message to the player that looks like this:
// "Command Name\n", ie... "GetVariable var1\n". Then it waits
// for the response with the type and value.
-NPVariant *
+GnashNPVariant
GnashPluginScriptObject::GetVariable(const std::string &name)
{
log_debug(__PRETTY_FUNCTION__);
@@ -659,7 +653,6 @@
log_debug("Trying to get a value for %s.", name);
- NPVariant *value = 0;
size_t ret = writePlayer(controlfd, str);
if (ret != str.size()) {
// If all the browser wants is the version, we don't need to
@@ -668,32 +661,27 @@
// be greater than 8.0.0. This appears to potentially be
// Google's way of trying to revent downloaders, as this requires
// plugin support.
+ NPVariant value;
if (name == "$version") {
- value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
- STRINGZ_TO_NPVARIANT(strdup("LNX 10,0,r999"), *value);
+ STRINGZ_TO_NPVARIANT(strdup("LNX 10,0,r999"), value);
} else {
log_error("Couldn't send GetVariable request, network problems.");
+ NULL_TO_NPVARIANT(value);
}
return value;
}
// Have the read function allocate the memory
- const char *data = 0;
- ret = readPlayer(controlfd, &data, 0);
- if (ret == 0) {
- value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
- NULL_TO_NPVARIANT(*value);
- return value;
+ std::string data = readPlayer(controlfd);
+ if (data.empty()) {
+ return GnashNPVariant();
}
- value = ei.parseXML(data);
+ GnashNPVariant parsed = ei.parseXML(data);
- // free the memory used for the data, as it was allocated in readPlayer().
- NPN_MemFree(const_cast<char *>(data));
-
- printNPVariant(value);
-
- return value;
+ printNPVariant(&parsed.get());
+
+ return parsed;
}
void
@@ -761,83 +749,58 @@
return 0;
}
-// Read the standalone player over the control socket
-int
-GnashPluginScriptObject::readPlayer(const std::string &data)
-{
-// log_debug(__PRETTY_FUNCTION__);
-
- const char *ptr = data.c_str();
- return readPlayer(_sockfds[READFD], &ptr, data.size());
-}
-
-int
-GnashPluginScriptObject::readPlayer(int fd, const std::string &data)
-{
-// log_debug(__PRETTY_FUNCTION__);
-
- const char *ptr = data.c_str();
- return readPlayer(fd, &ptr, data.size());
-}
-
-int
-GnashPluginScriptObject::readPlayer(const char **data, size_t length)
-{
- return readPlayer(_sockfds[READFD], data, length);
-}
-
-int
-GnashPluginScriptObject::readPlayer(int fd, const char **data, size_t length)
-{
-// log_debug(__PRETTY_FUNCTION__);
-
- if (fd > 0) {
- // Wait for some data from the player
- int bytes = 0;
- fd_set fdset;
- FD_ZERO(&fdset);
- FD_SET(fd, &fdset);
- struct timeval tval;
- tval.tv_sec = 10;
- tval.tv_usec = 0;
- // log_debug("Waiting for data... ");
- if (select(fd+1, &fdset, NULL, NULL, &tval)) {
- // log_debug("There is data in the network");
+std::string
+GnashPluginScriptObject::readPlayer(int fd)
+{
+// log_debug(__PRETTY_FUNCTION__);
+
+ std::string empty;
+
+ if (fd <= 0) {
+ log_error("Invalid fd passed");
+ return empty;
+ }
+
+ // Wait for some data from the player
+ int bytes = 0;
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+ struct timeval tval;
+ tval.tv_sec = 10;
+ tval.tv_usec = 0;
+ // log_debug("Waiting for data... ");
+ if (select(fd+1, &fdset, NULL, NULL, &tval)) {
+ // log_debug("There is data in the network");
#ifndef _WIN32
- ioctl(fd, FIONREAD, &bytes);
+ ioctl(fd, FIONREAD, &bytes);
#else
- ioctlSocket(fd, FIONREAD, &bytes);
+ ioctlSocket(fd, FIONREAD, &bytes);
#endif
- // } else {
- // log_debug("There is no data in the network");
- }
+ }
- // No data yet
- if (bytes == 0) {
- return 0;
- }
- log_debug("There are %d bytes in the network buffer", bytes);
-
- char *buf = 0;
- if (*data == 0) {
- // Since we know how bytes are in the network buffer, allocate
- // some memory to read the data.
- buf = (char *)NPN_MemAlloc(bytes+1);
- // terminate incase we want to treat the data like a string.
- buf[bytes] = 0;
- length = bytes;
- }
- int ret = ::read(fd, buf, bytes);
- if (ret == bytes) {
- *data = buf;
- }
-
- std::cout << buf << std::endl;
- return ret;
- }
+ // No data yet
+ if (bytes == 0) {
+ return empty;
+ }
+
+ log_debug("There are %d bytes in the network buffer", bytes);
+
+ std::string buf(bytes, '\0');
+
+ int ret = ::read(fd, &buf[0], bytes);
+ if (ret <= 0) {
+ return empty;
+ }
+
+ if (ret < bytes) {
+ buf.resize(ret);
+ }
+
+ std::cout << buf << std::endl;
- return 0;
+ return buf;
}
@@ -1049,34 +1012,6 @@
return plugin->handleInvoke(iochan, cond);
}
-void
-CopyVariantValue(const NPVariant& from, NPVariant& to)
-{
- // First, we'll make a shallow copy, which is fine for most variant types.
- to = from;
-
- // For deep copies for strings we obviously have to duplicate the string,
- // and object pointer copies need to have their reference count increased.
- switch(from.type) {
- case NPVariantType_String:
- {
- const NPString& fromstr = NPVARIANT_TO_STRING(from);
- const uint32_t& len = fromstr.UTF8Length;
-
- NPUTF8* tostr = static_cast<NPUTF8*>(NPN_MemAlloc(len));
- std::copy(fromstr.UTF8Characters, fromstr.UTF8Characters+len,
tostr);
-
- STRINGN_TO_NPVARIANT(tostr, len, to);
- break;
- }
- case NPVariantType_Object:
- NPN_RetainObject(NPVARIANT_TO_OBJECT(to));
- break;
- default:
- {}
- }
-}
-
} // end of gnash namespace
// local Variables:
=== modified file 'plugin/npapi/pluginScriptObject.h'
--- a/plugin/npapi/pluginScriptObject.h 2010-04-21 19:46:03 +0000
+++ b/plugin/npapi/pluginScriptObject.h 2010-04-22 16:22:57 +0000
@@ -41,6 +41,7 @@
#include <glib.h>
#include "npapi.h"
#include "npruntime.h"
+#include "GnashNPVariant.h"
#define READFD 0
#define WRITEFD 1
@@ -102,14 +103,14 @@
/// @param value the value to set the variable to
///
/// @return true or false based on the status of the invoke call
- bool SetVariable(const std::string &name, NPVariant *value);
+ bool SetVariable(const std::string &name, const NPVariant& value);
/// Get the value of a variable from the standalone player
///
/// @param name the name of the variable to set
///
/// @return the value as returned by the standalone player
- NPVariant *GetVariable(const std::string &name);
+ GnashNPVariant GetVariable(const std::string &name);
// Create a socketpair so we can talk to the player.
bool createPipe();
@@ -132,10 +133,7 @@
int writePlayer(int fd, const std::string &data);
// Read the standalone player over the control socket
- int readPlayer(const char **data, size_t length);
- int readPlayer(int fd, const char **data, size_t length);
- int readPlayer(const std::string &data);
- int readPlayer(int fd, const std::string &data);
+ std::string readPlayer(int fd);
protected:
bool AddMethod(NPIdentifier name, NPInvokeFunctionPtr func);
@@ -152,7 +150,7 @@
bool InvokeDefault(const NPVariant *args, uint32_t argCount, NPVariant
*result);
bool HasProperty(NPIdentifier name);
bool GetProperty(NPIdentifier name, NPVariant *result);
- bool SetProperty(NPIdentifier name, const NPVariant *value);
+ bool SetProperty(NPIdentifier name, const NPVariant& value);
bool RemoveProperty(NPIdentifier name);
bool Enumerate(NPIdentifier **identifier, uint32_t *count);
bool Construct(const NPVariant *data, uint32_t argCount, NPVariant
*result);
@@ -183,8 +181,8 @@
// _nppinstance->pdata should be the nsPluginInstance once NPP_New() is
finished.
NPP _nppinstance;
- std::map<NPIdentifier, const NPVariant*> _properties;
- std::map<NPIdentifier, NPInvokeFunctionPtr> _methods;
+ std::map<NPIdentifier, GnashNPVariant> _properties;
+ std::map<NPIdentifier, NPInvokeFunctionPtr> _methods;
// 0 for reading, 1 for writing
int _sockfds[2];
GIOChannel *_iochan[2];
=== modified file 'plugin/npapi/test.cpp'
--- a/plugin/npapi/test.cpp 2010-04-18 00:32:42 +0000
+++ b/plugin/npapi/test.cpp 2010-04-22 16:22:57 +0000
@@ -21,6 +21,7 @@
#include <cstdlib>
#include <vector>
#include <map>
+#include <cassert>
#include "npapi.h"
#include "npruntime.h"
@@ -39,6 +40,8 @@
int
main(int argc, char *argv[])
{
+ using namespace gnash;
+
ExternalInterface ei;
NPVariant *value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
@@ -154,9 +157,9 @@
// Parsing tests
//
xml = "<string>Hello World!</string>";
- NPVariant *np = ei.parseXML(xml);
- std::string data = NPVARIANT_TO_STRING(np[0]).UTF8Characters;
- if (NPVARIANT_IS_STRING(*np) &&
+ GnashNPVariant np = ei.parseXML(xml);
+ std::string data = NPStringToString(NPVARIANT_TO_STRING(np.get()));
+ if (NPVARIANT_IS_STRING(np.get()) &&
(data == "Hello World!")) {
runtest.pass("ExternalInterface::parseXML(string)");
} else {
@@ -165,8 +168,8 @@
xml = "<number>123.456</number>";
np = ei.parseXML(xml);
- double num = NPVARIANT_TO_DOUBLE(*np);
- if (NPVARIANT_IS_DOUBLE(*np) &&
+ double num = NPVARIANT_TO_DOUBLE(np.get());
+ if (NPVARIANT_IS_DOUBLE(np.get()) &&
(num == 123.456)) {
runtest.pass("ExternalInterface::parseXML(double)");
} else {
@@ -175,8 +178,8 @@
xml = "<number>78</number>";
np = ei.parseXML(xml);
- int inum = NPVARIANT_TO_INT32(*np);
- if (NPVARIANT_IS_INT32(*np) &&
+ int inum = NPVARIANT_TO_INT32(np.get());
+ if (NPVARIANT_IS_INT32(np.get()) &&
(inum == 78)) {
runtest.pass("ExternalInterface::parseXML(int32)");
} else {
@@ -185,8 +188,8 @@
xml = "<true/>";
np = ei.parseXML(xml);
- bool flag = NPVARIANT_TO_BOOLEAN(*np);
- if (NPVARIANT_IS_BOOLEAN(*np) &&
+ bool flag = NPVARIANT_TO_BOOLEAN(np.get());
+ if (NPVARIANT_IS_BOOLEAN(np.get()) &&
(flag == true)) {
runtest.pass("ExternalInterface::parseXML(true)");
} else {
@@ -195,8 +198,8 @@
xml = "<false/>";
np = ei.parseXML(xml);
- flag = NPVARIANT_TO_BOOLEAN(*np);
- if (NPVARIANT_IS_BOOLEAN(*np) &&
+ flag = NPVARIANT_TO_BOOLEAN(np.get());
+ if (NPVARIANT_IS_BOOLEAN(np.get()) &&
(flag == false)) {
runtest.pass("ExternalInterface::parseXML(false)");
} else {
@@ -205,7 +208,7 @@
xml = "<null/>";
np = ei.parseXML(xml);
- if (NPVARIANT_IS_NULL(*np)) {
+ if (NPVARIANT_IS_NULL(np.get())) {
runtest.pass("ExternalInterface::parseXML(null)");
} else {
runtest.fail("ExternalInterface::parseXML(null)");
@@ -213,16 +216,16 @@
xml = "<void/>";
np = ei.parseXML(xml);
- if (NPVARIANT_IS_VOID(*np)) {
+ if (NPVARIANT_IS_VOID(np.get())) {
runtest.pass("ExternalInterface::parseXML(void)");
} else {
runtest.fail("ExternalInterface::parseXML(void)");
}
xml = "<property id=\"0\"><string>foobar</string></property><property
id=\"1\"><number>12.34</number></property><property
id=\"2\"><number>56</number></property>";
- std::map<std::string, NPVariant *> props = ei.parseProperties(xml);
+ std::map<std::string, GnashNPVariant> props = ei.parseProperties(xml);
np = props["0"];
- data = NPVARIANT_TO_STRING(np[0]).UTF8Characters;
+ data = NPStringToString(NPVARIANT_TO_STRING(np.get()));
if ((props.size() == 3) && (data == "foobar")) {
runtest.pass("ExternalInterface::parseProperties()");
} else {
@@ -231,7 +234,7 @@
xml = "<object><property
id=\"test1\"><string>foobar</string></property><property
id=\"test2\"><number>12.34</number></property><property
id=\"test3\"><number>56</number></property></object>";
np = ei.parseXML(xml);
- if (NPVARIANT_IS_OBJECT(*np)) {
+ if (NPVARIANT_IS_OBJECT(np.get())) {
runtest.pass("ExternalInterface::parseXML(object)");
} else {
runtest.fail("ExternalInterface::parseXML(object)");
@@ -254,13 +257,13 @@
}
xml =
"<arguments><string>barfoo</string><number>135.78</number><number>89</number></arguments>";
- std::vector<NPVariant *> arguments = ei.parseArguments(xml);
+ std::vector<GnashNPVariant> arguments = ei.parseArguments(xml);
np = arguments[0];
- str = NPVARIANT_TO_STRING(np[0]).UTF8Characters;
- double dub = NPVARIANT_TO_DOUBLE(*arguments[1]);
- int val = NPVARIANT_TO_INT32(*arguments[2]);
+ str = NPStringToString(NPVARIANT_TO_STRING(np.get()));
+ double dub = NPVARIANT_TO_DOUBLE(arguments[1].get());
+ int val = NPVARIANT_TO_INT32(arguments[2].get());
if ((arguments.size() == 3) && (str == "barfoo")
- && (dub == 135.78) && (val = 89)) {
+ && (dub == 135.78) && (val == 89)) {
runtest.pass("ExternalInterface::parseArguments()");
} else {
runtest.fail("ExternalInterface::parseArguments()");
@@ -269,12 +272,12 @@
// Parse an invoke message
xml = "<invoke name=\"barbyfoo\"
returntype=\"xml\"><arguments><string>barfoo</string><number>135.78</number></arguments></invoke>";
ExternalInterface::invoke_t *invoke = ei.parseInvoke(xml);
- str = NPVARIANT_TO_STRING(*invoke->args[0]).UTF8Characters;
+ str = NPStringToString(NPVARIANT_TO_STRING(invoke->args[0].get()));
if ((invoke->name == "barbyfoo") && (invoke->type == "xml")
- && (NPVARIANT_IS_STRING(*invoke->args[0]))
+ && (NPVARIANT_IS_STRING(invoke->args[0].get()))
&& (str == "barfoo")
- && (NPVARIANT_IS_DOUBLE(*invoke->args[1]))
- && (NPVARIANT_TO_DOUBLE(*invoke->args[1]) == 135.78)
+ && (NPVARIANT_IS_DOUBLE(invoke->args[1].get()))
+ && (NPVARIANT_TO_DOUBLE(invoke->args[1].get()) == 135.78)
) {
runtest.pass("ExternalInterface::parseInvoke()");
} else {
@@ -293,6 +296,7 @@
void NPN_MemFree(void* ptr)
{
+ assert(ptr);
free(ptr);
}
@@ -356,6 +360,44 @@
}
}
+void
+NPN_ReleaseVariantValue(NPVariant *variant)
+{
+ switch(variant->type) {
+ case NPVariantType_String:
+ {
+
NPN_MemFree(const_cast<NPUTF8*>(NPVARIANT_TO_STRING(*variant).UTF8Characters));
+ break;
+ }
+ case NPVariantType_Object:
+ {
+ NPObject* obj = NPVARIANT_TO_OBJECT(*variant);
+ if (obj) {
+ NPN_ReleaseObject(obj);
+ }
+ break;
+ }
+ default:
+ {}
+ }
+
+ NULL_TO_NPVARIANT(*variant);
+}
+
+NPObject*
+NPN_RetainObject(NPObject *obj)
+{ assert(obj); ++obj->referenceCount; return obj; }
+
+
+void
+NPN_ReleaseObject(NPObject *npobj)
+{
+ assert(npobj);
+ --npobj->referenceCount;
+ if (npobj->referenceCount == 0) {
+ NPN_MemFree(npobj);
+ }
+}
// Local Variables:
// mode: C++
// indent-tabs-mode: nil
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r12171: A first attempt at an ownership model for NPVariants. Also simplify APIs,,
Bastiaan Jacques <=