1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-14 11:47:15 +01:00
SqMod/modules/xml/Node.hpp

614 lines
21 KiB
C++
Raw Normal View History

#ifndef _SQXML_NODE_HPP_
#define _SQXML_NODE_HPP_
// ------------------------------------------------------------------------------------------------
#include "Handle/Document.hpp"
#include "Wrapper/ParseResult.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* A light-weight handle for manipulating nodes in DOM tree.
*/
class Node
{
// --------------------------------------------------------------------------------------------
friend class Document;
friend class Text;
protected:
// --------------------------------------------------------------------------------------------
typedef xml_node Type;
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
Node(const DocumentRef doc, const Type & node)
: m_Doc(doc), m_Node(node)
{
/* ... */
}
private:
// ---------------------------------------------------------------------------------------------
DocumentRef m_Doc; // The main xml document instance.
Type m_Node; // The managed document node.
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Node()
: m_Doc(), m_Node()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
Node(const Node & o)
: m_Doc(o.m_Doc), m_Node(o.m_Node)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~Node()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Node & operator = (const Node & o)
{
m_Doc = o.m_Doc;
m_Node = o.m_Node;
return *this;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Node & o)
{
if (m_Node == o.m_Node)
{
return 0;
}
else if (m_Node > o.m_Node)
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return m_Node.value();
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* See whether this instance references a valid xml document.
*/
bool IsValid() const
{
return m_Doc;
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this document instance.
*/
Uint32 GetRefCount() const
{
return m_Doc.Count();
}
/* --------------------------------------------------------------------------------------------
* See whether the node is empty.
*/
bool IsEmpty() const
{
return m_Node.empty();
}
/* --------------------------------------------------------------------------------------------
* Get hash value (unique for handles to the same object).
*/
SQInteger GetHashValue() const
{
return static_cast< SQInteger >(m_Node.hash_value());
}
/* --------------------------------------------------------------------------------------------
* Get node offset in parsed file/string (in char_t units) for debugging purposes.
*/
SQInteger GetOffsetDebug() const
{
return static_cast< SQInteger >(m_Node.offset_debug());
}
/* --------------------------------------------------------------------------------------------
* Retrieve node type.
*/
Int32 GetType() const
{
return static_cast< Int32 >(m_Node.type());
}
/* --------------------------------------------------------------------------------------------
* Retrieve node name.
*/
CSStr GetName() const
{
return m_Node.name();
}
/* --------------------------------------------------------------------------------------------
* Retrieve node name.
*/
void SetName(CSStr name)
{
if (!m_Node.set_name(name))
{
STHROWF("Unable to set XML node name");
}
}
/* --------------------------------------------------------------------------------------------
* Modify the node name.
*/
bool ApplyName(CSStr name)
{
return m_Node.set_name(name);
}
/* --------------------------------------------------------------------------------------------
* Retrieve node value.
*/
CSStr GetValue() const
{
return m_Node.value();
}
/* --------------------------------------------------------------------------------------------
* Retrieve node value.
*/
void SetValue(CSStr name)
{
if (!m_Node.set_value(name))
{
STHROWF("Unable to set XML node value");
}
}
/* --------------------------------------------------------------------------------------------
* Modify the node value.
*/
bool ApplyValue(CSStr value)
{
return m_Node.set_value(value);
}
/* --------------------------------------------------------------------------------------------
* Parses buffer as an XML document fragment and appends all nodes as children of this node.
*/
ParseResult AppendBuffer(CSStr source)
{
// Is the specified source buffer even valid?
if (source)
{
return ParseResult(m_Doc, m_Node.append_buffer(source,
std::char_traits< SQChar >::length(source) * sizeof(SQChar)));
}
// Return the default result
return ParseResult();
}
/* --------------------------------------------------------------------------------------------
* Parses buffer as an XML document fragment and appends all nodes as children of this node.
*/
ParseResult AppendBuffer(CSStr source, Uint32 options)
{
// Is the specified source buffer even valid?
if (source)
{
return ParseResult(m_Doc, m_Node.append_buffer(source,
std::char_traits< SQChar >::length(source) * sizeof(SQChar), options));
}
// Return the default result
return ParseResult();
}
/* --------------------------------------------------------------------------------------------
* Parses buffer as an XML document fragment and appends all nodes as children of this node.
*/
ParseResult AppendBuffer(CSStr source, Uint32 options, Int32 encoding)
{
// Is the specified source buffer even valid?
if (source)
{
return ParseResult(m_Doc, m_Node.append_buffer(source,
std::char_traits< SQChar >::length(source) * sizeof(SQChar),
options, (xml_encoding)encoding));
}
// Return the default result
return ParseResult();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the first child attribute.
*/
Attribute GetFirstAttr() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the last child attribute.
*/
Attribute GetLastAttr() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the first child node.
*/
Node GetFirstChild() const
{
return Node(m_Doc, m_Node.first_child());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the last child node.
*/
Node GetLastChild() const
{
return Node(m_Doc, m_Node.last_child());
}
/* --------------------------------------------------------------------------------------------
* Get next sibling in the children list of the parent node.
*/
Node GetNextSibling() const
{
return Node(m_Doc, m_Node.next_sibling());
}
/* --------------------------------------------------------------------------------------------
* Get previous sibling in the children list of the parent node
*/
Node GetPrevSibling() const
{
return Node(m_Doc, m_Node.previous_sibling());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the parent node.
*/
Node GetParent() const
{
return Node(m_Doc, m_Node.parent());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the root node.
*/
Node GetRoot() const
{
return Node(m_Doc, m_Node.root());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the text object for the current node.
*/
Text GetText() const;
/* --------------------------------------------------------------------------------------------
* Retrieve child node with the specified name.
*/
Node Child(CSStr name) const
{
return Node(m_Doc, m_Node.child(name));
}
/* --------------------------------------------------------------------------------------------
* Retrieve child attribute with the specified name.
*/
Attribute GetAttribute(CSStr name) const;
/* --------------------------------------------------------------------------------------------
* Retrieve next sibling with the specified name.
*/
Node NextSibling(CSStr name) const
{
return Node(m_Doc, m_Node.next_sibling(name));
}
/* --------------------------------------------------------------------------------------------
* Retrieve previous sibling with the specified name.
*/
Node PrevSibling(CSStr name) const
{
return Node(m_Doc, m_Node.previous_sibling(name));
}
/* --------------------------------------------------------------------------------------------
* Retrieve child attribute, starting the search from a hint.
*/
Attribute AttributeFrom(CSStr name, Attribute & attr) const;
/* --------------------------------------------------------------------------------------------
* Get child value of current node; that is, value of the first child node of type PCDATA/CDATA.
*/
CSStr GetChildValue() const
{
return m_Node.child_value();
}
/* --------------------------------------------------------------------------------------------
* Retrieve child value of child with specified name.
*/
CSStr ChildValue(CSStr name) const
{
return m_Node.child_value(name);
}
/* --------------------------------------------------------------------------------------------
* Append a child attribute with the specified name.
*/
Attribute AppendAttr(CSStr name);
/* --------------------------------------------------------------------------------------------
* Prepend a child attribute with the specified name.
*/
Attribute PrependAttr(CSStr name);
/* --------------------------------------------------------------------------------------------
* Insert a child attribute with the specified name, after the specified node.
*/
Attribute InsertAttrAfter(CSStr name, const Attribute & attr);
/* --------------------------------------------------------------------------------------------
* Insert a child attribute with the specified name, before the specified node.
*/
Attribute InsertAttrBefore(CSStr name, const Attribute & attr);
/* --------------------------------------------------------------------------------------------
* Append a copy of the specified attribute as a child.
*/
Attribute AppendAttrCopy(const Attribute & proto);
/* --------------------------------------------------------------------------------------------
* Prepend a copy of the specified attribute as a child.
*/
Attribute PrependAttrCopy(const Attribute & proto);
/* --------------------------------------------------------------------------------------------
* Insert a copy of the specified attribute as a child after the specified attribute.
*/
Attribute InsertAttrCopyAfter(const Attribute & proto, const Attribute & attr);
/* --------------------------------------------------------------------------------------------
* Insert a copy of the specified attribute as a child before the specified attribute.
*/
Attribute InsertAttrCopyBefore(const Attribute & proto, const Attribute & attr);
/* --------------------------------------------------------------------------------------------
* Append a basic child node with the specified name.
*/
Node AppendChild(CSStr name)
{
return Node(m_Doc, m_Node.append_child(name));
}
/* --------------------------------------------------------------------------------------------
* Prepend a basic child node with the specified name.
*/
Node PrependChild(CSStr name)
{
return Node(m_Doc, m_Node.prepend_child(name));
}
/* --------------------------------------------------------------------------------------------
* Append a basic child node.
*/
Node AppendChildNode()
{
return Node(m_Doc, m_Node.append_child());
}
/* --------------------------------------------------------------------------------------------
* Prepend a basic child node.
*/
Node PrependChildNode()
{
return Node(m_Doc, m_Node.prepend_child());
}
/* --------------------------------------------------------------------------------------------
* Append a basic child node with the specified type.
*/
Node AppendChildType(Int32 type)
{
return Node(m_Doc, m_Node.append_child(static_cast< xml_node_type >(type)));
}
/* --------------------------------------------------------------------------------------------
* Prepend a basic child node with the specified type.
*/
Node PrependChildType(Int32 type)
{
return Node(m_Doc, m_Node.prepend_child(static_cast< xml_node_type >(type)));
}
/* --------------------------------------------------------------------------------------------
* Insert a basic child node with the specified name, after the specified node.
*/
Node InsertChildAfter(CSStr name, const Node & node)
{
return Node(m_Doc, m_Node.insert_child_after(name, node.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Insert a basic child node with the specified name, before the specified node.
*/
Node InsertChildBefore(CSStr name, const Node & node)
{
return Node(m_Doc, m_Node.insert_child_before(name, node.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Insert a basic child node with the specified type, after the specified node.
*/
Node InsertChildTypeAfter(Int32 type, const Node & node)
{
return Node(m_Doc, m_Node.insert_child_after(static_cast< xml_node_type >(type),
node.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Insert a basic child node with the specified type, before the specified node.
*/
Node InsertChildTypeBefore(Int32 type, const Node & node)
{
return Node(m_Doc, m_Node.insert_child_before(static_cast< xml_node_type >(type),
node.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Append a copy of the specified node as a child.
*/
Node AppendCopy(const Node & proto)
{
return Node(m_Doc, m_Node.append_copy(proto.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Prepend a copy of the specified node as a child.
*/
Node PrependCopy(const Node & proto)
{
return Node(m_Doc, m_Node.prepend_copy(proto.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Insert a copy of the specified node as a child after the specified node.
*/
Node InsertCopyAfter(const Node & proto, const Node & node)
{
return Node(m_Doc, m_Node.insert_copy_after(proto.m_Node, node.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Insert a copy of the specified node as a child before the specified node.
*/
Node InsertCopyBefore(const Node & proto, const Node & node)
{
return Node(m_Doc, m_Node.insert_copy_before(proto.m_Node, node.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Append the specified node as a child and take ownership of it.
*/
Node AppendMove(const Node & proto)
{
return Node(m_Doc, m_Node.append_copy(proto.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Prepend the specified node as a child and take ownership of it.
*/
Node PrependMove(const Node & proto)
{
return Node(m_Doc, m_Node.prepend_copy(proto.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Insert the specified node as a child after the specified node and take ownership of it.
*/
Node InsertMoveAfter(const Node & proto, const Node & node)
{
return Node(m_Doc, m_Node.insert_copy_after(proto.m_Node, node.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Insert the specified node as a child before the specified node and take ownership of it.
*/
Node InsertMoveBefore(const Node & proto, const Node & node)
{
return Node(m_Doc, m_Node.insert_copy_before(proto.m_Node, node.m_Node));
}
/* --------------------------------------------------------------------------------------------
* Remove the child attribute matching the specified name.
*/
bool RemoveAttr(CSStr name)
{
return m_Node.remove_attribute(name);
}
/* --------------------------------------------------------------------------------------------
* Remove the specified attribute.
*/
bool RemoveAttrInst(const Attribute & attr);
/* --------------------------------------------------------------------------------------------
* Remove the child node matching the specified name.
*/
bool RemoveChild(CSStr name)
{
return m_Node.remove_child(name);
}
/* --------------------------------------------------------------------------------------------
* Remove the specified node.
*/
bool RemoveChildInst(const Node & node)
{
return m_Node.remove_child(node.m_Node);
}
/* --------------------------------------------------------------------------------------------
* Find child node by attribute name/value.
*/
Node FindChildByAttr(CSStr attr_name, CSStr attr_value) const
{
return Node(m_Doc, m_Node.find_child_by_attribute(attr_name, attr_value));
}
/* --------------------------------------------------------------------------------------------
* Find child node by attribute name/value.
*/
Node FindChildByAttr(CSStr name, CSStr attr_name, CSStr attr_value) const
{
return Node(m_Doc, m_Node.find_child_by_attribute(name, attr_name, attr_value));
}
/* --------------------------------------------------------------------------------------------
* Search for a node by path consisting of node names and . or .. elements.
*/
Node FindElemByPath(CSStr path, SQChar delimiter) const
{
return Node(m_Doc, m_Node.first_element_by_path(path, delimiter));
}
};
} // Namespace:: SqMod
#endif // _SQXML_NODE_HPP_