[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11004: Migrated XMLNode to the new
From: |
Ben Limmer |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11004: Migrated XMLNode to the new filestructure and namespace |
Date: |
Fri, 05 Jun 2009 10:32:05 -0600 |
User-agent: |
Bazaar (1.13.1) |
------------------------------------------------------------
revno: 11004
committer: Ben Limmer <address@hidden>
branch nick: trunk
timestamp: Fri 2009-06-05 10:32:05 -0600
message:
Migrated XMLNode to the new filestructure and namespace
removed:
libcore/asobj/XMLNode_as.cpp
libcore/asobj/XMLNode_as.h
modified:
libcore/ClassHierarchy.cpp
libcore/asobj/Makefile.am
libcore/asobj/XML_as.cpp
libcore/asobj/XML_as.h
libcore/asobj/flash/xml/XMLNode_as.cpp
libcore/asobj/flash/xml/XMLNode_as.h
libcore/asobj/flash/xml/xml.am
testsuite/as3/classes.all/xml/XMLNode_as.hx
------------------------------------------------------------
revno: 10993.1.1
committer: Ben Limmer <address@hidden>
branch nick: branch_3
timestamp: Thu 2009-06-04 15:48:41 -0600
message:
Migrated XMLNode to the new filestructure. Passes all ming tests.
removed:
libcore/asobj/XMLNode_as.cpp
libcore/asobj/XMLNode_as.h
modified:
libcore/ClassHierarchy.cpp
libcore/asobj/Makefile.am
libcore/asobj/XML_as.cpp
libcore/asobj/XML_as.h
libcore/asobj/flash/xml/XMLNode_as.cpp
libcore/asobj/flash/xml/XMLNode_as.h
libcore/asobj/flash/xml/xml.am
testsuite/as3/classes.all/xml/XMLNode_as.hx
=== modified file 'libcore/ClassHierarchy.cpp'
--- a/libcore/ClassHierarchy.cpp 2009-05-27 17:45:42 +0000
+++ b/libcore/ClassHierarchy.cpp 2009-06-04 21:48:41 +0000
@@ -64,7 +64,7 @@
#include "builtin_function.h"
#include "XMLSocket_as.h"
#include "XML_as.h"
-#include "XMLNode_as.h"
+#include "xml/XMLNode_as.h"
#include "asClass.h"
#include "flash/text/TextFieldAutoSize_as.h"
=== modified file 'libcore/asobj/Makefile.am'
--- a/libcore/asobj/Makefile.am 2009-05-28 06:20:02 +0000
+++ b/libcore/asobj/Makefile.am 2009-06-04 21:48:41 +0000
@@ -84,7 +84,6 @@
MovieClipLoader.cpp\
String_as.cpp \
XML_as.cpp \
- XMLNode_as.cpp \
XMLSocket_as.cpp \
LoadableObject.cpp \
Object.cpp
@@ -121,7 +120,6 @@
String_as.h \
XML_as.h \
XMLSocket_as.h \
- XMLNode_as.h \
LoadableObject.h \
Namespace_as.h \
Object.h
=== removed file 'libcore/asobj/XMLNode_as.cpp'
--- a/libcore/asobj/XMLNode_as.cpp 2009-04-20 13:59:41 +0000
+++ b/libcore/asobj/XMLNode_as.cpp 1970-01-01 00:00:00 +0000
@@ -1,1001 +0,0 @@
-// XMLNode_as.cpp: ActionScript "XMLNode_as" class, for Gnash.
-//
-// Copyright (C) 2005, 2006, 2007, 2008, 2009 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
-
-#include "smart_ptr.h" // GNASH_USE_GC
-#include "log.h"
-#include "fn_call.h"
-#include "builtin_function.h"
-#include "Array_as.h" // for childNodes
-#include "XMLNode_as.h"
-#include "XML_as.h" // escape / unescape
-#include "log.h"
-#include "Object.h" // for getObjectInterface
-#include "VM.h" // for getting the string_table.
-#include "string_table.h"
-#include "PropertyList.h"
-
-#include <boost/bind.hpp>
-#include <string>
-#include <sstream>
-#include <vector>
-#include <algorithm>
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-
-namespace gnash {
-
-namespace {
- void enumerateAttributes(const XMLNode_as& node,
- PropertyList::SortedPropertyList&attributes);
- bool prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
- const std::string& prefix);
- bool namespaceMatches(
- const PropertyList::SortedPropertyList::value_type& val,
- const std::string& ns);
-
- as_value xmlnode_new(const fn_call& fn);
- as_value xmlnode_nodeName(const fn_call& fn);
- as_value xmlnode_nodeValue(const fn_call& fn);
- as_value xmlnode_nodeType(const fn_call& fn);
- as_value xmlnode_attributes(const fn_call& fn);
- as_value xmlnode_appendChild(const fn_call& fn);
- as_value xmlnode_cloneNode(const fn_call& fn);
- as_value xmlnode_hasChildNodes(const fn_call& fn);
- as_value xmlnode_insertBefore(const fn_call& fn);
- as_value xmlnode_removeNode(const fn_call& fn);
- as_value xmlnode_toString(const fn_call& fn);
- as_value xmlnode_firstChild(const fn_call& fn);
- as_value xmlnode_lastChild(const fn_call& fn);
- as_value xmlnode_nextSibling(const fn_call& fn);
- as_value xmlnode_previousSibling(const fn_call& fn);
- as_value xmlnode_childNodes(const fn_call& fn);
- as_value xmlnode_parentNode(const fn_call& fn);
- as_value xmlnode_getPrefixForNamespace(const fn_call& fn);
- as_value xmlnode_getNamespaceForPrefix(const fn_call& fn);
- as_value xmlnode_namespaceURI(const fn_call& fn);
- as_value xmlnode_localName(const fn_call& fn);
- as_value xmlnode_prefix(const fn_call& fn);
-
- void attachXMLNodeInterface(as_object& o);
-}
-
-
-XMLNode_as::XMLNode_as()
- :
- as_object(getXMLNodeInterface()),
- _parent(0),
- _attributes(new as_object),
- _type(Element)
-{
- //log_debug("%s: %p", __PRETTY_FUNCTION__, this);
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_debug(_("\tCreating XMLNode data at %p"), this);
-#endif
-}
-
-XMLNode_as::XMLNode_as(const XMLNode_as& tpl, bool deep)
- :
- as_object(getXMLNodeInterface()),
- _parent(0), // _parent is never implicitly copied
- _attributes(0),
- _name(tpl._name),
- _value(tpl._value),
- _type(tpl._type)
-{
- // only clone children if in deep mode
- if (deep) {
- const Children& from=tpl._children;
- for (Children::const_iterator it=from.begin(), itEnd=from.end();
- it != itEnd; ++it) {
-
- _children.push_back(new XMLNode_as(*(*it), deep));
- }
- }
-}
-
-XMLNode_as::~XMLNode_as()
-{
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_debug(_("\tDeleting XMLNode data %s with as_value %s at %p"),
- this->_name, this->as_value, this);
-#endif
-}
-
-bool
-XMLNode_as::hasChildNodes()
-{
- if (_children.size()) return true;
- return false;
-}
-
-boost::intrusive_ptr<XMLNode_as>
-XMLNode_as::firstChild()
-{
- if ( _children.empty() ) return NULL;
- return _children.front();
-}
-
-boost::intrusive_ptr<XMLNode_as>
-XMLNode_as::lastChild()
-{
- if (_children.empty()) {
- log_debug(_("XMLNode_as %p has no children"),
(void*)this);
- return 0;
- }
- return _children.back();
-}
-
-
-void
-XMLNode_as::appendChild(boost::intrusive_ptr<XMLNode_as> node)
-{
- assert (node);
-
- boost::intrusive_ptr<XMLNode_as> oldparent = node->getParent();
- node->setParent(this);
- _children.push_back(node);
- if ( oldparent ) {
- oldparent->_children.remove(node);
- }
-
-}
-
-boost::intrusive_ptr<XMLNode_as>
-XMLNode_as::cloneNode(bool deep)
-{
- boost::intrusive_ptr<XMLNode_as> newnode = new XMLNode_as(*this, deep);
- return newnode;
-}
-
-void
-XMLNode_as::insertBefore(boost::intrusive_ptr<XMLNode_as> newnode,
- boost::intrusive_ptr<XMLNode_as> pos)
-{
- // find iterator for positional parameter
- Children::iterator it = std::find(_children.begin(), _children.end(), pos);
- if (it == _children.end()) {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("XMLNode.insertBefore(): positional parameter "
- "is not a child of this node"));
- );
- return;
- }
-
- _children.insert(it, newnode);
- boost::intrusive_ptr<XMLNode_as> oldparent = newnode->getParent();
- newnode->setParent(this);
- if (oldparent) {
- oldparent->_children.remove(newnode);
- }
-}
-
-/// \brief removes the specified XML object from its parent. Also
-/// deletes all descendants of the node.
-void
-XMLNode_as::removeNode()
-{
- boost::intrusive_ptr<XMLNode_as> oldparent = getParent();
- if (oldparent) {
- oldparent->_children.remove(this);
- }
- _parent = 0;
-}
-
-XMLNode_as *
-XMLNode_as::previousSibling()
-{
- if (!_parent) return 0;
- if (_parent->_children.size() <= 1) return 0;
-
- XMLNode_as *previous_node = 0;
- for (Children::iterator itx = _parent->_children.begin();
- itx != _parent->_children.end(); itx++) {
-
- if (itx->get() == this) return previous_node;
-
- previous_node = itx->get();
- }
-
- return 0;
-}
-
-XMLNode_as *
-XMLNode_as::nextSibling()
-{
-
- if (!_parent) return 0;
-
- if (_parent->_children.size() <= 1) return 0;
-
- XMLNode_as *previous_node = 0;
- for (Children::reverse_iterator itx = _parent->_children.rbegin();
- itx != _parent->_children.rend(); ++itx) {
-
- if (itx->get() == this) return previous_node;
- previous_node = itx->get();
- }
-
- return 0;
-}
-
-void
-XMLNode_as::toString(std::ostream& xmlout, bool encode) const
-{
- stringify(*this, xmlout, encode);
-}
-
-void
-XMLNode_as::setAttribute(const std::string& name, const std::string& value)
-{
- if (_attributes) {
- string_table& st = _vm.getStringTable();
- _attributes->set_member(st.find(name), value);
- }
-}
-
-bool
-XMLNode_as::getPrefixForNamespace(const std::string& ns, std::string& prefix)
-{
- XMLNode_as* node = this;
- PropertyList::SortedPropertyList::const_iterator it;
- PropertyList::SortedPropertyList attrs;
-
- while (node) {
- enumerateAttributes(*node, attrs);
- if (!attrs.empty())
- {
- it = std::find_if(attrs.begin(), attrs.end(),
- boost::bind(namespaceMatches, _1, ns));
- if (it != attrs.end()) break;
- }
- node = node->getParent();
- }
-
- // None found.
- if (!node) return false;
-
- // Return the matching prefix
- const std::string& name = it->first;
-
- if (name.length() == 5) {
- return true;
- }
-
- assert (name.length() >= 6);
-
- if (name[5] != ':') return false;
-
- // Can also be empty.
- prefix = name.substr(6);
- return true;
-
-}
-
-void
-XMLNode_as::getNamespaceForPrefix(const std::string& prefix, std::string& ns)
-{
- XMLNode_as* node = this;
- PropertyList::SortedPropertyList::const_iterator it;
- PropertyList::SortedPropertyList attrs;
-
- while (node) {
-
- enumerateAttributes(*node, attrs);
-
- if (!attrs.empty()) {
-
- it = std::find_if(attrs.begin(), attrs.end(),
- boost::bind(prefixMatches, _1, prefix));
- if (it != attrs.end()) break;
- }
- node = node->getParent();
- }
-
- // None found; return undefined
- if (!node) return;
-
- // Return the matching namespace
- ns = it->second;
-
-}
-
-
-bool
-XMLNode_as::extractPrefix(std::string& prefix)
-{
- prefix.clear();
- if (_name.empty()) return false;
-
- std::string::size_type pos = _name.find(':');
- if (pos == std::string::npos || pos == _name.size() - 1) {
- return false;
- }
-
- prefix = _name.substr(0, pos);
- return true;
-}
-
-
-void
-XMLNode_as::stringify(const XMLNode_as& xml, std::ostream& xmlout, bool
encode)
-{
-
- const std::string& nodeValue = xml.nodeValue();
- const std::string& nodeName = xml.nodeName();
- NodeType type = xml.nodeType();
-
-#ifdef GNASH_DEBUG
- log_debug(_("Stringifying node %p with name %s, as_value %s, %u "
- "attributes and %u children"), (void*)&xml, nodeName,
- nodeValue, xml._attributes.size(), xml._children.size());
-#endif
-
- // Create the beginning of the tag
- if (!nodeName.empty()) {
-
- xmlout << "<" << nodeName;
-
- // Process the attributes, if any
- PropertyList::SortedPropertyList attrs;
- enumerateAttributes(xml, attrs);
- if (!attrs.empty()) {
-
- for (PropertyList::SortedPropertyList::iterator i =
- attrs.begin(), e = attrs.end(); i != e; ++i) {
- XML_as::escape(i->second);
- xmlout << " " << i->first << "=\"" << i->second << "\"";
- }
- }
-
- // If the node has no content, just close the tag now
- if ( nodeValue.empty() && xml._children.empty() ) {
- xmlout << " />";
- return;
- }
- else {
- // Will use a closing tag later
- xmlout << ">";
- }
-
- }
-
- // Node as_value first, then children
- if (type == Text)
- {
- as_object* global = xml.getVM().getGlobal();
- assert(global);
-
- // Insert entities.
- std::string escaped(nodeValue);
- XML_as::escape(escaped);
- const std::string& val = encode ?
- global->callMethod(NSV::PROP_ESCAPE, escaped).to_string() :
- escaped;
-
- xmlout << val;
- }
-
- // Childs, after node as_value.
- for (Children::const_iterator itx = xml._children.begin();
- itx != xml._children.end(); ++itx) {
-
- (*itx)->toString(xmlout, encode);
- }
-
- if (!nodeName.empty()) {
- xmlout << "</" << nodeName << ">";
- }
-}
-
-
-#ifdef GNASH_USE_GC
-void
-XMLNode_as::markReachableResources() const
-{
- // Mark children
- std::for_each(_children.begin(), _children.end(),
- boost::mem_fn(&as_object::setReachable));
-
- // Mark parent
- if (_parent) _parent->setReachable();
-
- // Mark attributes object
- if (_attributes) _attributes->setReachable();
-
- markAsObjectReachable();
-}
-#endif // GNASH_USE_GC
-
-void
-XMLNode_as::registerNative(as_object& global)
-{
- VM& vm = global.getVM();
- vm.registerNative(xmlnode_cloneNode, 253, 1);
- vm.registerNative(xmlnode_removeNode, 253, 2);
- vm.registerNative(xmlnode_insertBefore, 253, 3);
- vm.registerNative(xmlnode_appendChild, 253, 4);
- vm.registerNative(xmlnode_hasChildNodes, 253, 5);
- vm.registerNative(xmlnode_toString, 253, 6);
-}
-
-as_object*
-XMLNode_as::getXMLNodeInterface()
-{
- static boost::intrusive_ptr<as_object> o;
- if ( o == NULL ) {
- o = new as_object(getObjectInterface());
- attachXMLNodeInterface(*o);
- }
- return o.get();
-}
-
-
-void
-XMLNode_as::init(as_object& global)
-{
- // This is the global XMLNode_as "class"
- static boost::intrusive_ptr<builtin_function> cl;
-
- if ( cl == NULL )
- {
- cl=new builtin_function(&xmlnode_new, getXMLNodeInterface());
- }
-
- global.init_member("XMLNode", cl.get());
-
-}
-
-
-// XMLNode interface implementation
-
-namespace {
-
-void
-attachXMLNodeInterface(as_object& o)
-{
- // These need to be full-featured AS functions (builtin_function)
-
- VM& vm = o.getVM();
-
- const int noFlags = 0;
-
- // No prop flags:
- o.init_member("cloneNode", vm.getNative(253, 1), noFlags);
- o.init_member("removeNode", vm.getNative(253, 2), noFlags);
- o.init_member("insertBefore", vm.getNative(253, 3), noFlags);
- o.init_member("appendChild", vm.getNative(253, 4), noFlags);
- o.init_member("hasChildNodes", vm.getNative(253, 5), noFlags);
- o.init_member("toString", vm.getNative(253, 6), noFlags);
- o.init_member("getPrefixForNamespace", new builtin_function(
- xmlnode_getPrefixForNamespace), noFlags);
- o.init_member("getNamespaceForPrefix", new builtin_function(
- xmlnode_getNamespaceForPrefix), noFlags);
-
-
- const int protectedFlags = as_prop_flags::isProtected;
-
- // Just the protected flag:
- o.init_property("nodeValue", &xmlnode_nodeValue,
- &xmlnode_nodeValue, protectedFlags);
- o.init_property("nodeName", &xmlnode_nodeName,
- &xmlnode_nodeName, protectedFlags);
-
- o.init_readonly_property("firstChild", &xmlnode_firstChild,
protectedFlags);
- o.init_readonly_property("lastChild", &xmlnode_lastChild, protectedFlags);
- o.init_readonly_property("localName", &xmlnode_localName, protectedFlags);
- o.init_readonly_property("namespaceURI",
- &xmlnode_namespaceURI, protectedFlags);
- o.init_readonly_property("nextSibling",
- &xmlnode_nextSibling, protectedFlags);
- o.init_readonly_property("prefix", &xmlnode_prefix, protectedFlags);
- o.init_readonly_property("previousSibling",
- &xmlnode_previousSibling, protectedFlags);
- o.init_readonly_property("nodeType", &xmlnode_nodeType, protectedFlags);
- o.init_readonly_property("attributes", &xmlnode_attributes,
protectedFlags);
- o.init_readonly_property("childNodes", &xmlnode_childNodes,
protectedFlags);
- o.init_readonly_property("parentNode", &xmlnode_parentNode,
protectedFlags);
-
-}
-
-
-as_value
-xmlnode_new(const fn_call& fn)
-{
-
- XMLNode_as *xml_obj = new XMLNode_as;
- if ( fn.nargs > 0 )
- {
- xml_obj->nodeTypeSet(XMLNode_as::NodeType(fn.arg(0).to_int()));
- if (fn.nargs > 1)
- {
- xml_obj->nodeValueSet(fn.arg(1).to_string());
- }
- }
-
- return as_value(xml_obj);
-}
-
-
-as_value
-xmlnode_appendChild(const fn_call& fn)
-{
-// GNASH_REPORT_FUNCTION;
-
- boost::intrusive_ptr<XMLNode_as> ptr =
ensureType<XMLNode_as>(fn.this_ptr);
-
- if ( ! fn.nargs )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("XMLNode::appendChild() needs at least one
argument"));
- );
- return as_value();
- }
-
- boost::intrusive_ptr<XMLNode_as> xml_obj =
- boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object());
- if ( ! xml_obj )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("First argument to XMLNode::appendChild() is not "
- "an XMLNode"));
- );
- return as_value();
- }
-
- ptr->appendChild(xml_obj);
- return as_value(); // undefined
-
-}
-
-
-as_value
-xmlnode_cloneNode(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
- bool deep = false;
- if (fn.nargs > 0) deep = fn.arg(0).to_bool();
-
- boost::intrusive_ptr<XMLNode_as> newnode = ptr->cloneNode(deep);
- return as_value(newnode.get());
-}
-
-
-as_value
-xmlnode_insertBefore(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr =
ensureType<XMLNode_as>(fn.this_ptr);
-
- if ( fn.nargs < 2 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("XMLNode.insertBefore(%s) needs at least two "
- "arguments"), ss.str());
- );
- return as_value();
- }
-
- boost::intrusive_ptr<XMLNode_as> newnode =
- boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object());
-
- if (!newnode) {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("First argument to XMLNode.insertBefore(%s) is
not "
- "an XMLNode"), ss.str());
- );
- return as_value();
- }
-
- boost::intrusive_ptr<XMLNode_as> pos =
- boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(1).to_object());
-
- if (!pos) {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("Second argument to XMLNode.insertBefore(%s) is
not "
- "an XMLNode"), ss.str());
- );
- return as_value();
- }
-
- ptr->insertBefore(newnode, pos);
- return as_value();
-
-}
-
-
-as_value
-xmlnode_getNamespaceForPrefix(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- if (!fn.nargs) {
- return as_value();
- }
-
- std::string ns;
-
- ptr->getNamespaceForPrefix(fn.arg(0).to_string(), ns);
- if (ns.empty()) return as_value();
- return as_value(ns);
-}
-
-
-as_value
-xmlnode_getPrefixForNamespace(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- if (!fn.nargs) {
- return as_value();
- }
-
- std::string prefix;
-
- // Return undefined if none found; otherwise the prefix string found.
- // This can be empty if it is a standard namespace.
- if (!ptr->getPrefixForNamespace(fn.arg(0).to_string(), prefix)) {
- return as_value();
- }
- return as_value(prefix);
-}
-
-/// If the node has a prefix, return the matching namespace. Otherwise,
-/// returns a namespaceURI set with the xmlns attribute, searching upwards
-/// through parent nodes if necessary.
-//
-/// This standard namespace can only be set during XML parsing and cannot
-/// be changed or set using attributes.
-//
-/// Conversely, the similar getNamespaceForPrefix("") can be set and changed
-/// through attributes.
-as_value
-xmlnode_namespaceURI(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
- // Read-only property
-
- const std::string& name = ptr->nodeName();
-
- if (name.empty()) {
- as_value null;
- null.set_null();
- return null;
- }
-
- std::string prefix;
- if (ptr->extractPrefix(prefix)) {
- std::string ns;
- ptr->getNamespaceForPrefix(prefix, ns);
- return as_value(ns);
- }
-
- // Search recursively for a namespace. Return an empty string
- // if none found.
- XMLNode_as* node = ptr.get();
- while (node && node->getNamespaceURI().empty()) {
- node = node->getParent();
- }
- if (!node) return as_value("");
-
- return as_value(node->getNamespaceURI());
-}
-
-
-// Return the prefix part of the node name. If there is no colon, or one
-// colon at the end of the string, this is empty. Otherwise it is the part
-// up to the first colon.
-as_value
-xmlnode_prefix(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
- // Read-only property
-
- if (ptr->nodeName().empty()) {
- as_value null;
- null.set_null();
- return null;
- }
-
- std::string prefix;
- if (!ptr->extractPrefix(prefix)) return as_value("");
- return as_value(prefix);
-}
-
-
-// The local part of a node name. If there is no colon or a single colon
-// at the end of the string, this is the whole string. Otherwise all of the
-// string after the first colon.
-as_value
-xmlnode_localName(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
- // Read-only property
-
- if (ptr->nodeName().empty()) {
- as_value null;
- null.set_null();
- return null;
- }
-
- const std::string& nodeName = ptr->nodeName();
- if (nodeName.empty()) return as_value("");
-
- std::string::size_type pos = nodeName.find(':');
- if (pos == std::string::npos || pos == nodeName.size() - 1) {
- return as_value(nodeName);
- }
-
- return as_value(nodeName.substr(pos + 1));
-}
-
-
-as_value
-xmlnode_removeNode(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
- ptr->removeNode();
- return as_value();
-}
-
-
-// TODO: shouldn't overriding get_text_value() be fine ?
-as_value
-xmlnode_toString(const fn_call& fn)
-{
- //GNASH_REPORT_FUNCTION;
-
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
- std::stringstream ss;
- ptr->toString(ss);
-
- return as_value(ss.str());
-}
-
-
-as_value
-xmlnode_hasChildNodes(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- return as_value(ptr->hasChildNodes());
-}
-
-
-as_value
-xmlnode_nodeValue(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- as_value rv;
- rv.set_null();
-
- if ( fn.nargs == 0 )
- {
- const std::string& val = ptr->nodeValue();
- if ( ! val.empty() ) rv = val;
- }
- else
- {
- ptr->nodeValueSet(fn.arg(0).to_string());
- }
- return rv;
-}
-
-
-as_value
-xmlnode_nodeName(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- as_value rv;
- rv.set_null();
-
- if (!fn.nargs) {
- const std::string& val = ptr->nodeName();
- if ( ! val.empty() ) rv = val;
- }
- else
- {
- ptr->nodeNameSet(fn.arg(0).to_string());
- }
- return rv;
-}
-
-
-as_value
-xmlnode_nodeType(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- return as_value(ptr->nodeType());
-}
-
-
-as_value
-xmlnode_attributes(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
- as_object* attrs = ptr->getAttributes();
- if (attrs) return as_value(attrs);
- return as_value();
-}
-
-
-/// Read-only property; evaluates the specified XML object and
-/// references the first child in the parent node's child
-/// list. This property is null if the node does not have
-/// children. This property is undefined if the node is a text
-/// node. This is a read-only property and cannot be used to
-/// manipulate child nodes; use the appendChild(), insertBefore(),
-/// and removeNode() methods to manipulate child nodes.
-///
-as_value
-xmlnode_firstChild(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- as_value rv;
- rv.set_null();
-
- boost::intrusive_ptr<XMLNode_as> node = ptr->firstChild();
- if (node) {
- rv = node.get();
- }
-
- return rv;
-}
-
-
-/// Read-only property; an XMLNode as_value that references the last
-/// child in the node's child list. The XML.lastChild property
-/// is null if the node does not have children. This property cannot
-/// be used to manipulate child nodes; use the appendChild(),
-/// insertBefore(), and removeNode() methods to manipulate child
-/// nodes.
-as_value
-xmlnode_lastChild(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- as_value rv;
- rv.set_null();
-
- boost::intrusive_ptr<XMLNode_as> node = ptr->lastChild();
- if (node) rv = node.get();
-
- return rv;
-}
-
-
-as_value
-xmlnode_nextSibling(const fn_call& fn)
-{
- as_value rv;
- rv.set_null();
-
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- XMLNode_as *node = ptr->nextSibling();
- if (node) {
- rv = node;
- }
- return rv;
-}
-
-
-as_value
-xmlnode_previousSibling(const fn_call& fn)
-{
- as_value rv;
- rv.set_null();
-
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- XMLNode_as *node = ptr->previousSibling();
- if (node) {
- rv = node;
- }
- return rv;
-}
-
-
-as_value
-xmlnode_parentNode(const fn_call& fn)
-{
- as_value rv;
- rv.set_null();
-
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- XMLNode_as *node = ptr->getParent();
- if (node) {
- rv = node;
- }
- return rv;
-}
-
-
-as_value
-xmlnode_childNodes(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
- boost::intrusive_ptr<Array_as> ary = new Array_as();
-
- typedef XMLNode_as::Children Children;
-
- Children& child = ptr->childNodes();
- for ( Children::const_iterator it=child.begin(), itEnd=child.end();
- it != itEnd; ++it )
- {
- boost::intrusive_ptr<XMLNode_as> node = *it;
- ary->push(as_value(node.get()));
- }
-
- return as_value(ary.get());
-}
-
-
-void
-enumerateAttributes(const XMLNode_as& node,
- PropertyList::SortedPropertyList& attrs)
-{
- attrs.clear();
- const as_object* obj = node.getAttributes();
- if (obj) {
- obj->enumerateProperties(attrs);
- }
-
-}
-
-/// Return true if this attribute is a namespace specifier and the
-/// namespace matches.
-bool
-namespaceMatches(const PropertyList::SortedPropertyList::value_type& val,
- const std::string& ns)
-{
- StringNoCaseEqual noCaseCompare;
- return (noCaseCompare(val.first.substr(0, 5), "xmlns") &&
- noCaseCompare(val.second, ns));
-}
-
-
-bool
-prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
- const std::string& prefix)
-{
- const std::string& name = val.first;
- StringNoCaseEqual noCaseCompare;
-
- // An empty prefix searches for a standard namespace specifier.
- // Attributes are stored with no trailing or leading whitespace,
- // so a simple comparison should do. TODO: what about "xmlns:"?
- if (prefix.empty()) {
- return noCaseCompare(name, "xmlns") || noCaseCompare(name, "xmlns:");
- }
-
- if (!noCaseCompare(name.substr(0, 6), "xmlns:")) return false;
-
- return noCaseCompare(prefix, name.substr(6));
-}
-
-} // anonymous namespace
-
-} // end of gnash namespace
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
=== removed file 'libcore/asobj/XMLNode_as.h'
--- a/libcore/asobj/XMLNode_as.h 2009-03-31 09:26:54 +0000
+++ b/libcore/asobj/XMLNode_as.h 1970-01-01 00:00:00 +0000
@@ -1,254 +0,0 @@
-//
-// Copyright (C) 2005, 2006, 2007, 2008, 2009 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_ASOBJ_XML_NODE_H
-#define GNASH_ASOBJ_XML_NODE_H
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-
-#include "smart_ptr.h" // GNASH_USE_GC
-#include "action.h"
-#include "impl.h"
-#include "log.h"
-
-#include <list>
-#include <vector>
-#include <string>
-#include <sstream>
-
-namespace gnash {
-
-/// XMLNode ActionScript class
-//
-/// This is also the base class for the XML actionscript class (see
-/// XML_as.cpp, XML_as.h). Because XML_as also inherits from LoadableObject,
-/// this is a virtual base class.
-//
-/// Trivial copying and assignment are forbidden
-class XMLNode_as : public virtual as_object, boost::noncopyable
-{
-public:
-
- enum NodeType {
- Element = 1,
- Attribute = 2,
- Text = 3,
- Cdata = 4,
- EntityRef = 5,
- Entity = 6,
- ProcInstr = 7,
- Comment = 8,
- Document = 9,
- DocType = 10,
- DocFragment = 11,
- Notation = 12
- };
-
- XMLNode_as();
-
- virtual ~XMLNode_as();
-
- // Initialize the global XMLNode class
- static void init(as_object& global);
-
- // Used by XML_as
- static as_object* getXMLNodeInterface();
-
- /// Register ASnative methods
- static void registerNative(as_object& global);
-
- size_t length() const { return _children.size(); }
-
- const std::string& nodeName() const { return _name; }
-
- const std::string& nodeValue() const { return _value; }
-
- /// Get the type of an XML Node.
- NodeType nodeType() const { return _type; }
-
- /// Set the type of an XML Node.
- void nodeTypeSet(NodeType type) {
- _type = type;
- }
-
- /// Set name of this node, but only if it doesn't have a name yet
- //
- /// TODO: check if this is the correct behaviour
- ///
- void nodeNameSet(const std::string& name) { _name = name; }
-
- bool extractPrefix(std::string& prefix);
-
- /// Set value of this node, overriding any previous value
- void nodeValueSet(const std::string& value) { _value = value; }
-
- /// Performs a recursive search of node attributes to find a match
- void getNamespaceForPrefix(const std::string& prefix, std::string& ns);
-
- /// Performs a recursive search of node attributes to find a match
- //
- /// @return false if no match found.
- bool getPrefixForNamespace(const std::string& ns, std::string& prefix);
-
- void setNamespaceURI(const std::string value) {
- _namespaceURI = value;
- }
-
- const std::string& getNamespaceURI() const {
- return _namespaceURI;
- }
-
- /// Returns true if the specified node has child nodes; otherwise,
- /// returns false.
- bool hasChildNodes();
-
- boost::intrusive_ptr<XMLNode_as> firstChild();
- boost::intrusive_ptr<XMLNode_as> lastChild();
-
- // Use a list for quick erasing
- typedef std::list<boost::intrusive_ptr<XMLNode_as> > Children;
-
- Children& childNodes() { return _children; }
-
- XMLNode_as* previousSibling();
- XMLNode_as* nextSibling();
-
- /// Copy a node
- //
- /// Method; constructs and returns a new XML node of the same type,
- /// name, value, and attributes as the specified XML object. If deep
- /// is set to true, all child nodes are recursively cloned, resulting
- /// in an exact copy of the original object's document tree.
- boost::intrusive_ptr<XMLNode_as> cloneNode(bool deep);
-
- /// Append a child node the the XML object
- //
- /// Appends the specified node to the XML object's child
- /// list. This method operates directly on the node referenced by the
- /// childNode parameter; it does not append a copy of the node. If the
- /// node to be appended already exists in another tree structure,
- /// appending the node to the new location will remove it from its
- /// current location. If the childNode parameter refers to a node that
- /// already exists in another XML tree structure, the appended child
- /// node is placed in the new tree structure after it is removed from
- /// its existing parent node.
- ///
- /// @param childNode The XMLNode_as object to append as a child.
- void appendChild(boost::intrusive_ptr<XMLNode_as> childNode);
-
- /// Set the parent XMLNode_as of this node.
- //
- /// @param node The new parent of this node. May be 0.
- void setParent(XMLNode_as* node) { _parent = node; }
-
- /// Get the parent XMLNode_as of this node. Can be 0.
- XMLNode_as *getParent() const {
- return _parent.get();
- }
-
- /// Insert a node before a node
- //
- /// Method; inserts a new child node into the XML object's child
- /// list, before the beforeNode node. If the beforeNode parameter is
- /// undefined or null, the node is added using the appendChild()
- /// method. If beforeNode is not a child of my_xml, the insertion
- /// fails.
- ///
- /// @param newnoe
- /// The node to insert, moving from its current tree
- ///
- /// @param beforeWhich
- /// The node before which to insert the new one.
- /// Must be a child of this XMLNode or the operation will fail.
- ///
- void insertBefore(boost::intrusive_ptr<XMLNode_as> newnode,
- boost::intrusive_ptr<XMLNode_as> pos);
-
- /// Removes the specified XML object from its parent.
- //
- /// Also deletes all descendants of the node.
- void removeNode();
-
- /// Convert the XMLNode to a string
- //
- /// @param o The ostream to write the string to.
- /// @param encode Whether to URL encode the node values. This
- /// is false by default, as it is only necessary
- /// for XML.sendAndLoad.
- virtual void toString(std::ostream& str, bool encode = false) const;
-
- /// Return the attributes object associated with this node.
- as_object* getAttributes() { return _attributes; }
-
- /// Return a read-only version of this node's attributes object.
- const as_object* getAttributes() const { return _attributes; }
-
- /// Set a named attribute to a value.
- //
- /// @param name The name of the attribute to set. If already present,
- /// the value is changed. If not present, the attribute is
- /// added.
- /// @param value The value to set the named attribute to.
- void setAttribute(const std::string& name, const std::string& value);
-
-protected:
-
-#ifdef GNASH_USE_GC
- /// Mark XMLNode-specific reachable resources and invoke
- /// the parent's class version (markAsObjectReachable)
- //
- /// XMLNode-specific reachable resources are:
- /// - The child elements (_children)
- /// - The parent elements (_parent)
- ///
- virtual void markReachableResources() const;
-#endif // GNASH_USE_GC
-
- Children _children;
-
-private:
-
- /// A non-trivial copy-constructor for cloning nodes.
- XMLNode_as(const XMLNode_as &node, bool deep);
-
- boost::intrusive_ptr<XMLNode_as> _parent;
-
- as_object* _attributes;
-
- std::string _name;
-
- std::string _value;
-
- NodeType _type;
-
- std::string _namespaceURI;
-
- static void stringify(const XMLNode_as& xml, std::ostream& xmlout,
- bool encode);
-
-};
-
-} // gnash namespace
-
-
-#endif
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
=== modified file 'libcore/asobj/XML_as.cpp'
--- a/libcore/asobj/XML_as.cpp 2009-05-14 16:02:12 +0000
+++ b/libcore/asobj/XML_as.cpp 2009-06-04 21:48:41 +0000
@@ -28,7 +28,7 @@
#include "fn_call.h"
#include "LoadableObject.h"
-#include "XMLNode_as.h"
+#include "xml/XMLNode_as.h"
#include "XML_as.h"
#include "builtin_function.h"
#include "VM.h"
=== modified file 'libcore/asobj/XML_as.h'
--- a/libcore/asobj/XML_as.h 2009-01-22 20:10:39 +0000
+++ b/libcore/asobj/XML_as.h 2009-06-04 21:48:41 +0000
@@ -19,7 +19,7 @@
#define GNASH_ASOBJ_XML_H
#include "LoadableObject.h"
-#include "XMLNode_as.h"
+#include "xml/XMLNode_as.h"
#include "log.h"
#include "dsodefs.h"
#include "StringPredicates.h"
=== modified file 'libcore/asobj/flash/xml/XMLNode_as.cpp'
--- a/libcore/asobj/flash/xml/XMLNode_as.cpp 2009-05-28 17:11:03 +0000
+++ b/libcore/asobj/flash/xml/XMLNode_as.cpp 2009-06-04 21:48:41 +0000
@@ -22,154 +22,976 @@
#endif
#include "xml/XMLNode_as.h"
+//FIXME: direct this to the proper flash namespace
+#include "XML_as.h"
+#include "Array_as.h"
+#include "Object.h"
+#include "VM.h"
#include "log.h"
#include "fn_call.h"
#include "smart_ptr.h" // for boost intrusive_ptr
#include "builtin_function.h" // need builtin_function
#include "GnashException.h" // for ActionException
+#include "string_table.h"
+#include "PropertyList.h"
+
+#include <boost/bind.hpp>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
namespace gnash {
-// Forward declarations
+// Function Prototypes
namespace {
+ void enumerateAttributes(const XMLNode_as& node,
PropertyList::SortedPropertyList&attributes);
+ bool prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
+ const std::string& prefix);
+ bool namespaceMatches(
+ const PropertyList::SortedPropertyList::value_type& val,
+ const std::string& ns);
+ //FIXME: these should be changed to the proper return type & arguments
+ as_value xmlnode_new(const fn_call& fn);
+ as_value xmlnode_nodeName(const fn_call& fn);
+ as_value xmlnode_nodeValue(const fn_call& fn);
+ as_value xmlnode_nodeType(const fn_call& fn);
+ as_value xmlnode_attributes(const fn_call& fn);
+ as_value xmlnode_appendChild(const fn_call& fn);
as_value xmlnode_cloneNode(const fn_call& fn);
+ as_value xmlnode_lastChild(const fn_call& fn);
+ as_value xmlnode_firstChild(const fn_call& fn);
+ as_value xmlnode_nextSibling(const fn_call& fn);
+ as_value xmlnode_childNodes(const fn_call& fn);
+ as_value xmlnode_previousSibling(const fn_call& fn);
+ as_value xmlnode_parentNode(const fn_call& fn);
as_value xmlnode_getNamespaceForPrefix(const fn_call& fn);
as_value xmlnode_getPrefixForNamespace(const fn_call& fn);
+ as_value xmlnode_namespaceURI(const fn_call& fn);
as_value xmlnode_hasChildNodes(const fn_call& fn);
as_value xmlnode_insertBefore(const fn_call& fn);
as_value xmlnode_removeNode(const fn_call& fn);
as_value xmlnode_toString(const fn_call& fn);
+ as_value xmlnode_localName(const fn_call& fn);
+ as_value xmlnode_prefix(const fn_call& fn);
as_value xmlnode_ctor(const fn_call& fn);
void attachXMLNodeInterface(as_object& o);
void attachXMLNodeStaticInterface(as_object& o);
as_object* getXMLNodeInterface();
-
-}
-
-class XMLNode_as : public as_object
-{
-
-public:
-
- XMLNode_as()
- :
- as_object(getXMLNodeInterface())
- {}
-};
-
-// extern (used by Global.cpp)
-void xmlnode_class_init(as_object& global)
-{
- static boost::intrusive_ptr<builtin_function> cl;
-
- if (!cl) {
- cl = new builtin_function(&xmlnode_ctor, getXMLNodeInterface());
- attachXMLNodeStaticInterface(*cl);
- }
-
- // Register _global.XMLNode
- global.init_member("XMLNode", cl.get());
-}
-
-namespace {
-
-void
-attachXMLNodeInterface(as_object& o)
-{
- o.init_member("cloneNode", new builtin_function(xmlnode_cloneNode));
- o.init_member("getNamespaceForPrefix", new
builtin_function(xmlnode_getNamespaceForPrefix));
- o.init_member("getPrefixForNamespace", new
builtin_function(xmlnode_getPrefixForNamespace));
- o.init_member("hasChildNodes", new
builtin_function(xmlnode_hasChildNodes));
- o.init_member("insertBefore", new builtin_function(xmlnode_insertBefore));
- o.init_member("removeNode", new builtin_function(xmlnode_removeNode));
- o.init_member("toString", new builtin_function(xmlnode_toString));
-}
-
-void
-attachXMLNodeStaticInterface(as_object& o)
-{
-
+}
+
+//should be declared in header file
+//class XMLNode_as : public as_object
+//{
+//public:
+// XMLNode_as();
+// ~XMLNode_as();
+//};
+
+//ADDED//
+XMLNode_as::XMLNode_as()
+ : as_object(getXMLNodeInterface()),
+ _parent(0),
+ _attributes(new as_object),
+ _type(Element)
+{
+ //log_debug("%s: %p", __PRETTY_FUNCTION__, this);
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_debug(_("\tCreating XMLNode data at %p"), this);
+#endif
+}
+
+XMLNode_as::XMLNode_as(const XMLNode_as& tpl, bool deep)
+ :
+ as_object(getXMLNodeInterface()),
+ _parent(0), // _parent is never implicitly copied
+ _attributes(0),
+ _name(tpl._name),
+ _value(tpl._value),
+ _type(tpl._type)
+{
+ // only clone children if in deep mode
+ if (deep) {
+ const Children& from=tpl._children;
+ for (Children::const_iterator it=from.begin(), itEnd=from.end();
+ it != itEnd; ++it) {
+
+ _children.push_back(new XMLNode_as(*(*it), deep));
+ }
+ }
+}
+
+XMLNode_as::~XMLNode_as()
+{
+#ifdef DEBUG_MEMORY_ALLOCATION
+ log_debug(_("\tDeleting XMLNode data %s with as_value %s at %p"),
+ this->_name, this->as_value, this);
+#endif
+}
+
+bool
+XMLNode_as::hasChildNodes()
+{
+ if (_children.size()) return true;
+ return false;
+}
+
+boost::intrusive_ptr<XMLNode_as>
+XMLNode_as::firstChild()
+{
+ if ( _children.empty() ) return NULL;
+ return _children.front();
+}
+
+boost::intrusive_ptr<XMLNode_as>
+XMLNode_as::cloneNode(bool deep)
+{
+ boost::intrusive_ptr<XMLNode_as> newnode = new XMLNode_as(*this, deep);
+ return newnode;
+}
+
+boost::intrusive_ptr<XMLNode_as>
+XMLNode_as::lastChild()
+{
+ if (_children.empty()) {
+ log_debug(_("XMLNode_as %p has no children"),
(void*)this);
+ return 0;
+ }
+ return _children.back();
+}
+
+void
+XMLNode_as::appendChild(boost::intrusive_ptr<XMLNode_as> node)
+{
+ assert (node);
+
+ boost::intrusive_ptr<XMLNode_as> oldparent = node->getParent();
+ node->setParent(this);
+ _children.push_back(node);
+ if ( oldparent ) {
+ oldparent->_children.remove(node);
+ }
+
+}
+
+void
+XMLNode_as::insertBefore(boost::intrusive_ptr<XMLNode_as> newnode,
+ boost::intrusive_ptr<XMLNode_as> pos)
+{
+ // find iterator for positional parameter
+ Children::iterator it = std::find(_children.begin(), _children.end(), pos);
+ if (it == _children.end()) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("XMLNode.insertBefore(): positional parameter "
+ "is not a child of this node"));
+ );
+ return;
+ }
+
+ _children.insert(it, newnode);
+ boost::intrusive_ptr<XMLNode_as> oldparent = newnode->getParent();
+ newnode->setParent(this);
+ if (oldparent) {
+ oldparent->_children.remove(newnode);
+ }
+}
+
+// \brief removes the specified XML object from its parent. Also
+// deletes all descendants of the node.
+void
+XMLNode_as::removeNode()
+{
+ boost::intrusive_ptr<XMLNode_as> oldparent = getParent();
+ if (oldparent) {
+ oldparent->_children.remove(this);
+ }
+ _parent = 0;
+}
+
+XMLNode_as *
+XMLNode_as::previousSibling()
+{
+ if (!_parent) return 0;
+ if (_parent->_children.size() <= 1) return 0;
+
+ XMLNode_as *previous_node = 0;
+ for (Children::iterator itx = _parent->_children.begin();
+ itx != _parent->_children.end(); itx++) {
+
+ if (itx->get() == this) return previous_node;
+
+ previous_node = itx->get();
+ }
+
+ return 0;
+}
+
+XMLNode_as *
+XMLNode_as::nextSibling()
+{
+
+ if (!_parent) return 0;
+
+ if (_parent->_children.size() <= 1) return 0;
+
+ XMLNode_as *previous_node = 0;
+ for (Children::reverse_iterator itx = _parent->_children.rbegin();
+ itx != _parent->_children.rend(); ++itx) {
+
+ if (itx->get() == this) return previous_node;
+ previous_node = itx->get();
+ }
+
+ return 0;
+}
+
+void
+XMLNode_as::toString(std::ostream& xmlout, bool encode) const
+{
+ stringify(*this, xmlout, encode);
+}
+
+void
+XMLNode_as::setAttribute(const std::string& name, const std::string& value)
+{
+ if (_attributes) {
+ string_table& st = _vm.getStringTable();
+ _attributes->set_member(st.find(name), value);
+ }
+}
+
+bool
+XMLNode_as::getPrefixForNamespace(const std::string& ns, std::string& prefix)
+{
+ XMLNode_as* node = this;
+ PropertyList::SortedPropertyList::const_iterator it;
+ PropertyList::SortedPropertyList attrs;
+
+ while (node) {
+ enumerateAttributes(*node, attrs);
+ if (!attrs.empty())
+ {
+ it = std::find_if(attrs.begin(), attrs.end(),
+ boost::bind(namespaceMatches, _1, ns));
+ if (it != attrs.end()) break;
+ }
+ node = node->getParent();
+ }
+
+ // None found.
+ if (!node) return false;
+
+ // Return the matching prefix
+ const std::string& name = it->first;
+
+ if (name.length() == 5) {
+ return true;
+ }
+
+ assert (name.length() >= 6);
+
+ if (name[5] != ':') return false;
+
+ // Can also be empty.
+ prefix = name.substr(6);
+ return true;
+}
+
+void
+XMLNode_as::getNamespaceForPrefix(const std::string& prefix, std::string& ns)
+{
+ XMLNode_as* node = this;
+ PropertyList::SortedPropertyList::const_iterator it;
+ PropertyList::SortedPropertyList attrs;
+
+ while (node) {
+
+ enumerateAttributes(*node, attrs);
+
+ if (!attrs.empty()) {
+
+ it = std::find_if(attrs.begin(), attrs.end(),
+ boost::bind(prefixMatches, _1, prefix));
+ if (it != attrs.end()) break;
+ }
+ node = node->getParent();
+ }
+
+ // None found; return undefined
+ if (!node) return;
+
+ // Return the matching namespace
+ ns = it->second;
+
+}
+
+bool
+XMLNode_as::extractPrefix(std::string& prefix)
+{
+ prefix.clear();
+ if (_name.empty()) return false;
+
+ std::string::size_type pos = _name.find(':');
+ if (pos == std::string::npos || pos == _name.size() - 1) {
+ return false;
+ }
+
+ prefix = _name.substr(0, pos);
+ return true;
+}
+
+void
+XMLNode_as::stringify(const XMLNode_as& xml, std::ostream& xmlout, bool
encode)
+{
+
+ const std::string& nodeValue = xml.nodeValue();
+ const std::string& nodeName = xml.nodeName();
+ NodeType type = xml.nodeType();
+
+#ifdef GNASH_DEBUG
+ log_debug(_("Stringifying node %p with name %s, as_value %s, %u "
+ "attributes and %u children"), (void*)&xml, nodeName,
+ nodeValue, xml._attributes.size(), xml._children.size());
+#endif
+
+ // Create the beginning of the tag
+ if (!nodeName.empty()) {
+
+ xmlout << "<" << nodeName;
+
+ // Process the attributes, if any
+ PropertyList::SortedPropertyList attrs;
+ enumerateAttributes(xml, attrs);
+ if (!attrs.empty()) {
+
+ for (PropertyList::SortedPropertyList::iterator i =
+ attrs.begin(), e = attrs.end(); i != e; ++i) {
+ XML_as::escape(i->second);
+ xmlout << " " << i->first << "=\"" << i->second << "\"";
+ }
+ }
+
+ // If the node has no content, just close the tag now
+ if ( nodeValue.empty() && xml._children.empty() ) {
+ xmlout << " />";
+ return;
+ }
+ else {
+ // Will use a closing tag later
+ xmlout << ">";
+ }
+
+ }
+
+ // Node as_value first, then children
+ if (type == Text)
+ {
+ as_object* global = xml.getVM().getGlobal();
+ assert(global);
+
+ // Insert entities.
+ std::string escaped(nodeValue);
+ XML_as::escape(escaped);
+ const std::string& val = encode ?
+ global->callMethod(NSV::PROP_ESCAPE, escaped).to_string() :
+ escaped;
+
+ xmlout << val;
+ }
+
+ // Childs, after node as_value.
+ for (Children::const_iterator itx = xml._children.begin();
+ itx != xml._children.end(); ++itx) {
+
+ (*itx)->toString(xmlout, encode);
+ }
+
+ if (!nodeName.empty()) {
+ xmlout << "</" << nodeName << ">";
+ }
+}
+
+#ifdef GNASH_USE_GC
+void
+XMLNode_as::markReachableResources() const
+{
+ // Mark children
+ std::for_each(_children.begin(), _children.end(),
+ boost::mem_fn(&as_object::setReachable));
+
+ // Mark parent
+ if (_parent) _parent->setReachable();
+
+ // Mark attributes object
+ if (_attributes) _attributes->setReachable();
+
+ markAsObjectReachable();
+}
+#endif // GNASH_USE_GC
+
+void
+XMLNode_as::registerNative(as_object& global)
+{
+ VM& vm = global.getVM();
+ vm.registerNative(xmlnode_cloneNode, 253, 1);
+ vm.registerNative(xmlnode_removeNode, 253, 2);
+ vm.registerNative(xmlnode_insertBefore, 253, 3);
+ vm.registerNative(xmlnode_appendChild, 253, 4);
+ vm.registerNative(xmlnode_hasChildNodes, 253, 5);
+ vm.registerNative(xmlnode_toString, 253, 6);
}
as_object*
-getXMLNodeInterface()
+XMLNode_as::getXMLNodeInterface()
{
static boost::intrusive_ptr<as_object> o;
- if ( ! o ) {
- o = new as_object();
+ if ( o == NULL ) {
+ o = new as_object(getObjectInterface());
attachXMLNodeInterface(*o);
}
return o.get();
}
+void
+XMLNode_as::init(as_object& global)
+{
+ // This is the global XMLNode_as "class"
+ static boost::intrusive_ptr<builtin_function> cl;
+
+ if ( cl == NULL )
+ {
+ cl=new builtin_function(&xmlnode_new, getXMLNodeInterface());
+ }
+
+ global.init_member("XMLNode", cl.get());
+
+}
+
+namespace {
+
+void
+attachXMLNodeInterface(as_object& o)
+{
+ // These need to be full-featured AS functions (builtin_function)
+
+ VM& vm = o.getVM();
+
+ const int noFlags = 0;
+
+ // No prop flags:
+ o.init_member("cloneNode", vm.getNative(253, 1), noFlags);
+ o.init_member("removeNode", vm.getNative(253, 2), noFlags);
+ o.init_member("insertBefore", vm.getNative(253, 3), noFlags);
+ o.init_member("appendChild", vm.getNative(253, 4), noFlags);
+ o.init_member("hasChildNodes", vm.getNative(253, 5), noFlags);
+ o.init_member("toString", vm.getNative(253, 6), noFlags);
+ o.init_member("getPrefixForNamespace", new builtin_function(
+ xmlnode_getPrefixForNamespace), noFlags);
+ o.init_member("getNamespaceForPrefix", new builtin_function(
+ xmlnode_getNamespaceForPrefix), noFlags);
+
+
+ const int protectedFlags = as_prop_flags::isProtected;
+
+ // Just the protected flag:
+ o.init_property("nodeValue", &xmlnode_nodeValue,
+ &xmlnode_nodeValue, protectedFlags);
+ o.init_property("nodeName", &xmlnode_nodeName,
+ &xmlnode_nodeName, protectedFlags);
+
+ o.init_readonly_property("firstChild", &xmlnode_firstChild,
protectedFlags);
+ o.init_readonly_property("lastChild", &xmlnode_lastChild, protectedFlags);
+ o.init_readonly_property("localName", &xmlnode_localName, protectedFlags);
+ o.init_readonly_property("namespaceURI",
+ &xmlnode_namespaceURI, protectedFlags);
+ o.init_readonly_property("nextSibling",
+ &xmlnode_nextSibling, protectedFlags);
+ o.init_readonly_property("prefix", &xmlnode_prefix, protectedFlags);
+ o.init_readonly_property("previousSibling",
+ &xmlnode_previousSibling, protectedFlags);
+ o.init_readonly_property("nodeType", &xmlnode_nodeType, protectedFlags);
+ o.init_readonly_property("attributes", &xmlnode_attributes,
protectedFlags);
+ o.init_readonly_property("childNodes", &xmlnode_childNodes,
protectedFlags);
+ o.init_readonly_property("parentNode", &xmlnode_parentNode,
protectedFlags);
+
+}
+
+
+as_value
+xmlnode_new(const fn_call& fn)
+{
+
+ XMLNode_as *xml_obj = new XMLNode_as;
+ if ( fn.nargs > 0 )
+ {
+ xml_obj->nodeTypeSet(XMLNode_as::NodeType(fn.arg(0).to_int()));
+ if (fn.nargs > 1)
+ {
+ xml_obj->nodeValueSet(fn.arg(1).to_string());
+ }
+ }
+
+ return as_value(xml_obj);
+}
+
+
+as_value
+xmlnode_appendChild(const fn_call& fn)
+{
+// GNASH_REPORT_FUNCTION;
+
+ boost::intrusive_ptr<XMLNode_as> ptr =
ensureType<XMLNode_as>(fn.this_ptr);
+
+ if ( ! fn.nargs )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("XMLNode::appendChild() needs at least one
argument"));
+ );
+ return as_value();
+ }
+
+ boost::intrusive_ptr<XMLNode_as> xml_obj =
+ boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object());
+ if ( ! xml_obj )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("First argument to XMLNode::appendChild() is not "
+ "an XMLNode"));
+ );
+ return as_value();
+ }
+
+ ptr->appendChild(xml_obj);
+ return as_value(); // undefined
+
+}
+
as_value
xmlnode_cloneNode(const fn_call& fn)
{
- boost::intrusive_ptr<XMLNode_as> ptr =
- ensureType<XMLNode_as>(fn.this_ptr);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+ bool deep = false;
+ if (fn.nargs > 0) deep = fn.arg(0).to_bool();
+
+ boost::intrusive_ptr<XMLNode_as> newnode = ptr->cloneNode(deep);
+ return as_value(newnode.get());
+}
+
+
+as_value
+xmlnode_insertBefore(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr =
ensureType<XMLNode_as>(fn.this_ptr);
+
+ if ( fn.nargs < 2 )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror(_("XMLNode.insertBefore(%s) needs at least two "
+ "arguments"), ss.str());
+ );
+ return as_value();
+ }
+
+ boost::intrusive_ptr<XMLNode_as> newnode =
+ boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object());
+
+ if (!newnode) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror(_("First argument to XMLNode.insertBefore(%s) is
not "
+ "an XMLNode"), ss.str());
+ );
+ return as_value();
+ }
+
+ boost::intrusive_ptr<XMLNode_as> pos =
+ boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(1).to_object());
+
+ if (!pos) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror(_("Second argument to XMLNode.insertBefore(%s) is
not "
+ "an XMLNode"), ss.str());
+ );
+ return as_value();
+ }
+
+ ptr->insertBefore(newnode, pos);
return as_value();
+
}
+
as_value
xmlnode_getNamespaceForPrefix(const fn_call& fn)
{
- boost::intrusive_ptr<XMLNode_as> ptr =
- ensureType<XMLNode_as>(fn.this_ptr);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ if (!fn.nargs) {
+ return as_value();
+ }
+
+ std::string ns;
+
+ ptr->getNamespaceForPrefix(fn.arg(0).to_string(), ns);
+ if (ns.empty()) return as_value();
+ return as_value(ns);
}
+
as_value
xmlnode_getPrefixForNamespace(const fn_call& fn)
{
- boost::intrusive_ptr<XMLNode_as> ptr =
- ensureType<XMLNode_as>(fn.this_ptr);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-xmlnode_hasChildNodes(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr =
- ensureType<XMLNode_as>(fn.this_ptr);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-xmlnode_insertBefore(const fn_call& fn)
-{
- boost::intrusive_ptr<XMLNode_as> ptr =
- ensureType<XMLNode_as>(fn.this_ptr);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ if (!fn.nargs) {
+ return as_value();
+ }
+
+ std::string prefix;
+
+ // Return undefined if none found; otherwise the prefix string found.
+ // This can be empty if it is a standard namespace.
+ if (!ptr->getPrefixForNamespace(fn.arg(0).to_string(), prefix)) {
+ return as_value();
+ }
+ return as_value(prefix);
+}
+
+/// If the node has a prefix, return the matching namespace. Otherwise,
+/// returns a namespaceURI set with the xmlns attribute, searching upwards
+/// through parent nodes if necessary.
+//
+/// This standard namespace can only be set during XML parsing and cannot
+/// be changed or set using attributes.
+//
+/// Conversely, the similar getNamespaceForPrefix("") can be set and changed
+/// through attributes.
+as_value
+xmlnode_namespaceURI(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+ // Read-only property
+
+ const std::string& name = ptr->nodeName();
+
+ if (name.empty()) {
+ as_value null;
+ null.set_null();
+ return null;
+ }
+
+ std::string prefix;
+ if (ptr->extractPrefix(prefix)) {
+ std::string ns;
+ ptr->getNamespaceForPrefix(prefix, ns);
+ return as_value(ns);
+ }
+
+ // Search recursively for a namespace. Return an empty string
+ // if none found.
+ XMLNode_as* node = ptr.get();
+ while (node && node->getNamespaceURI().empty()) {
+ node = node->getParent();
+ }
+ if (!node) return as_value("");
+
+ return as_value(node->getNamespaceURI());
+}
+
+
+// Return the prefix part of the node name. If there is no colon, or one
+// colon at the end of the string, this is empty. Otherwise it is the part
+// up to the first colon.
+as_value
+xmlnode_prefix(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+ // Read-only property
+
+ if (ptr->nodeName().empty()) {
+ as_value null;
+ null.set_null();
+ return null;
+ }
+
+ std::string prefix;
+ if (!ptr->extractPrefix(prefix)) return as_value("");
+ return as_value(prefix);
+}
+
+
+// The local part of a node name. If there is no colon or a single colon
+// at the end of the string, this is the whole string. Otherwise all of the
+// string after the first colon.
+as_value
+xmlnode_localName(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+ // Read-only property
+
+ if (ptr->nodeName().empty()) {
+ as_value null;
+ null.set_null();
+ return null;
+ }
+
+ const std::string& nodeName = ptr->nodeName();
+ if (nodeName.empty()) return as_value("");
+
+ std::string::size_type pos = nodeName.find(':');
+ if (pos == std::string::npos || pos == nodeName.size() - 1) {
+ return as_value(nodeName);
+ }
+
+ return as_value(nodeName.substr(pos + 1));
+}
+
as_value
xmlnode_removeNode(const fn_call& fn)
{
- boost::intrusive_ptr<XMLNode_as> ptr =
- ensureType<XMLNode_as>(fn.this_ptr);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+ ptr->removeNode();
return as_value();
}
+
+// TODO: shouldn't overriding get_text_value() be fine ?
as_value
xmlnode_toString(const fn_call& fn)
{
- boost::intrusive_ptr<XMLNode_as> ptr =
- ensureType<XMLNode_as>(fn.this_ptr);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
+ //GNASH_REPORT_FUNCTION;
+
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+ std::stringstream ss;
+ ptr->toString(ss);
+
+ return as_value(ss.str());
+}
+
+
+as_value
+xmlnode_hasChildNodes(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ return as_value(ptr->hasChildNodes());
+}
+
+
+as_value
+xmlnode_nodeValue(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ as_value rv;
+ rv.set_null();
+
+ if ( fn.nargs == 0 )
+ {
+ const std::string& val = ptr->nodeValue();
+ if ( ! val.empty() ) rv = val;
+ }
+ else
+ {
+ ptr->nodeValueSet(fn.arg(0).to_string());
+ }
+ return rv;
+}
+
+
+as_value
+xmlnode_nodeName(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ as_value rv;
+ rv.set_null();
+
+ if (!fn.nargs) {
+ const std::string& val = ptr->nodeName();
+ if ( ! val.empty() ) rv = val;
+ }
+ else
+ {
+ ptr->nodeNameSet(fn.arg(0).to_string());
+ }
+ return rv;
+}
+
+
+as_value
+xmlnode_nodeType(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ return as_value(ptr->nodeType());
+}
+
+
+as_value
+xmlnode_attributes(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+ as_object* attrs = ptr->getAttributes();
+ if (attrs) return as_value(attrs);
+ return as_value();
+}
+
+
+/// Read-only property; evaluates the specified XML object and
+/// references the first child in the parent node's child
+/// list. This property is null if the node does not have
+/// children. This property is undefined if the node is a text
+/// node. This is a read-only property and cannot be used to
+/// manipulate child nodes; use the appendChild(), insertBefore(),
+/// and removeNode() methods to manipulate child nodes.
+///
+as_value
+xmlnode_firstChild(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ as_value rv;
+ rv.set_null();
+
+ boost::intrusive_ptr<XMLNode_as> node = ptr->firstChild();
+ if (node) {
+ rv = node.get();
+ }
+
+ return rv;
+}
+
+
+/// Read-only property; an XMLNode as_value that references the last
+/// child in the node's child list. The XML.lastChild property
+/// is null if the node does not have children. This property cannot
+/// be used to manipulate child nodes; use the appendChild(),
+/// insertBefore(), and removeNode() methods to manipulate child
+/// nodes.
+as_value
+xmlnode_lastChild(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ as_value rv;
+ rv.set_null();
+
+ boost::intrusive_ptr<XMLNode_as> node = ptr->lastChild();
+ if (node) rv = node.get();
+
+ return rv;
+}
+
+
+as_value
+xmlnode_nextSibling(const fn_call& fn)
+{
+ as_value rv;
+ rv.set_null();
+
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ XMLNode_as *node = ptr->nextSibling();
+ if (node) {
+ rv = node;
+ }
+ return rv;
+}
+
+
+as_value
+xmlnode_previousSibling(const fn_call& fn)
+{
+ as_value rv;
+ rv.set_null();
+
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ XMLNode_as *node = ptr->previousSibling();
+ if (node) {
+ rv = node;
+ }
+ return rv;
+}
+
+
+as_value
+xmlnode_parentNode(const fn_call& fn)
+{
+ as_value rv;
+ rv.set_null();
+
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ XMLNode_as *node = ptr->getParent();
+ if (node) {
+ rv = node;
+ }
+ return rv;
+}
+
+
+as_value
+xmlnode_childNodes(const fn_call& fn)
+{
+ boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+ boost::intrusive_ptr<Array_as> ary = new Array_as();
+
+ typedef XMLNode_as::Children Children;
+
+ Children& child = ptr->childNodes();
+ for ( Children::const_iterator it=child.begin(), itEnd=child.end();
+ it != itEnd; ++it )
+ {
+ boost::intrusive_ptr<XMLNode_as> node = *it;
+ ary->push(as_value(node.get()));
+ }
+
+ return as_value(ary.get());
+}
+
+
+void
+enumerateAttributes(const XMLNode_as& node,
+ PropertyList::SortedPropertyList& attrs)
+{
+ attrs.clear();
+ const as_object* obj = node.getAttributes();
+ if (obj) {
+ obj->enumerateProperties(attrs);
+ }
+
+}
+
+/// Return true if this attribute is a namespace specifier and the
+/// namespace matches.
+bool
+namespaceMatches(const PropertyList::SortedPropertyList::value_type& val,
+ const std::string& ns)
+{
+ StringNoCaseEqual noCaseCompare;
+ return (noCaseCompare(val.first.substr(0, 5), "xmlns") &&
+ noCaseCompare(val.second, ns));
+}
+
+
+bool
+prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
+ const std::string& prefix)
+{
+ const std::string& name = val.first;
+ StringNoCaseEqual noCaseCompare;
+
+ // An empty prefix searches for a standard namespace specifier.
+ // Attributes are stored with no trailing or leading whitespace,
+ // so a simple comparison should do. TODO: what about "xmlns:"?
+ if (prefix.empty()) {
+ return noCaseCompare(name, "xmlns") || noCaseCompare(name, "xmlns:");
+ }
+
+ if (!noCaseCompare(name.substr(0, 6), "xmlns:")) return false;
+
+ return noCaseCompare(prefix, name.substr(6));
}
as_value
@@ -179,10 +1001,10 @@
return as_value(obj.get()); // will keep alive
}
-
+
+////END ADD
} // anonymous namespace
} // gnash namespace
-
// local Variables:
// mode: C++
// indent-tabs-mode: t
=== modified file 'libcore/asobj/flash/xml/XMLNode_as.h'
--- a/libcore/asobj/flash/xml/XMLNode_as.h 2009-05-28 17:29:17 +0000
+++ b/libcore/asobj/flash/xml/XMLNode_as.h 2009-06-04 21:48:41 +0000
@@ -24,14 +24,220 @@
#include "gnashconfig.h"
#endif
+#include "smart_ptr.h" // GNASH_USE_GC
+#include "action.h"
+#include "impl.h"
+#include "log.h"
+
+#include <list>
+#include <vector>
+#include <string>
+#include <sstream>
namespace gnash {
-
-// Forward declarations
-class as_object;
-
-/// Initialize the global XMLNode class
-void xmlnode_class_init(as_object& global);
+class XMLNode_as : public virtual as_object, boost::noncopyable
+{
+public:
+
+ enum NodeType {
+ Element = 1,
+ Attribute = 2,
+ Text = 3,
+ Cdata = 4,
+ EntityRef = 5,
+ Entity = 6,
+ ProcInstr = 7,
+ Comment = 8,
+ Document = 9,
+ DocType = 10,
+ DocFragment = 11,
+ Notation = 12
+ };
+
+ XMLNode_as();
+
+ virtual ~XMLNode_as();
+
+ // Initialize the global XMLNode class
+ static void init(as_object& global);
+
+ // Used by XML_as
+ static as_object* getXMLNodeInterface();
+
+ /// Register ASnative methods
+ static void registerNative(as_object& global);
+
+ size_t length() const { return _children.size(); }
+
+ const std::string& nodeName() const { return _name; }
+
+ const std::string& nodeValue() const { return _value; }
+
+ /// Get the type of an XML Node.
+ NodeType nodeType() const { return _type; }
+
+ /// Set the type of an XML Node.
+ void nodeTypeSet(NodeType type) {
+ _type = type;
+ }
+
+ /// Set name of this node, but only if it doesn't have a name yet
+ //
+ /// TODO: check if this is the correct behaviour
+ ///
+ void nodeNameSet(const std::string& name) { _name = name; }
+
+ bool extractPrefix(std::string& prefix);
+
+ /// Set value of this node, overriding any previous value
+ void nodeValueSet(const std::string& value) { _value = value; }
+
+ /// Performs a recursive search of node attributes to find a match
+ void getNamespaceForPrefix(const std::string& prefix, std::string& ns);
+
+ /// Performs a recursive search of node attributes to find a match
+ //
+ /// @return false if no match found.
+ bool getPrefixForNamespace(const std::string& ns, std::string& prefix);
+
+ void setNamespaceURI(const std::string value) {
+ _namespaceURI = value;
+ }
+
+ const std::string& getNamespaceURI() const {
+ return _namespaceURI;
+ }
+
+ /// Returns true if the specified node has child nodes; otherwise,
+ /// returns false.
+ bool hasChildNodes();
+
+ boost::intrusive_ptr<XMLNode_as> firstChild();
+ boost::intrusive_ptr<XMLNode_as> lastChild();
+
+ // Use a list for quick erasing
+ typedef std::list<boost::intrusive_ptr<XMLNode_as> > Children;
+
+ Children& childNodes() { return _children; }
+
+ XMLNode_as* previousSibling();
+ XMLNode_as* nextSibling();
+
+ /// Copy a node
+ // UNIMPLEMENTED
+ /// Method; constructs and returns a new XML node of the same type,
+ /// name, value, and attributes as the specified XML object. If deep
+ /// is set to true, all child nodes are recursively cloned, resulting
+ /// in an exact copy of the original object's document tree.
+ boost::intrusive_ptr<XMLNode_as> cloneNode(bool deep);
+
+ /// Append a child node the the XML object
+ //
+ /// Appends the specified node to the XML object's child
+ /// list. This method operates directly on the node referenced by the
+ /// childNode parameter; it does not append a copy of the node. If the
+ /// node to be appended already exists in another tree structure,
+ /// appending the node to the new location will remove it from its
+ /// current location. If the childNode parameter refers to a node that
+ /// already exists in another XML tree structure, the appended child
+ /// node is placed in the new tree structure after it is removed from
+ /// its existing parent node.
+ ///
+ /// @param childNode The XMLNode_as object to append as a child.
+
+ void appendChild(boost::intrusive_ptr<XMLNode_as> childNode);
+
+ /// Set the parent XMLNode_as of this node.
+ //
+ /// @param node The new parent of this node. May be 0.
+ void setParent(XMLNode_as* node) { _parent = node; }
+
+ /// Get the parent XMLNode_as of this node. Can be 0.
+ XMLNode_as *getParent() const {
+ return _parent.get();
+ }
+
+ /// Insert a node before a node
+ //
+ /// Method; inserts a new child node into the XML object's child
+ /// list, before the beforeNode node. If the beforeNode parameter is
+ /// undefined or null, the node is added using the appendChild()
+ /// method. If beforeNode is not a child of my_xml, the insertion
+ /// fails.
+ ///
+ /// @param newnoe
+ /// The node to insert, moving from its current tree
+ ///
+ /// @param beforeWhich
+ /// The node before which to insert the new one.
+ /// Must be a child of this XMLNode or the operation will fail.
+ ///
+ void insertBefore(boost::intrusive_ptr<XMLNode_as> newnode,
+ boost::intrusive_ptr<XMLNode_as> pos);
+
+ /// Removes the specified XML object from its parent.
+ //
+ /// Also deletes all descendants of the node.
+ void removeNode();
+
+ /// Convert the XMLNode to a string
+ //
+ /// @param o The ostream to write the string to.
+ /// @param encode Whether to URL encode the node values. This
+ /// is false by default, as it is only necessary
+ /// for XML.sendAndLoad.
+ virtual void toString(std::ostream& str, bool encode = false) const;
+
+ /// Return the attributes object associated with this node.
+ as_object* getAttributes() { return _attributes; }
+
+ /// Return a read-only version of this node's attributes object.
+ const as_object* getAttributes() const { return _attributes; }
+
+ /// Set a named attribute to a value.
+ //
+ /// @param name The name of the attribute to set. If already present,
+ /// the value is changed. If not present, the attribute is
+ /// added.
+ /// @param value The value to set the named attribute to.
+ void setAttribute(const std::string& name, const std::string& value);
+
+protected:
+
+#ifdef GNASH_USE_GC
+ /// Mark XMLNode-specific reachable resources and invoke
+ /// the parent's class version (markAsObjectReachable)
+ //
+ /// XMLNode-specific reachable resources are:
+ /// - The child elements (_children)
+ /// - The parent elements (_parent)
+ ///
+ virtual void markReachableResources() const;
+#endif // GNASH_USE_GC
+
+ Children _children;
+
+private:
+
+ /// A non-trivial copy-constructor for cloning nodes.
+ XMLNode_as(const XMLNode_as &node, bool deep);
+
+ boost::intrusive_ptr<XMLNode_as> _parent;
+
+ as_object* _attributes;
+
+ std::string _name;
+
+ std::string _value;
+
+ NodeType _type;
+
+ std::string _namespaceURI;
+
+ static void stringify(const XMLNode_as& xml, std::ostream& xmlout,
+ bool encode);
+
+};
} // gnash namespace
@@ -43,3 +249,4 @@
// indent-tabs-mode: t
// End:
+
=== modified file 'libcore/asobj/flash/xml/xml.am'
--- a/libcore/asobj/flash/xml/xml.am 2009-06-01 19:12:38 +0000
+++ b/libcore/asobj/flash/xml/xml.am 2009-06-05 16:32:05 +0000
@@ -31,7 +31,7 @@
endif
if BUILD_XMLNODE_AS3
-# XML_SOURCES += flash/xml/XMLNode_as.cpp
+XML_SOURCES += flash/xml/XMLNode_as.cpp
XML_HEADERS += flash/xml/XMLNode_as.h
endif
@@ -50,12 +50,17 @@
echo "#define GNASH_ASOBJ_FLASH_XML_H 1" >> $${header}; \
echo "#include \"sharedlib.h\"" >> $${header}; \
echo "static gnash::SharedLib::initentry *as3xmlclasses[] = {" >>
$${header}; \
- sources="`echo $(XML_SOURCES) | cut -d ' ' -f 2-`"; \
- for i in $${sources}; do \
- item=`basename $$i | sed -e 's:\_as.cpp::'`; \
+ oldway=`grep -l "_class_init" $(srcdir)/flash/xml/*_as.h`; \
+ newway=`grep -l "void init" $(srcdir)/flash/xml/*_as.h`; \
+ for i in $${oldway}; do \
+ item=`basename $$i | sed -e 's:\_as.h::'`; \
lowname="`echo $${item} | tr '[A-Z]' '[a-z]'`"; \
echo " gnash::$${lowname}_class_init," >> $${header}; \
done; \
+ for i in $${newway}; do \
+ item=`basename $$i | sed -e 's:\_as.h::'`; \
+ echo " gnash::$${item}_as::init," >> $${header}; \
+ done; \
echo ' 0' >> $${header}; \
echo '};' >> $${header}; \
echo "#endif // end of GNASH_ASOBJ_FLASH_XML_H" >> $${header};
=== modified file 'testsuite/as3/classes.all/xml/XMLNode_as.hx'
--- a/testsuite/as3/classes.all/xml/XMLNode_as.hx 2009-06-03 19:42:00
+0000
+++ b/testsuite/as3/classes.all/xml/XMLNode_as.hx 2009-06-04 21:48:41
+0000
@@ -28,6 +28,7 @@
import flash.xml.XMLNodeType;
import flash.display.MovieClip;
#else
+import flash.XMLNode;
import flash.MovieClip;
#end
import flash.Lib;
@@ -40,7 +41,7 @@
// Class must be named with the _as suffix, as that's the same name as the
file.
class XMLNode_as {
static function main() {
- #if flash9
+ #if flash
var x1:XMLNode = new XMLNode(XMLNodeType.ELEMENT_NODE, null);
// Make sure we actually get a valid class
- [Gnash-commit] /srv/bzr/gnash/trunk r11004: Migrated XMLNode to the new filestructure and namespace,
Ben Limmer <=