gnash-commit
[Top][All Lists]
Advanced

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]