📄 gameswf_xml.cpp
字号:
// gameswf_xml.h -- Rob Savoye <rob@welcomehome.org> 2005// This source code has been donated to the Public Domain. Do// whatever you want with it.#include <sys/types.h>#include <sys/stat.h>#include "gameswf_log.h"#include "gameswf_action.h"#include "gameswf_impl.h"#include "gameswf_log.h"#include "base/smart_ptr.h"#include "gameswf_string.h"#include "base/tu_config.h"#ifdef HAVE_LIBXML#include <unistd.h>#include "gameswf_xml.h"#include <libxml/xmlmemory.h>#include <libxml/parser.h>#include <libxml/xmlreader.h>namespace gameswf{ //#define DEBUG_MEMORY_ALLOCATION 1 array<as_object *> _xmlobjs; // FIXME: hack alertXMLAttr::XMLAttr(){#ifdef DEBUG_MEMORY_ALLOCATION log_msg("\t\tCreating XMLAttr data at %p \n", this);#endif _name = 0; _value = 0;}XMLAttr::~XMLAttr(){#ifdef DEBUG_MEMORY_ALLOCATION log_msg("\t\tDeleting XMLAttr data %s at %p \n", this->_name, this);#endif //log_msg("%s: %p \n", __FUNCTION__, this); if (_name) { delete _name; } if (_value) { delete _value; } } XMLNode::XMLNode(){ //log_msg("%s: %p \n", __FUNCTION__, this);#ifdef DEBUG_MEMORY_ALLOCATION log_msg("\tCreating XMLNode data at %p \n", this);#endif _name = 0; _value = 0;}XMLNode::~XMLNode(){ int i; //log_msg("%s: %p \n", __FUNCTION__, this);#ifdef DEBUG_MEMORY_ALLOCATION log_msg("\tDeleting XMLNode data %s at %p\n", this->_name, this);#endif for (i=0; i<_children.size(); i++) {// if (_children[i]->_name) {// delete _children[i]->_name;// }// if (_children[i]->_value) {// delete _children[i]->_value;// } delete _children[i]; } for (i=0; i<_attributes.size(); i++) { // if (_attributes[i]->_name) {// delete _attributes[i]->_name;// }// if (_attributes[i]->_value) {// delete _attributes[i]->_value;// } delete _attributes[i]; } _children.clear(); _attributes.clear(); if (_name) { delete _name; } if (_value) { delete _value; } // _value.set_undefined();}XML::XML(){#ifdef DEBUG_MEMORY_ALLOCATION log_msg("Creating XML data at %p \n", this);#endif //log_msg("%s: %p \n", __FUNCTION__, this); _loaded = false; _nodename = 0;}// Parse the ASCII XML string into memoryXML::XML(tu_string xml_in){#ifdef DEBUG_MEMORY_ALLOCATION log_msg("Creating XML data at %p \n", this);#endif //log_msg("%s: %p \n", __FUNCTION__, this); //memset(&_nodes, 0, sizeof(XMLNode)); parseXML(xml_in);}XML::XML(struct node *childNode){#ifdef DEBUG_MEMORY_ALLOCATION log_msg("\tCreating XML data at %p \n", this);#endif //log_msg("%s: %p \n", __FUNCTION__, this);}XML::~XML(){#ifdef DEBUG_MEMORY_ALLOCATION if (this->_nodes) { log_msg("\tDeleting XML top level node %s at %p \n", this->_nodes->_name, this); } else { log_msg("\tDeleting XML top level node at %p \n", this); }#endif //log_msg("%s: %p \n", __FUNCTION__, this); delete _nodes;}// Dispatch event handler(s), if any.boolXML::on_event(event_id id){ // Keep m_as_environment alive during any method calls! // smart_ptr<as_object_interface> this_ptr(this); #if 0 // First, check for built-in event handler. as_value method; if (get_event_handler(event_id(id), &method)) {/ // Dispatch. call_method0(method, &m_as_environment, this); return true; } // Check for member function. // In ActionScript 2.0, event method names are CASE SENSITIVE. // In ActionScript 1.0, event method names are CASE INSENSITIVE. const tu_string& method_name = id.get_function_name(); if (method_name.length() > 0)hostByNameGet { as_value method; if (get_member(method_name, &method)) { call_method0(method, &m_as_environment, this); return true; } }#endif return false;}voidXML::on_event_load(){ // Do the events that (appear to) happen as the movie // loads. frame1 tags and actions are executed (even // before advance() is called). Then the onLoad event // is triggered. { on_event(event_id::LOAD); }}XMLNode*XML::extractNode(xmlNodePtr node, bool mem){ xmlAttrPtr attr; xmlNodePtr childnode; xmlChar *ptr = NULL; XMLNode *element, *child; int len; element = new XMLNode; //log_msg("Created new element for %s at %p\n", node->name, element); memset(element, 0, sizeof (XMLNode)); //log_msg("%s: extracting node %s\n", __FUNCTION__, node->name); // See if we have any Attributes (properties) attr = node->properties; while (attr != NULL) { //log_msg("extractNode %s has property %s, value is %s\n", // node->name, attr->name, attr->children->content); XMLAttr *attrib = new XMLAttr; len = memadjust(strlen(reinterpret_cast<const char *>(attr->name))+1); attrib->_name = (char *)new char[len]; memset(attrib->_name, 0, len); strcpy(attrib->_name, reinterpret_cast<const char *>(attr->name)); len = memadjust(strlen(reinterpret_cast<const char *>(attr->children->content))+1); attrib->_value = (char *)new char[len]; memset(attrib->_value, 0, len); strcpy(attrib->_value, reinterpret_cast<const char *>(attr->children->content)); //log_msg("\tPushing attribute %s for element %s has value %s\n", // attr->name, node->name, attr->children->content); element->_attributes.push_back(attrib); attr = attr->next; } len = memadjust(strlen(reinterpret_cast<const char *>(node->name))+1); element->_name = (char *)new char[len]; memset(element->_name, 0, len); strcpy(element->_name, reinterpret_cast<const char *>(node->name)); //element->_name = reinterpret_cast<const char *>(node->name); if (node->children) { //ptr = node->children->content; ptr = xmlNodeGetContent(node->children); if (ptr != NULL) { if ((strchr((const char *)ptr, '\n') == 0) && (ptr[0] != 0)) { if (node->children->content == NULL) { //log_msg("Node %s has no contents\n", node->name); } else { //log_msg("extractChildNode from text for %s has contents %s\n", node->name, ptr); len = memadjust(strlen(reinterpret_cast<const char *>(ptr))+1); element->_value = (char *)new char[len]; memset(element->_value, 0, len); strcpy(element->_value, reinterpret_cast<const char *>(ptr)); //element->_value = reinterpret_cast<const char *>(ptr); } } xmlFree(ptr); } } // See if we have any data (content) childnode = node->children; while (childnode != NULL) { if (childnode->type == XML_ELEMENT_NODE) { //log_msg("\t\t extracting node %s\n", childnode->name); child = extractNode(childnode, mem); //if (child->_value.get_type() != as_value::UNDEFINED) { if (child->_value != 0) { //log_msg("\tPushing childNode %s, value %s on element %p\n", child->_name.c_str(), child->_value.to_string(), element); } else { //log_msg("\tPushing childNode %s on element %p\n", child->_name.c_str(), element); } element->_children.push_back(child); } childnode = childnode->next; } return element;}// Read in an XML document from the specified sourceboolXML::parseDoc(xmlDocPtr document, bool mem){ XMLNode *top; xmlNodePtr cur; if (document == 0) { log_error("Can't load XML file!\n"); return false; } cur = xmlDocGetRootElement(document); if (cur != NULL) { top = extractNode(cur, mem); //_nodes->_name = reinterpret_cast<const char *>(cur->name); _nodes = top; //_node_data.push_back(top); //cur = cur->next; } _loaded = true; return true;}// This reads in an XML file from disk and parses into into a memory resident// tree which can be walked through later.boolXML::parseXML(tu_string xml_in){ bool ret = true; //log_msg("Parse XML from memory: %s\n", xml_in.c_str()); if (xml_in.size() == 0) { log_error("XML data is empty!\n"); return false; }#ifndef USE_DMALLOC //dump_memory_stats(__FUNCTION__, __LINE__, "before xmlParseMemory");#endif#ifdef USE_XMLREADER XMLNode *node = 0; xmlTextReaderPtr reader; reader = xmlReaderForMemory(xml_in.c_str(), xml_in.size(), NULL, NULL, 0); if (reader != NULL) { ret = true; while (ret) { ret = xmlTextReaderRead(reader); node = processNode(reader, node); } xmlFreeTextReader(reader); if (ret != false) { log_error("%s : couldn't parse\n", xml_in.c_str()); return false; } } else { log_error("Unable to open %s\n", xml_in.c_str()); return false; } xmlCleanupParser(); return true;#else#ifdef USE_DOM xmlInitParser(); _doc = xmlParseMemory(xml_in.c_str(), xml_in.size()); if (_doc == 0) { log_error("Can't parse XML data!\n"); return false; } ret = parseDoc(_doc, true); xmlCleanupParser(); xmlFreeDoc(_doc); xmlMemoryDump();#endif#ifndef USE_DMALLOC //dump_memory_stats(__FUNCTION__, __LINE__, "after xmlParseMemory");#endif return ret;#endif }// XML_READER_TYPE_NONE = 0// XML_READER_TYPE_ELEMENT = 1,// XML_READER_TYPE_ATTRIBUTE = 2,// XML_READER_TYPE_TEXT = 3,// XML_READER_TYPE_COMMENT = 8,// XML_READER_TYPE_SIGNIFICANT_WHITESPACE = 14,// XML_READER_TYPE_END_ELEMENT = 15,//// processNode:// 2 1 IP 0// processNode:// 3 3 #text 0 192.168.2.50// processNode:// 2 15 IP 0// processNode:// 2 14 #text 0const char *tabs[] = { "", "\t", "\t\t", "\t\t\t", "\t\t\t", "\t\t\t\t",};#ifdef USE_XMLREADER// This is an xmlReader (SAX) based parser. For some reason it core dumps// when compiled with GCC 3.x, but works just fine with GCC 4.x.XMLNode*XML::processNode(xmlTextReaderPtr reader, XMLNode *node){ //log_msg("%s: node is %p\n", __FUNCTION__, node); static XMLNode *parent[10]; xmlChar *name, *value; int depth; XMLNode *element; //static int previous_depth = 0; xmlReaderTypes type; if (node == 0) { memset(parent, 0, sizeof(XMLNode *)); } type = (xmlReaderTypes)xmlTextReaderNodeType(reader); depth = xmlTextReaderDepth(reader); value = xmlTextReaderValue(reader); name = xmlTextReaderName(reader); if (name == NULL) name = xmlStrdup(BAD_CAST "--");#if 0 printf("%d %d %s %d\n", depth, (int)type, name, xmlTextReaderIsEmptyElement(reader)); #endif //child = node->_children[0]; switch(xmlTextReaderNodeType(reader)) { case XML_READER_TYPE_NONE: break; case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: // This is an empty text node //log_msg("\tWhitespace at depth %d\n", depth); break; case XML_READER_TYPE_END_ELEMENT: if (depth == 0) { // This is the last node in the file element = node; break; } parent[depth]->_children.push_back(element);// log_msg("Pushing element %s on node %s\n", node->_name, parent[depth]->_name);// log_msg("End element at depth %d is %s for parent %s %p\n", depth, name,// parent[depth]->_name, parent[depth]); element = parent[depth]; break; case XML_READER_TYPE_ELEMENT: element = new XMLNode;// log_msg("%sElement at depth %d is %s for node at %p\n", tabs[depth], depth, name, element); element->_name = (char *)new char[strlen(reinterpret_cast<const char *>(name))+1]; memset(element->_name, 0, strlen(reinterpret_cast<const char *>(name))+1); strcpy(element->_name, reinterpret_cast<const char *>(name)); if (node == 0) { _nodes = element; parent[0] = element;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -