diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/Lua/lib/pugilua.dll b/Lua/lib/pugilua.dll index 9825aea..a6c982e 100644 Binary files a/Lua/lib/pugilua.dll and b/Lua/lib/pugilua.dll differ diff --git a/Lua/lib/pugilua.lib b/Lua/lib/pugilua.lib index f75705c..38324fb 100644 Binary files a/Lua/lib/pugilua.lib and b/Lua/lib/pugilua.lib differ diff --git a/Lua/lib/test.lua b/Lua/lib/test.lua index 699b064..b412417 100644 --- a/Lua/lib/test.lua +++ b/Lua/lib/test.lua @@ -1,12 +1,37 @@ assert(require 'pugilua') +print(pugi.version) + local doc=pugi.xml_document() os.execute("cd") local res=doc:load_file [[..\..\scripts\pugilua\pugilua.vcxproj]] print(res.description) assert(res.valid) -local node=doc:child('Project') +local node=doc:root():child('Project') assert(node.valid) print(node.valid) -print(node.name) \ No newline at end of file +print(node.name) +local query1=doc:root():select_nodes('Project/PropertyGroup') +local query2=node:select_nodes('PropertyGroup') +assert(query1) +assert(query2) +print(query1.type,pugi.xpath_node_set.type_sorted) +query1:sort(true) +print(query1.type,pugi.xpath_node_set.type_sorted) +print(query1.size,query2.size) +n=query1.size +for i=0,n-1 do + local node=query1:get(i):node() + local attribute=query1:get(i):attribute() + print(node.valid,node.path,attribute.valid) + local a=node:first_attribute() + while a.valid do + print(a.name) + a=a:next_attribute() + end +end + +---- +node=doc:root():child('Project') +print(node.text) \ No newline at end of file diff --git a/Notepad++.lnk b/Notepad++.lnk deleted file mode 100644 index 93733fb..0000000 Binary files a/Notepad++.lnk and /dev/null differ diff --git a/contrib/pugilua/pugilua_lib.cpp b/contrib/pugilua/pugilua_lib.cpp index 77f7454..6891949 100644 --- a/contrib/pugilua/pugilua_lib.cpp +++ b/contrib/pugilua/pugilua_lib.cpp @@ -4,69 +4,575 @@ #include #include #include +#include +#include namespace pugi { namespace lua { + static char const* version = "0.1.0"; + + class lxpath_node; + class lxpath_node_set; + + //////////////////// + static int encoding_auto = (int)pugi::encoding_auto; + static int encoding_utf8 = (int)pugi::encoding_utf8; + static int encoding_utf16_le = (int)pugi::encoding_utf16_le; + static int encoding_utf16_be = (int)pugi::encoding_utf16_be; + static int encoding_utf16 = (int)pugi::encoding_utf16; + static int encoding_utf32_le = (int)pugi::encoding_utf32_le; + static int encoding_utf32_be = (int)pugi::encoding_utf32_be; + static int encoding_utf32 = (int)pugi::encoding_utf32; + static int encoding_wchar = (int)pugi::encoding_wchar; + static int encoding_latin1 = (int)pugi::encoding_latin1; + + //////////////////// + static int node_null = (int)pugi::node_null; + static int node_document = (int)pugi::node_document; + static int node_element = (int)pugi::node_element; + static int node_pcdata = (int)pugi::node_pcdata; + static int node_cdata = (int)pugi::node_cdata; + static int node_comment = (int)pugi::node_comment; + static int node_pi = (int)pugi::node_pi; + static int node_declaration = (int)pugi::node_declaration; + static int node_doctype = (int)pugi::node_doctype; + + //////////////////// + class lxml_attribute { + public: + lxml_attribute(pugi::xml_attribute const& a):att(a) {} + lxml_attribute() {} + + public: + bool valid() const { return (bool)att; } + bool empty() const { return att.empty(); } + std::string name() const { return att.name(); } + std::string value() const { return att.value(); } + double number() const { return att.as_double(); } + bool as_bool() const { return att.as_bool(); } + + void set_name(char const* n) { att.set_name(n); } + void set_value(char const* v) { att.set_value(v); } + + RefCountedPtr next_attribute() const { + return RefCountedPtr(new lxml_attribute(att.next_attribute())); + } + + RefCountedPtr previous_attribute() const { + return RefCountedPtr(new lxml_attribute(att.previous_attribute())); + } + + size_t hash_value() const { + return att.hash_value(); + } + + public: // non-lua interface + pugi::xml_attribute const& get() const { + return att; + } + + private: + pugi::xml_attribute att; + }; + + /////////////////////// class lxml_parse_result { public: - lxml_parse_result(pugi::xml_parse_result& r):res(r) { } - lxml_parse_result() { } + lxml_parse_result(pugi::xml_parse_result& r); + lxml_parse_result(); public: - std::string description() const { - return res.description(); + std::string description() const; + + bool valid() const; + + int status() const { + return res.status; } - bool valid() const { - return (bool)res; + int encoding() const { + return res.encoding; } + ptrdiff_t offset() const { + return res.offset; + } + + public: + static int status_ok() { return pugi::status_ok; } + static int status_file_not_found() { return pugi::status_file_not_found; } + static int status_io_error() { return pugi::status_io_error; } + static int status_out_of_memory() { return pugi::status_out_of_memory; } + static int status_internal_error() { return pugi::status_internal_error; } + static int status_unrecognized_tag() { return pugi::status_unrecognized_tag; } + static int status_bad_pi() { return pugi::status_bad_pi; } + static int status_bad_comment() { return pugi::status_bad_comment; } + static int status_bad_cdata() { return pugi::status_bad_cdata; } + static int status_bad_doctype() { return pugi::status_bad_doctype; } + static int status_bad_pcdata() { return pugi::status_bad_pcdata; } + static int status_bad_start_element() { return pugi::status_bad_start_element; } + static int status_bad_attribute() { return pugi::status_bad_attribute; } + static int status_bad_end_element() { return pugi::status_bad_end_element; } + static int status_end_element_mismatch() { return pugi::status_end_element_mismatch; } + private: pugi::xml_parse_result res; }; + /////////////// class lxml_node { public: - lxml_node(pugi::xml_node& n):node(n){} - lxml_node() { } + lxml_node(pugi::xml_node const& n); + lxml_node(); public: - bool valid() const { - return (bool)node; - } + bool valid() const; - RefCountedPtr child(char const* name) { - return RefCountedPtr(new lxml_node(node.child(name))); - } + std::string name() const; + std::string value() const; - std::string name() const { - return node.name(); - } + bool empty() const; + + int type() const; + + RefCountedPtr first_attribute() const; + RefCountedPtr last_attribute() const; + + RefCountedPtr first_child() const; + RefCountedPtr last_child() const; + + RefCountedPtr parent() const; + RefCountedPtr root() const; + + RefCountedPtr child(char const* name) const; + RefCountedPtr attribute(char const* name) const; + + RefCountedPtr next() const; + RefCountedPtr previous() const; + + RefCountedPtr next_sibling(char const* name) const; + RefCountedPtr previous_sibling(char const* name) const; + + std::string child_value(char const* name) const; + + bool set_name(char const* rhs); + bool set_value(char const* rhs); + + RefCountedPtr append_attribute(const char* name); + RefCountedPtr prepend_attribute(const char* name); + RefCountedPtr insert_attribute_after(const char* name, RefCountedPtr attr); + RefCountedPtr insert_attribute_before(const char* name, RefCountedPtr attr); + + RefCountedPtr append_attribute_copy(RefCountedPtr proto); + RefCountedPtr prepend_attribute_copy(RefCountedPtr proto); + RefCountedPtr insert_attribute_copy_after(RefCountedPtr proto, RefCountedPtr attr); + RefCountedPtr insert_attribute_copy_before(RefCountedPtr proto, RefCountedPtr attr); + + RefCountedPtr append(int type); + RefCountedPtr prepend(int type); + RefCountedPtr insert_after(int type, RefCountedPtr _node); + RefCountedPtr insert_before(int type, RefCountedPtr _node); + + RefCountedPtr append_child(const char* name); + RefCountedPtr prepend_child(const char* name); + RefCountedPtr insert_child_after(const char* name, RefCountedPtr _node); + RefCountedPtr insert_child_before(const char* name, RefCountedPtr _node); + + RefCountedPtr append_copy(RefCountedPtr proto); + RefCountedPtr prepend_copy(RefCountedPtr proto); + RefCountedPtr insert_copy_after(RefCountedPtr proto, RefCountedPtr _node); + RefCountedPtr insert_copy_before(RefCountedPtr proto, RefCountedPtr _node); + + bool remove_attribute(RefCountedPtr a); + bool remove_attribute_by_name(const char* name); + + bool remove_child(RefCountedPtr n); + bool remove_child_by_name(const char* name); + + RefCountedPtr find_child_by_name_and_attribute(const char* name, const char* attr_name, const char* attr_value) const; + RefCountedPtr find_child_by_attribute(const char* attr_name, const char* attr_value) const; + + std::string path() const; + + RefCountedPtr first_element_by_path(const char* path) const; + + RefCountedPtr select_single_node(const char* query) const; + + RefCountedPtr select_nodes(char const* query) const; + + std::string text() const; + + //todo: text(), xml_tree_walker somehow + + public: // non-lua interface + pugi::xml_node const& get() const; private: pugi::xml_node node; }; + /////////////////// class lxml_document { public: - RefCountedPtr load_file(char const* path) { - return RefCountedPtr(new lxml_parse_result(doc.load_file(path))); - } + RefCountedPtr lxml_document::root() const; - // redundant, but defined due to composition up to now - RefCountedPtr child(char const* name) { - return RefCountedPtr(new lxml_node(doc.child(name))); - } + bool valid() const; - bool valid() const { - return (bool)doc; - } + void reset(); + + RefCountedPtr load_file(char const* path); + RefCountedPtr load(char const* contents); + bool save_file(char const* path) const; private: pugi::xml_document doc; }; + ///////////////// + class lxpath_node { + public: + lxpath_node(pugi::xpath_node const& n); + lxpath_node(); + + bool valid() const; + + RefCountedPtr node() const; + RefCountedPtr attribute() const; + + private: + pugi::xpath_node _node; + }; + + ///////////////////// + class lxpath_node_set { + public: + lxpath_node_set(pugi::xpath_node_set& s); + lxpath_node_set(); + public: + + int type() const; + + size_t size() const; + + // todo: think if 1..size is a better convention for lua + RefCountedPtr get(size_t i); + + void sort(bool reverse); + + public: + // enums + static int type_unsorted () { return pugi::xpath_node_set::type_unsorted; } + static int type_sorted () { return pugi::xpath_node_set::type_sorted; } + static int type_sorted_reverse () { return pugi::xpath_node_set::type_sorted_reverse; } + private: + pugi::xpath_node_set node_set; + }; + + } +} + +namespace pugi { + namespace lua { + + /////////////////////// + lxml_parse_result::lxml_parse_result(pugi::xml_parse_result& r):res(r) { } + lxml_parse_result::lxml_parse_result() { } + + std::string lxml_parse_result::description() const { + return res.description(); + } + + bool lxml_parse_result::valid() const { + return (bool)res; + } + + + /////////////// + lxml_node::lxml_node(pugi::xml_node const& n):node(n){} + lxml_node::lxml_node() { } + + pugi::xml_node const& lxml_node::get() const { + return node; + } + + bool lxml_node::valid() const { + return (bool)node; + } + + RefCountedPtr lxml_node::child(char const* name) const { + return RefCountedPtr(new lxml_node(node.child(name))); + } + + std::string lxml_node::name() const { + return node.name(); + } + + std::string lxml_node::value() const { + return node.value(); + } + + RefCountedPtr lxml_node::select_nodes(char const* query) const { + try { + return RefCountedPtr(new lxpath_node_set(node.select_nodes(query))); + } catch (pugi::xpath_exception const& e) { + std::cerr<<"Error: "<(new lxpath_node_set()); + } + } + + bool lxml_node::empty() const { + return node.empty(); + } + + int lxml_node::type() const { + return node.type(); + } + + RefCountedPtr lxml_node::first_attribute() const { + return RefCountedPtr(new lxml_attribute(node.first_attribute())); + } + + RefCountedPtr lxml_node::last_attribute() const { + return RefCountedPtr(new lxml_attribute(node.last_attribute())); + } + + RefCountedPtr lxml_node::first_child() const { + return RefCountedPtr(new lxml_node(node.first_child())); + } + + RefCountedPtr lxml_node::last_child() const { + return RefCountedPtr(new lxml_node(node.last_child())); + } + + RefCountedPtr lxml_node::parent() const { + return RefCountedPtr(new lxml_node(node.parent())); + } + + RefCountedPtr lxml_node::root() const { + return RefCountedPtr(new lxml_node(node.root())); + } + + RefCountedPtr lxml_node::attribute(char const* name) const { + return RefCountedPtr(new lxml_attribute(node.attribute(name))); + } + + RefCountedPtr lxml_node::next() const { + return RefCountedPtr(new lxml_node(node.next_sibling())); + } + + RefCountedPtr lxml_node::previous() const { + return RefCountedPtr(new lxml_node(node.previous_sibling())); + } + + RefCountedPtr lxml_node::next_sibling(char const* name) const { + return RefCountedPtr(new lxml_node(node.next_sibling(name))); + } + + RefCountedPtr lxml_node::previous_sibling(char const* name) const { + return RefCountedPtr(new lxml_node(node.previous_sibling(name))); + } + + std::string lxml_node::child_value(char const* name) const { + return node.child_value(name); + } + + bool lxml_node::set_name(char const* rhs) { + return node.set_name(rhs); + } + + bool lxml_node::set_value(char const* rhs) { + return node.set_value(rhs); + } + + RefCountedPtr lxml_node::append_attribute(const char* name) { + return RefCountedPtr(new lxml_attribute(node.append_attribute(name))); + } + + RefCountedPtr lxml_node::prepend_attribute(const char* name) { + return RefCountedPtr(new lxml_attribute(node.prepend_attribute(name))); + } + + RefCountedPtr lxml_node::insert_attribute_after(const char* name, RefCountedPtr attr) { + return RefCountedPtr(new lxml_attribute(node.insert_attribute_after(name,attr->get()))); + } + + RefCountedPtr lxml_node::insert_attribute_before(const char* name, RefCountedPtr attr) { + return RefCountedPtr(new lxml_attribute(node.insert_attribute_before(name,attr->get()))); + } + + RefCountedPtr lxml_node::append_attribute_copy(RefCountedPtr proto) { + return RefCountedPtr(new lxml_attribute(node.append_copy(proto->get()))); + } + + RefCountedPtr lxml_node::prepend_attribute_copy(RefCountedPtr proto) { + return RefCountedPtr(new lxml_attribute(node.prepend_copy(proto->get()))); + } + + RefCountedPtr lxml_node::insert_attribute_copy_after(RefCountedPtr proto, RefCountedPtr attr) { + return RefCountedPtr(new lxml_attribute(node.insert_copy_after(proto->get(),attr->get()))); + } + + RefCountedPtr lxml_node::insert_attribute_copy_before(RefCountedPtr proto, RefCountedPtr attr) { + return RefCountedPtr(new lxml_attribute(node.insert_copy_before(proto->get(),attr->get()))); + } + + RefCountedPtr lxml_node::append(int type) { + return RefCountedPtr(new lxml_node(node.append_child((xml_node_type)type))); + } + + RefCountedPtr lxml_node::prepend(int type) { + return RefCountedPtr(new lxml_node(node.prepend_child((xml_node_type)type))); + } + + RefCountedPtr lxml_node::insert_after(int type, RefCountedPtr _node) { + return RefCountedPtr(new lxml_node(node.insert_child_after((xml_node_type)type,_node->get()))); + } + + RefCountedPtr lxml_node::insert_before(int type, RefCountedPtr _node) { + return RefCountedPtr(new lxml_node(node.insert_child_before((xml_node_type)type,_node->get()))); + } + + RefCountedPtr lxml_node::append_child(const char* name) { + return RefCountedPtr(new lxml_node(node.append_child(name))); + } + + RefCountedPtr lxml_node::prepend_child(const char* name) { + return RefCountedPtr(new lxml_node(node.prepend_child(name))); + } + + RefCountedPtr lxml_node::insert_child_after(const char* name, RefCountedPtr _node) { + return RefCountedPtr(new lxml_node(node.insert_child_after(name,_node->get()))); + } + + RefCountedPtr lxml_node::insert_child_before(const char* name, RefCountedPtr _node) { + return RefCountedPtr(new lxml_node(node.insert_child_before(name,_node->get()))); + } + + RefCountedPtr lxml_node::append_copy(RefCountedPtr proto) { + return RefCountedPtr(new lxml_node(node.append_copy(proto->get()))); + } + + RefCountedPtr lxml_node::prepend_copy(RefCountedPtr proto) { + return RefCountedPtr(new lxml_node(node.prepend_copy(proto->get()))); + } + + RefCountedPtr lxml_node::insert_copy_after(RefCountedPtr proto, RefCountedPtr _node) { + return RefCountedPtr(new lxml_node(node.insert_copy_after(proto->get(),_node->get()))); + } + + RefCountedPtr lxml_node::insert_copy_before(RefCountedPtr proto, RefCountedPtr _node) { + return RefCountedPtr(new lxml_node(node.insert_copy_before(proto->get(),_node->get()))); + } + + bool lxml_node::remove_attribute(RefCountedPtr a) { + return node.remove_attribute(a->get()); + } + + bool lxml_node::remove_attribute_by_name(const char* name) { + return node.remove_attribute(name); + } + + bool lxml_node::remove_child(RefCountedPtr n) { + return node.remove_child(n->get()); + } + + bool lxml_node::remove_child_by_name(const char* name) { + return node.remove_child(name); + } + + RefCountedPtr lxml_node::find_child_by_name_and_attribute(const char* name, const char* attr_name, const char* attr_value) const { + return RefCountedPtr(new lxml_node(node.find_child_by_attribute(name,attr_name,attr_value))); + } + + RefCountedPtr lxml_node::find_child_by_attribute(const char* attr_name, const char* attr_value) const { + return RefCountedPtr(new lxml_node(node.find_child_by_attribute(attr_name,attr_name,attr_value))); + } + + std::string lxml_node::path() const { + return node.path(); + } + + RefCountedPtr lxml_node::first_element_by_path(const char* path) const { + return RefCountedPtr(new lxml_node(node.first_element_by_path(path))); + } + + RefCountedPtr lxml_node::select_single_node(char const* query) const { + try { + return RefCountedPtr(new lxpath_node(node.select_single_node(query))); + } catch (pugi::xpath_exception const& e) { + std::cerr<<"Error: "<(new lxpath_node()); + } + } + + std::string lxml_node::text() const { + std::stringstream ss; + node.print(ss); + return ss.str(); + } + + /////////////////// + RefCountedPtr lxml_document::load_file(char const* path) { + return RefCountedPtr(new lxml_parse_result(doc.load_file(path))); + } + + RefCountedPtr lxml_document::root() const { + return RefCountedPtr(new lxml_node(pugi::xml_node(doc))); + } + + bool lxml_document::valid() const { + return (bool)doc; + } + + void lxml_document::reset() { + doc.reset(); + } + + RefCountedPtr lxml_document::load(char const* contents) { + return RefCountedPtr(new lxml_parse_result(doc.load(contents))); + } + + bool lxml_document::save_file(char const* path) const { + return doc.save_file(path); + } + + ////////////////////// + lxpath_node::lxpath_node(pugi::xpath_node const& n):_node(n){} + lxpath_node::lxpath_node() { } + + bool lxpath_node::valid() const { + return (bool)_node; + } + + RefCountedPtr lxpath_node::node() const { + return RefCountedPtr(new lxml_node(_node.node())); + } + + RefCountedPtr lxpath_node::attribute() const { + return RefCountedPtr(new lxml_attribute(_node.attribute())); + } + + + ///////////////////// + lxpath_node_set::lxpath_node_set(pugi::xpath_node_set& s):node_set(s) { } + lxpath_node_set::lxpath_node_set() { } + + int lxpath_node_set::type() const { + return node_set.type(); + } + + size_t lxpath_node_set::size() const { + return node_set.size(); + } + + RefCountedPtr lxpath_node_set::get(size_t i) { + return RefCountedPtr(new lxpath_node(node_set[i])); + } + + void lxpath_node_set::sort(bool reverse) { + node_set.sort(reverse); + } } } @@ -75,24 +581,148 @@ void register_pugilua (lua_State* L) { luabridge::getGlobalNamespace(L) .beginNamespace("pugi") + .addVariable("version",&version,false) + + .addVariable("encoding_auto",&encoding_auto,false) + .addVariable("encoding_utf8",&encoding_utf8,false) + .addVariable("encoding_utf16_le",&encoding_utf16_le,false) + .addVariable("encoding_utf16_be",&encoding_utf16_be,false) + .addVariable("encoding_utf16",&encoding_utf16,false) + .addVariable("encoding_utf32_le",&encoding_utf32_le,false) + .addVariable("encoding_utf32_be",&encoding_utf32_be,false) + .addVariable("encoding_utf32",&encoding_utf32,false) + .addVariable("encoding_wchar",&encoding_wchar,false) + .addVariable("encoding_latin1",&encoding_latin1,false) + + .addVariable("node_null",&node_null,false) + .addVariable("node_document",&node_document,false) + .addVariable("node_element",&node_element,false) + .addVariable("node_pcdata",&node_pcdata,false) + .addVariable("node_cdata",&node_cdata,false) + .addVariable("node_comment",&node_comment,false) + .addVariable("node_pi",&node_pi,false) + .addVariable("node_declaration",&node_declaration,false) + .addVariable("node_doctype",&node_doctype,false) + + .beginClass("xml_attribute") + .addConstructor() + .addProperty("valid",&lxml_attribute::valid) + .addProperty("empty",&lxml_attribute::empty) + .addProperty("name",&lxml_attribute::name) + .addProperty("value",&lxml_attribute::value) + .addProperty("number",&lxml_attribute::number) + .addProperty("bool",&lxml_attribute::as_bool) + .addProperty("hash_value",&lxml_attribute::hash_value) + .addFunction("set_name",&lxml_attribute::set_name) + .addFunction("set_value",&lxml_attribute::set_value) + .addFunction("next_attribute",&lxml_attribute::next_attribute) + .addFunction("previous_attribute",&lxml_attribute::previous_attribute) + .endClass() + .beginClass("xml_parse_result") .addConstructor() .addProperty("description",&lxml_parse_result::description) .addProperty("valid",&lxml_parse_result::valid) + .addProperty("status",&lxml_parse_result::status) + .addProperty("encoding",&lxml_parse_result::encoding) + .addProperty("offset",&lxml_parse_result::offset) + .addStaticProperty("status_ok",&lxml_parse_result::status_ok) + .addStaticProperty("status_io_error",&lxml_parse_result::status_io_error) + .addStaticProperty("status_out_of_memory",&lxml_parse_result::status_out_of_memory) + .addStaticProperty("status_internal_error",&lxml_parse_result::status_internal_error) + .addStaticProperty("status_unrecognized_tag",&lxml_parse_result::status_unrecognized_tag) + .addStaticProperty("status_bad_pi",&lxml_parse_result::status_bad_pi) + .addStaticProperty("status_bad_comment",&lxml_parse_result::status_bad_comment) + .addStaticProperty("status_bad_cdata",&lxml_parse_result::status_bad_cdata) + .addStaticProperty("status_bad_doctype",&lxml_parse_result::status_bad_doctype) + .addStaticProperty("status_bad_pcdata",&lxml_parse_result::status_bad_pcdata) + .addStaticProperty("status_bad_start_element",&lxml_parse_result::status_bad_start_element) + .addStaticProperty("status_bad_attribute",&lxml_parse_result::status_bad_attribute) + .addStaticProperty("status_bad_end_element",&lxml_parse_result::status_bad_end_element) + .addStaticProperty("status_end_element_mismatch",&lxml_parse_result::status_end_element_mismatch) + .addStaticProperty("status_file_not_found",&lxml_parse_result::status_file_not_found) .endClass() .beginClass("xml_node") .addConstructor() .addProperty("valid",&lxml_node::valid) .addProperty("name",&lxml_node::name) + .addProperty("value",&lxml_node::value) + .addProperty("type",&lxml_node::type) + .addProperty("path",&lxml_node::path) + .addProperty("text",&lxml_node::text) .addFunction("child",&lxml_node::child) + .addFunction("first_attribute",&lxml_node::first_attribute) + .addFunction("last_attribute",&lxml_node::last_attribute) + .addFunction("first_child",&lxml_node::first_child) + .addFunction("last_child",&lxml_node::last_child) + .addFunction("parent",&lxml_node::parent) + .addFunction("root",&lxml_node::root) + .addFunction("attribute",&lxml_node::attribute) + .addFunction("next",&lxml_node::next) + .addFunction("previous",&lxml_node::previous) + .addFunction("next_sibling",&lxml_node::next_sibling) + .addFunction("previous_sibling",&lxml_node::previous_sibling) + .addFunction("child_value",&lxml_node::child_value) + .addFunction("set_name",&lxml_node::set_name) + .addFunction("set_value",&lxml_node::set_value) + .addFunction("append_attribute",&lxml_node::append_attribute) + .addFunction("prepend_attribute",&lxml_node::prepend_attribute) + .addFunction("insert_attribute_after",&lxml_node::insert_attribute_after) + .addFunction("insert_attribute_before",&lxml_node::insert_attribute_before) + .addFunction("append_attribute_copy",&lxml_node::append_attribute_copy) + .addFunction("prepend_attribute_copy",&lxml_node::prepend_attribute_copy) + .addFunction("insert_attribute_copy_after",&lxml_node::insert_attribute_copy_after) + .addFunction("insert_attribute_copy_before",&lxml_node::insert_attribute_copy_before) + .addFunction("append",&lxml_node::append) + .addFunction("prepend",&lxml_node::prepend) + .addFunction("insert_after",&lxml_node::insert_after) + .addFunction("insert_before",&lxml_node::insert_before) + .addFunction("append_child",&lxml_node::append_child) + .addFunction("prepend_child",&lxml_node::prepend_child) + .addFunction("insert_child_after",&lxml_node::insert_child_after) + .addFunction("insert_child_before",&lxml_node::insert_child_before) + .addFunction("append_copy",&lxml_node::append_copy) + .addFunction("prepend_copy",&lxml_node::prepend_copy) + .addFunction("insert_copy_after",&lxml_node::insert_copy_after) + .addFunction("insert_copy_before",&lxml_node::insert_copy_before) + .addFunction("remove_attribute",&lxml_node::remove_attribute) + .addFunction("remove_attribute_by_name",&lxml_node::remove_attribute_by_name) + .addFunction("remove_child",&lxml_node::remove_child) + .addFunction("remove_child_by_name",&lxml_node::remove_child_by_name) + .addFunction("find_child_by_name_and_attribute",&lxml_node::find_child_by_name_and_attribute) + .addFunction("find_child_by_attribute",&lxml_node::find_child_by_attribute) + .addFunction("first_element_by_path",&lxml_node::first_element_by_path) + .addFunction("select_single_node",&lxml_node::select_single_node) + .addFunction("select_nodes",&lxml_node::select_nodes) .endClass() .beginClass("xml_document") .addConstructor() .addProperty("valid",&lxml_document::valid) + .addFunction("root",&lxml_document::root) + .addFunction("reset",&lxml_document::reset) .addFunction("load_file",&lxml_document::load_file) - .addFunction("child",&lxml_document::child) + .addFunction("load",&lxml_document::load) + .addFunction("save_file",&lxml_document::save_file) + .endClass() + + .beginClass("xpath_node") + .addConstructor() + .addProperty("valid",&lxpath_node::valid) + .addFunction("node",&lxpath_node::node) + .addFunction("attribute",&lxpath_node::attribute) + .endClass() + + .beginClass("xpath_node_set") + .addConstructor() + .addProperty("type",&lxpath_node_set::type) + .addProperty("size",&lxpath_node_set::size) + .addStaticProperty("type_unsorted",&lxpath_node_set::type_unsorted) + .addStaticProperty("type_sorted",&lxpath_node_set::type_sorted) + .addStaticProperty("type_sorted_reverse",&lxpath_node_set::type_sorted_reverse) + .addFunction("get",&lxpath_node_set::get) + .addFunction("sort",&lxpath_node_set::sort) .endClass() .endNamespace() diff --git a/docs/samples/save_declaration.cpp b/docs/samples/save_declaration.cpp index 6c82061..aaed9b5 100644 --- a/docs/samples/save_declaration.cpp +++ b/docs/samples/save_declaration.cpp @@ -1,27 +1,27 @@ -#include "pugixml.hpp" - -#include - -int main() -{ - //[code_save_declaration - // get a test document - pugi::xml_document doc; - doc.load("hey"); - - // add a custom declaration node - pugi::xml_node decl = doc.prepend_child(pugi::node_declaration); - decl.append_attribute("version") = "1.0"; - decl.append_attribute("encoding") = "UTF-8"; - decl.append_attribute("standalone") = "no"; - - // - // - // hey - // - doc.save(std::cout); - std::cout << std::endl; - //] -} - -// vim:et +#include "pugixml.hpp" + +#include + +int main() +{ + //[code_save_declaration + // get a test document + pugi::xml_document doc; + doc.load("hey"); + + // add a custom declaration node + pugi::xml_node decl = doc.prepend_child(pugi::node_declaration); + decl.append_attribute("version") = "1.0"; + decl.append_attribute("encoding") = "UTF-8"; + decl.append_attribute("standalone") = "no"; + + // + // + // hey + // + doc.save(std::cout); + std::cout << std::endl; + //] +} + +// vim:et diff --git a/docs/samples/text.cpp b/docs/samples/text.cpp index 9b1cf69..7e03709 100644 --- a/docs/samples/text.cpp +++ b/docs/samples/text.cpp @@ -1,35 +1,35 @@ -#include "pugixml.hpp" - -#include - -int main() -{ - pugi::xml_document doc; - - // get a test document - doc.load("test1.1yes"); - - pugi::xml_node project = doc.child("project"); - - //[code_text_access - std::cout << "Project name: " << project.child("name").text().get() << std::endl; - std::cout << "Project version: " << project.child("version").text().as_double() << std::endl; - std::cout << "Project visibility: " << (project.child("public").text().as_bool(/* def= */ true) ? "public" : "private") << std::endl; - std::cout << "Project description: " << project.child("description").text().get() << std::endl; - //] - - std::cout << std::endl; - - //[code_text_modify - // change project version - project.child("version").text() = 1.2; - - // add description element and set the contents - // note that we do not have to explicitly add the node_pcdata child - project.append_child("description").text().set("a test project"); - //] - - doc.save(std::cout); -} - -// vim:et +#include "pugixml.hpp" + +#include + +int main() +{ + pugi::xml_document doc; + + // get a test document + doc.load("test1.1yes"); + + pugi::xml_node project = doc.child("project"); + + //[code_text_access + std::cout << "Project name: " << project.child("name").text().get() << std::endl; + std::cout << "Project version: " << project.child("version").text().as_double() << std::endl; + std::cout << "Project visibility: " << (project.child("public").text().as_bool(/* def= */ true) ? "public" : "private") << std::endl; + std::cout << "Project description: " << project.child("description").text().get() << std::endl; + //] + + std::cout << std::endl; + + //[code_text_modify + // change project version + project.child("version").text() = 1.2; + + // add description element and set the contents + // note that we do not have to explicitly add the node_pcdata child + project.append_child("description").text().set("a test project"); + //] + + doc.save(std::cout); +} + +// vim:et diff --git a/docs/samples/traverse_rangefor.cpp b/docs/samples/traverse_rangefor.cpp index 1f7212e..a284b9e 100644 --- a/docs/samples/traverse_rangefor.cpp +++ b/docs/samples/traverse_rangefor.cpp @@ -1,32 +1,32 @@ -#include "pugixml.hpp" - -#include - -int main() -{ - pugi::xml_document doc; - if (!doc.load_file("xgconsole.xml")) return -1; - - pugi::xml_node tools = doc.child("Profile").child("Tools"); - - //[code_traverse_rangefor - for (pugi::xml_node tool: tools.children("Tool")) - { - std::cout << "Tool:"; - - for (pugi::xml_attribute attr: tool.attributes()) - { - std::cout << " " << attr.name() << "=" << attr.value(); - } - - for (pugi::xml_node child: tool.children()) - { - std::cout << ", child " << child.name(); - } - - std::cout << std::endl; - } - //] -} - -// vim:et +#include "pugixml.hpp" + +#include + +int main() +{ + pugi::xml_document doc; + if (!doc.load_file("xgconsole.xml")) return -1; + + pugi::xml_node tools = doc.child("Profile").child("Tools"); + + //[code_traverse_rangefor + for (pugi::xml_node tool: tools.children("Tool")) + { + std::cout << "Tool:"; + + for (pugi::xml_attribute attr: tool.attributes()) + { + std::cout << " " << attr.name() << "=" << attr.value(); + } + + for (pugi::xml_node child: tool.children()) + { + std::cout << ", child " << child.name(); + } + + std::cout << std::endl; + } + //] +} + +// vim:et diff --git a/docs/samples/xpath_variables.cpp b/docs/samples/xpath_variables.cpp index 5404c0b..c6e9c51 100644 --- a/docs/samples/xpath_variables.cpp +++ b/docs/samples/xpath_variables.cpp @@ -1,38 +1,38 @@ -#include "pugixml.hpp" - -#include -#include - -int main() -{ - pugi::xml_document doc; - if (!doc.load_file("xgconsole.xml")) return -1; - -//[code_xpath_variables - // Select nodes via compiled query - pugi::xpath_variable_set vars; - vars.add("remote", pugi::xpath_type_boolean); - - pugi::xpath_query query_remote_tools("/Profile/Tools/Tool[@AllowRemote = string($remote)]", &vars); - - vars.set("remote", true); - pugi::xpath_node_set tools_remote = query_remote_tools.evaluate_node_set(doc); - - vars.set("remote", false); - pugi::xpath_node_set tools_local = query_remote_tools.evaluate_node_set(doc); - - std::cout << "Remote tool: "; - tools_remote[2].node().print(std::cout); - - std::cout << "Local tool: "; - tools_local[0].node().print(std::cout); - - // You can pass the context directly to select_nodes/select_single_node - pugi::xpath_node_set tools_local_imm = doc.select_nodes("/Profile/Tools/Tool[@AllowRemote = string($remote)]", &vars); - - std::cout << "Local tool imm: "; - tools_local_imm[0].node().print(std::cout); -//] -} - -// vim:et +#include "pugixml.hpp" + +#include +#include + +int main() +{ + pugi::xml_document doc; + if (!doc.load_file("xgconsole.xml")) return -1; + +//[code_xpath_variables + // Select nodes via compiled query + pugi::xpath_variable_set vars; + vars.add("remote", pugi::xpath_type_boolean); + + pugi::xpath_query query_remote_tools("/Profile/Tools/Tool[@AllowRemote = string($remote)]", &vars); + + vars.set("remote", true); + pugi::xpath_node_set tools_remote = query_remote_tools.evaluate_node_set(doc); + + vars.set("remote", false); + pugi::xpath_node_set tools_local = query_remote_tools.evaluate_node_set(doc); + + std::cout << "Remote tool: "; + tools_remote[2].node().print(std::cout); + + std::cout << "Local tool: "; + tools_local[0].node().print(std::cout); + + // You can pass the context directly to select_nodes/select_single_node + pugi::xpath_node_set tools_local_imm = doc.select_nodes("/Profile/Tools/Tool[@AllowRemote = string($remote)]", &vars); + + std::cout << "Local tool imm: "; + tools_local_imm[0].node().print(std::cout); +//] +} + +// vim:et diff --git a/scripts/pugilua/pugilua.vcxproj.filters b/scripts/pugilua/pugilua.vcxproj.filters index 13b9b01..923314e 100644 --- a/scripts/pugilua/pugilua.vcxproj.filters +++ b/scripts/pugilua/pugilua.vcxproj.filters @@ -15,15 +15,15 @@ - + Source Files - + Source Files - + Header Files diff --git a/scripts/pugixml_airplay.mkf b/scripts/pugixml_airplay.mkf index 0ca5c23..477f54a 100644 --- a/scripts/pugixml_airplay.mkf +++ b/scripts/pugixml_airplay.mkf @@ -1,13 +1,13 @@ -includepaths -{ -"../src" -} - -files -{ -("../src") -pugiconfig.hpp -pugixml.cpp -pugixml.hpp -} - +includepaths +{ +"../src" +} + +files +{ +("../src") +pugiconfig.hpp +pugixml.cpp +pugixml.hpp +} + diff --git a/tests/data/truncation.xml b/tests/data/truncation.xml index 9cdbe13..266bc60 100644 --- a/tests/data/truncation.xml +++ b/tests/data/truncation.xml @@ -1,19 +1,19 @@ - - - - - - some text - - some more text - - - <æ+%è¯- å__å--="name" ä>·å__="value">ä¸-ç_æ_%å__å¤_è¯-è¨_ð¤-¢ - - - <æ°_å__> - <æ°_>å++ç"° - <å__>太é__ - - - + + + + + + some text + + some more text + + + <æ+%è¯- å__å--="name" ä>·å__="value">ä¸-ç_æ_%å__å¤_è¯-è¨_ð¤-¢ + + + <æ°_å__> + <æ°_>å++ç"° + <å__>太é__ + + + diff --git a/tests/test_dom_text.cpp b/tests/test_dom_text.cpp index 153c372..49f9744 100644 --- a/tests/test_dom_text.cpp +++ b/tests/test_dom_text.cpp @@ -1,252 +1,252 @@ -#include "common.hpp" - -#include "helpers.hpp" - -TEST_XML_FLAGS(dom_text_empty, "foo", parse_default | parse_pi) -{ - xml_node node = doc.child(STR("node")); - - CHECK(node.child(STR("a")).text()); - CHECK(node.child(STR("b")).text()); - CHECK(!node.child(STR("c")).text()); - CHECK(!node.child(STR("d")).text()); - CHECK(!xml_node().text()); - CHECK(!xml_text()); - - generic_empty_test(node.child(STR("a")).text()); -} - -TEST_XML(dom_text_bool_ops, "foo") -{ - generic_bool_ops_test(doc.child(STR("node")).text()); -} - -TEST_XML_FLAGS(dom_text_get, "foo", parse_default | parse_pi) -{ - xml_node node = doc.child(STR("node")); - - CHECK_STRING(node.child(STR("a")).text().get(), STR("foo")); - CHECK_STRING(node.child(STR("a")).first_child().text().get(), STR("foo")); - - CHECK_STRING(node.child(STR("b")).text().get(), STR("bar")); - CHECK_STRING(node.child(STR("b")).last_child().text().get(), STR("bar")); - - CHECK_STRING(node.child(STR("c")).text().get(), STR("")); - CHECK_STRING(node.child(STR("c")).first_child().text().get(), STR("")); - - CHECK_STRING(node.child(STR("d")).text().get(), STR("")); - - CHECK_STRING(xml_node().text().get(), STR("")); -} - -TEST_XML_FLAGS(dom_text_as_string, "foo", parse_default | parse_pi) -{ - xml_node node = doc.child(STR("node")); - - CHECK_STRING(node.child(STR("a")).text().as_string(), STR("foo")); - CHECK_STRING(node.child(STR("a")).first_child().text().as_string(), STR("foo")); - - CHECK_STRING(node.child(STR("b")).text().as_string(), STR("bar")); - CHECK_STRING(node.child(STR("b")).last_child().text().as_string(), STR("bar")); - - CHECK_STRING(node.child(STR("c")).text().as_string(), STR("")); - CHECK_STRING(node.child(STR("c")).first_child().text().as_string(), STR("")); - - CHECK_STRING(node.child(STR("d")).text().as_string(), STR("")); - - CHECK_STRING(xml_node().text().as_string(), STR("")); -} - -TEST_XML(dom_text_as_int, "1-1-21474836482147483647") -{ - xml_node node = doc.child(STR("node")); - - CHECK(xml_text().as_int() == 0); - CHECK(node.child(STR("text1")).text().as_int() == 1); - CHECK(node.child(STR("text2")).text().as_int() == -1); - CHECK(node.child(STR("text3")).text().as_int() == -2147483647 - 1); - CHECK(node.child(STR("text4")).text().as_int() == 2147483647); -} - -TEST_XML(dom_text_as_uint, "0121474836474294967295") -{ - xml_node node = doc.child(STR("node")); - - CHECK(xml_text().as_uint() == 0); - CHECK(node.child(STR("text1")).text().as_uint() == 0); - CHECK(node.child(STR("text2")).text().as_uint() == 1); - CHECK(node.child(STR("text3")).text().as_uint() == 2147483647); - CHECK(node.child(STR("text4")).text().as_uint() == 4294967295u); -} - -TEST_XML(dom_text_as_float, "010.12-5.13e-43.14159265358979323846") -{ - xml_node node = doc.child(STR("node")); - - CHECK(xml_text().as_float() == 0); - CHECK_DOUBLE(node.child(STR("text1")).text().as_float(), 0); - CHECK_DOUBLE(node.child(STR("text2")).text().as_float(), 1); - CHECK_DOUBLE(node.child(STR("text3")).text().as_float(), 0.12); - CHECK_DOUBLE(node.child(STR("text4")).text().as_float(), -5.1); - CHECK_DOUBLE(node.child(STR("text5")).text().as_float(), 3e-4); - CHECK_DOUBLE(node.child(STR("text6")).text().as_float(), 3.14159265358979323846); -} - -TEST_XML(dom_text_as_double, "010.12-5.13e-43.14159265358979323846") -{ - xml_node node = doc.child(STR("node")); - - CHECK(xml_text().as_double() == 0); - CHECK_DOUBLE(node.child(STR("text1")).text().as_double(), 0); - CHECK_DOUBLE(node.child(STR("text2")).text().as_double(), 1); - CHECK_DOUBLE(node.child(STR("text3")).text().as_double(), 0.12); - CHECK_DOUBLE(node.child(STR("text4")).text().as_double(), -5.1); - CHECK_DOUBLE(node.child(STR("text5")).text().as_double(), 3e-4); - CHECK_DOUBLE(node.child(STR("text6")).text().as_double(), 3.14159265358979323846); -} - -TEST_XML(dom_text_as_bool, "01trueTrueYesyesfalse") -{ - xml_node node = doc.child(STR("node")); - - CHECK(!xml_text().as_bool()); - CHECK(!node.child(STR("text1")).text().as_bool()); - CHECK(node.child(STR("text2")).text().as_bool()); - CHECK(node.child(STR("text3")).text().as_bool()); - CHECK(node.child(STR("text4")).text().as_bool()); - CHECK(node.child(STR("text5")).text().as_bool()); - CHECK(node.child(STR("text6")).text().as_bool()); - CHECK(!node.child(STR("text7")).text().as_bool()); -} - -TEST_XML(dom_text_get_no_state, "") -{ - xml_node node = doc.child(STR("node")); - xml_text t = node.text(); - - CHECK(!t); - CHECK(t.get() && *t.get() == 0); - CHECK(!node.first_child()); - - node.append_child(node_pcdata); - - CHECK(t); - CHECK_STRING(t.get(), STR("")); - - node.first_child().set_value(STR("test")); - - CHECK(t); - CHECK_STRING(t.get(), STR("test")); -} - -TEST_XML(dom_text_set, "") -{ - xml_node node = doc.child(STR("node")); - xml_text t = node.text(); - - t.set(STR("")); - CHECK(node.first_child().type() == node_pcdata); - CHECK_NODE(node, STR("")); - - t.set(STR("boo")); - CHECK(node.first_child().type() == node_pcdata); - CHECK(node.first_child() == node.last_child()); - CHECK_NODE(node, STR("boo")); - - t.set(STR("foobarfoobar")); - CHECK(node.first_child().type() == node_pcdata); - CHECK(node.first_child() == node.last_child()); - CHECK_NODE(node, STR("foobarfoobar")); -} - -TEST_XML(dom_text_assign, "") -{ - xml_node node = doc.child(STR("node")); - - node.append_child(STR("text1")).text() = STR("v1"); - xml_text() = STR("v1"); - - node.append_child(STR("text2")).text() = -2147483647; - node.append_child(STR("text3")).text() = -2147483647 - 1; - xml_text() = -2147483647 - 1; - - node.append_child(STR("text4")).text() = 4294967295u; - node.append_child(STR("text5")).text() = 4294967294u; - xml_text() = 2147483647; - - node.append_child(STR("text6")).text() = 0.5; - xml_text() = 0.5; - - node.append_child(STR("text7")).text() = true; - xml_text() = true; - - CHECK_NODE(node, STR("v1-2147483647-2147483648429496729542949672940.5true")); -} - -TEST_XML(dom_text_set_value, "") -{ - xml_node node = doc.child(STR("node")); - - CHECK(node.append_child(STR("text1")).text().set(STR("v1"))); - CHECK(!xml_text().set(STR("v1"))); - - CHECK(node.append_child(STR("text2")).text().set(-2147483647)); - CHECK(node.append_child(STR("text3")).text().set(-2147483647 - 1)); - CHECK(!xml_text().set(-2147483647 - 1)); - - CHECK(node.append_child(STR("text4")).text().set(4294967295u)); - CHECK(node.append_child(STR("text5")).text().set(4294967294u)); - CHECK(!xml_text().set(2147483647)); - - CHECK(node.append_child(STR("text6")).text().set(0.5)); - CHECK(!xml_text().set(0.5)); - - CHECK(node.append_child(STR("text7")).text().set(true)); - CHECK(!xml_text().set(true)); - - CHECK_NODE(node, STR("v1-2147483647-2147483648429496729542949672940.5true")); -} - -TEST_XML(dom_text_middle, "notthisonetext") -{ - xml_node node = doc.child(STR("node")); - xml_text t = node.text(); - - CHECK_STRING(t.get(), STR("text")); - t.set(STR("notext")); - - CHECK_NODE(node, STR("notthisonenotext")); - CHECK(node.remove_child(t.data())); - - CHECK(!t); - CHECK_NODE(node, STR("notthisone")); - - t.set(STR("yestext")); - - CHECK(t); - CHECK_NODE(node, STR("notthisoneyestext")); - CHECK(t.data() == node.last_child()); -} - -TEST_XML_FLAGS(dom_text_data, "foo", parse_default | parse_pi) -{ - xml_node node = doc.child(STR("node")); - - CHECK(node.child(STR("a")).text().data() == node.child(STR("a")).first_child()); - CHECK(node.child(STR("b")).text().data() == node.child(STR("b")).first_child()); - CHECK(!node.child(STR("c")).text().data()); - CHECK(!node.child(STR("d")).text().data()); - CHECK(!xml_text().data()); -} - -TEST(dom_text_defaults) -{ - xml_text text; - - CHECK_STRING(text.as_string(STR("foo")), STR("foo")); - CHECK(text.as_int(42) == 42); - CHECK(text.as_uint(42) == 42); - CHECK(text.as_double(42) == 42); - CHECK(text.as_float(42) == 42); - CHECK(text.as_bool(true) == true); -} +#include "common.hpp" + +#include "helpers.hpp" + +TEST_XML_FLAGS(dom_text_empty, "foo", parse_default | parse_pi) +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.child(STR("a")).text()); + CHECK(node.child(STR("b")).text()); + CHECK(!node.child(STR("c")).text()); + CHECK(!node.child(STR("d")).text()); + CHECK(!xml_node().text()); + CHECK(!xml_text()); + + generic_empty_test(node.child(STR("a")).text()); +} + +TEST_XML(dom_text_bool_ops, "foo") +{ + generic_bool_ops_test(doc.child(STR("node")).text()); +} + +TEST_XML_FLAGS(dom_text_get, "foo", parse_default | parse_pi) +{ + xml_node node = doc.child(STR("node")); + + CHECK_STRING(node.child(STR("a")).text().get(), STR("foo")); + CHECK_STRING(node.child(STR("a")).first_child().text().get(), STR("foo")); + + CHECK_STRING(node.child(STR("b")).text().get(), STR("bar")); + CHECK_STRING(node.child(STR("b")).last_child().text().get(), STR("bar")); + + CHECK_STRING(node.child(STR("c")).text().get(), STR("")); + CHECK_STRING(node.child(STR("c")).first_child().text().get(), STR("")); + + CHECK_STRING(node.child(STR("d")).text().get(), STR("")); + + CHECK_STRING(xml_node().text().get(), STR("")); +} + +TEST_XML_FLAGS(dom_text_as_string, "foo", parse_default | parse_pi) +{ + xml_node node = doc.child(STR("node")); + + CHECK_STRING(node.child(STR("a")).text().as_string(), STR("foo")); + CHECK_STRING(node.child(STR("a")).first_child().text().as_string(), STR("foo")); + + CHECK_STRING(node.child(STR("b")).text().as_string(), STR("bar")); + CHECK_STRING(node.child(STR("b")).last_child().text().as_string(), STR("bar")); + + CHECK_STRING(node.child(STR("c")).text().as_string(), STR("")); + CHECK_STRING(node.child(STR("c")).first_child().text().as_string(), STR("")); + + CHECK_STRING(node.child(STR("d")).text().as_string(), STR("")); + + CHECK_STRING(xml_node().text().as_string(), STR("")); +} + +TEST_XML(dom_text_as_int, "1-1-21474836482147483647") +{ + xml_node node = doc.child(STR("node")); + + CHECK(xml_text().as_int() == 0); + CHECK(node.child(STR("text1")).text().as_int() == 1); + CHECK(node.child(STR("text2")).text().as_int() == -1); + CHECK(node.child(STR("text3")).text().as_int() == -2147483647 - 1); + CHECK(node.child(STR("text4")).text().as_int() == 2147483647); +} + +TEST_XML(dom_text_as_uint, "0121474836474294967295") +{ + xml_node node = doc.child(STR("node")); + + CHECK(xml_text().as_uint() == 0); + CHECK(node.child(STR("text1")).text().as_uint() == 0); + CHECK(node.child(STR("text2")).text().as_uint() == 1); + CHECK(node.child(STR("text3")).text().as_uint() == 2147483647); + CHECK(node.child(STR("text4")).text().as_uint() == 4294967295u); +} + +TEST_XML(dom_text_as_float, "010.12-5.13e-43.14159265358979323846") +{ + xml_node node = doc.child(STR("node")); + + CHECK(xml_text().as_float() == 0); + CHECK_DOUBLE(node.child(STR("text1")).text().as_float(), 0); + CHECK_DOUBLE(node.child(STR("text2")).text().as_float(), 1); + CHECK_DOUBLE(node.child(STR("text3")).text().as_float(), 0.12); + CHECK_DOUBLE(node.child(STR("text4")).text().as_float(), -5.1); + CHECK_DOUBLE(node.child(STR("text5")).text().as_float(), 3e-4); + CHECK_DOUBLE(node.child(STR("text6")).text().as_float(), 3.14159265358979323846); +} + +TEST_XML(dom_text_as_double, "010.12-5.13e-43.14159265358979323846") +{ + xml_node node = doc.child(STR("node")); + + CHECK(xml_text().as_double() == 0); + CHECK_DOUBLE(node.child(STR("text1")).text().as_double(), 0); + CHECK_DOUBLE(node.child(STR("text2")).text().as_double(), 1); + CHECK_DOUBLE(node.child(STR("text3")).text().as_double(), 0.12); + CHECK_DOUBLE(node.child(STR("text4")).text().as_double(), -5.1); + CHECK_DOUBLE(node.child(STR("text5")).text().as_double(), 3e-4); + CHECK_DOUBLE(node.child(STR("text6")).text().as_double(), 3.14159265358979323846); +} + +TEST_XML(dom_text_as_bool, "01trueTrueYesyesfalse") +{ + xml_node node = doc.child(STR("node")); + + CHECK(!xml_text().as_bool()); + CHECK(!node.child(STR("text1")).text().as_bool()); + CHECK(node.child(STR("text2")).text().as_bool()); + CHECK(node.child(STR("text3")).text().as_bool()); + CHECK(node.child(STR("text4")).text().as_bool()); + CHECK(node.child(STR("text5")).text().as_bool()); + CHECK(node.child(STR("text6")).text().as_bool()); + CHECK(!node.child(STR("text7")).text().as_bool()); +} + +TEST_XML(dom_text_get_no_state, "") +{ + xml_node node = doc.child(STR("node")); + xml_text t = node.text(); + + CHECK(!t); + CHECK(t.get() && *t.get() == 0); + CHECK(!node.first_child()); + + node.append_child(node_pcdata); + + CHECK(t); + CHECK_STRING(t.get(), STR("")); + + node.first_child().set_value(STR("test")); + + CHECK(t); + CHECK_STRING(t.get(), STR("test")); +} + +TEST_XML(dom_text_set, "") +{ + xml_node node = doc.child(STR("node")); + xml_text t = node.text(); + + t.set(STR("")); + CHECK(node.first_child().type() == node_pcdata); + CHECK_NODE(node, STR("")); + + t.set(STR("boo")); + CHECK(node.first_child().type() == node_pcdata); + CHECK(node.first_child() == node.last_child()); + CHECK_NODE(node, STR("boo")); + + t.set(STR("foobarfoobar")); + CHECK(node.first_child().type() == node_pcdata); + CHECK(node.first_child() == node.last_child()); + CHECK_NODE(node, STR("foobarfoobar")); +} + +TEST_XML(dom_text_assign, "") +{ + xml_node node = doc.child(STR("node")); + + node.append_child(STR("text1")).text() = STR("v1"); + xml_text() = STR("v1"); + + node.append_child(STR("text2")).text() = -2147483647; + node.append_child(STR("text3")).text() = -2147483647 - 1; + xml_text() = -2147483647 - 1; + + node.append_child(STR("text4")).text() = 4294967295u; + node.append_child(STR("text5")).text() = 4294967294u; + xml_text() = 2147483647; + + node.append_child(STR("text6")).text() = 0.5; + xml_text() = 0.5; + + node.append_child(STR("text7")).text() = true; + xml_text() = true; + + CHECK_NODE(node, STR("v1-2147483647-2147483648429496729542949672940.5true")); +} + +TEST_XML(dom_text_set_value, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.append_child(STR("text1")).text().set(STR("v1"))); + CHECK(!xml_text().set(STR("v1"))); + + CHECK(node.append_child(STR("text2")).text().set(-2147483647)); + CHECK(node.append_child(STR("text3")).text().set(-2147483647 - 1)); + CHECK(!xml_text().set(-2147483647 - 1)); + + CHECK(node.append_child(STR("text4")).text().set(4294967295u)); + CHECK(node.append_child(STR("text5")).text().set(4294967294u)); + CHECK(!xml_text().set(2147483647)); + + CHECK(node.append_child(STR("text6")).text().set(0.5)); + CHECK(!xml_text().set(0.5)); + + CHECK(node.append_child(STR("text7")).text().set(true)); + CHECK(!xml_text().set(true)); + + CHECK_NODE(node, STR("v1-2147483647-2147483648429496729542949672940.5true")); +} + +TEST_XML(dom_text_middle, "notthisonetext") +{ + xml_node node = doc.child(STR("node")); + xml_text t = node.text(); + + CHECK_STRING(t.get(), STR("text")); + t.set(STR("notext")); + + CHECK_NODE(node, STR("notthisonenotext")); + CHECK(node.remove_child(t.data())); + + CHECK(!t); + CHECK_NODE(node, STR("notthisone")); + + t.set(STR("yestext")); + + CHECK(t); + CHECK_NODE(node, STR("notthisoneyestext")); + CHECK(t.data() == node.last_child()); +} + +TEST_XML_FLAGS(dom_text_data, "foo", parse_default | parse_pi) +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.child(STR("a")).text().data() == node.child(STR("a")).first_child()); + CHECK(node.child(STR("b")).text().data() == node.child(STR("b")).first_child()); + CHECK(!node.child(STR("c")).text().data()); + CHECK(!node.child(STR("d")).text().data()); + CHECK(!xml_text().data()); +} + +TEST(dom_text_defaults) +{ + xml_text text; + + CHECK_STRING(text.as_string(STR("foo")), STR("foo")); + CHECK(text.as_int(42) == 42); + CHECK(text.as_uint(42) == 42); + CHECK(text.as_double(42) == 42); + CHECK(text.as_float(42) == 42); + CHECK(text.as_bool(true) == true); +} diff --git a/tests/test_header_string_iostream.cpp b/tests/test_header_string_iostream.cpp index 1105626..3210080 100644 --- a/tests/test_header_string_iostream.cpp +++ b/tests/test_header_string_iostream.cpp @@ -1,5 +1,5 @@ -// Tests compatibility with string/iostream -#include -#include "../src/pugixml.hpp" -#include -#include +// Tests compatibility with string/iostream +#include +#include "../src/pugixml.hpp" +#include +#include diff --git a/tests/test_version.cpp b/tests/test_version.cpp index 6fbfe1b..4b8b99a 100644 --- a/tests/test_version.cpp +++ b/tests/test_version.cpp @@ -1,5 +1,5 @@ -#include "../src/pugixml.hpp" - -#if PUGIXML_VERSION != 120 -#error Unexpected pugixml version -#endif +#include "../src/pugixml.hpp" + +#if PUGIXML_VERSION != 120 +#error Unexpected pugixml version +#endif diff --git a/tests/test_xpath_variables.cpp b/tests/test_xpath_variables.cpp index 785a504..5480d0c 100644 --- a/tests/test_xpath_variables.cpp +++ b/tests/test_xpath_variables.cpp @@ -1,402 +1,402 @@ -#ifndef PUGIXML_NO_XPATH - -#include "common.hpp" - -#include - -TEST(xpath_variables_type_none) -{ - xpath_variable_set set; - - xpath_variable* var = set.add(STR("target"), xpath_type_none); - CHECK(!var); -} - -TEST(xpath_variables_type_boolean) -{ - xpath_variable_set set; - - xpath_variable* var = set.add(STR("target"), xpath_type_boolean); - CHECK(var); - - CHECK(var->type() == xpath_type_boolean); - CHECK_STRING(var->name(), STR("target")); - - CHECK(var->get_boolean() == false); - CHECK_DOUBLE_NAN(var->get_number()); - CHECK_STRING(var->get_string(), STR("")); - CHECK(var->get_node_set().empty()); - - CHECK(var->set(true)); - CHECK(!var->set(1.0)); - CHECK(!var->set(STR("abc"))); - CHECK(!var->set(xpath_node_set())); - - CHECK(var->get_boolean() == true); - CHECK_DOUBLE_NAN(var->get_number()); - CHECK_STRING(var->get_string(), STR("")); - CHECK(var->get_node_set().empty()); -} - -TEST(xpath_variables_type_number) -{ - xpath_variable_set set; - - xpath_variable* var = set.add(STR("target"), xpath_type_number); - CHECK(var); - - CHECK(var->type() == xpath_type_number); - CHECK_STRING(var->name(), STR("target")); - - CHECK(var->get_boolean() == false); - CHECK_DOUBLE(var->get_number(), 0); - CHECK_STRING(var->get_string(), STR("")); - CHECK(var->get_node_set().empty()); - - CHECK(!var->set(true)); - CHECK(var->set(1.0)); - CHECK(!var->set(STR("abc"))); - CHECK(!var->set(xpath_node_set())); - - CHECK(var->get_boolean() == false); - CHECK_DOUBLE(var->get_number(), 1); - CHECK_STRING(var->get_string(), STR("")); - CHECK(var->get_node_set().empty()); -} - -TEST(xpath_variables_type_string) -{ - xpath_variable_set set; - - xpath_variable* var = set.add(STR("target"), xpath_type_string); - CHECK(var); - - CHECK(var->type() == xpath_type_string); - CHECK_STRING(var->name(), STR("target")); - - CHECK(var->get_boolean() == false); - CHECK_DOUBLE_NAN(var->get_number()); - CHECK_STRING(var->get_string(), STR("")); - CHECK(var->get_node_set().empty()); - - CHECK(!var->set(true)); - CHECK(!var->set(1.0)); - CHECK(var->set(STR("abc"))); - CHECK(!var->set(xpath_node_set())); - - CHECK(var->get_boolean() == false); - CHECK_DOUBLE_NAN(var->get_number()); - CHECK_STRING(var->get_string(), STR("abc")); - CHECK(var->get_node_set().empty()); -} - -TEST_XML(xpath_variables_type_node_set, "") -{ - xpath_variable_set set; - - xpath_variable* var = set.add(STR("target"), xpath_type_node_set); - CHECK(var); - - CHECK(var->type() == xpath_type_node_set); - CHECK_STRING(var->name(), STR("target")); - - CHECK(var->get_boolean() == false); - CHECK_DOUBLE_NAN(var->get_number()); - CHECK_STRING(var->get_string(), STR("")); - CHECK(var->get_node_set().empty()); - - CHECK(!var->set(true)); - CHECK(!var->set(1.0)); - CHECK(!var->set(STR("abc"))); - CHECK(var->set(doc.select_nodes(STR("*")))); - - CHECK(var->get_boolean() == false); - CHECK_DOUBLE_NAN(var->get_number()); - CHECK_STRING(var->get_string(), STR("")); - CHECK(var->get_node_set().size() == 1 && var->get_node_set()[0] == doc.first_child()); -} - -TEST(xpath_variables_set_operations) -{ - xpath_variable_set set; - - xpath_variable* v1 = set.add(STR("var1"), xpath_type_number); - CHECK(v1); - - xpath_variable* v2 = set.add(STR("var2"), xpath_type_string); - CHECK(v2); - - CHECK(v1 != v2); - - CHECK(set.add(STR("var1"), xpath_type_number) == v1); - CHECK(set.add(STR("var2"), xpath_type_string) == v2); - CHECK(set.add(STR("var2"), xpath_type_node_set) == 0); - - CHECK(set.get(STR("var1")) == v1); - CHECK(set.get(STR("var2")) == v2); - CHECK(set.get(STR("var")) == 0); - CHECK(set.get(STR("var11")) == 0); - - CHECK(static_cast(set).get(STR("var1")) == v1); - CHECK(static_cast(set).get(STR("var3")) == 0); -} - -TEST_XML(xpath_variables_set_operations_set, "") -{ - xpath_variable_set set; - - xpath_variable* v1 = set.add(STR("var1"), xpath_type_number); - CHECK(v1); - - xpath_variable* v2 = set.add(STR("var2"), xpath_type_string); - CHECK(v2); - - CHECK(set.set(STR("var1"), 1.0)); - CHECK_DOUBLE(v1->get_number(), 1.0); - - CHECK(set.set(STR("var2"), STR("value"))); - CHECK_STRING(v2->get_string(), STR("value")); - - CHECK(!set.set(STR("var1"), true)); - - CHECK(set.set(STR("var3"), doc.select_nodes(STR("*")))); - - xpath_variable* v3 = set.get(STR("var3")); - - CHECK(v3); - CHECK(v3->type() == xpath_type_node_set); - CHECK(v3->get_node_set().size() == 1); -} - -TEST(xpath_variables_set_out_of_memory) -{ - test_runner::_memory_fail_threshold = 1; - - xpath_variable_set set; - - xpath_variable* var = set.add(STR("target"), xpath_type_number); - CHECK(!var); -} - -TEST(xpath_variables_out_of_memory) -{ - test_runner::_memory_fail_threshold = 64; - - xpath_variable_set set; - - xpath_variable* var = set.add(STR("target"), xpath_type_string); - CHECK(var); - - CHECK(!var->set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))); -} - -TEST_XML(xpath_variables_evaluate, "") -{ - xpath_variable_set set; - set.set(STR("var1"), true); - set.set(STR("var2"), 0.5); - set.set(STR("var3"), STR("value")); - set.set(STR("var4"), doc.select_nodes(STR("*"))); - - CHECK_XPATH_BOOLEAN_VAR(doc, STR("$var1"), &set, true); - CHECK_XPATH_NUMBER_VAR(doc, STR("$var2"), &set, 0.5); - CHECK_XPATH_STRING_VAR(doc, STR("$var3"), &set, STR("value")); - CHECK_XPATH_NODESET_VAR(doc, STR("$var4"), &set) % 2; -} - -TEST_XML(xpath_variables_evaluate_conversion, "3") -{ - xpath_variable_set set; - set.set(STR("var"), doc.select_nodes(STR("*"))); - - CHECK_XPATH_BOOLEAN_VAR(doc, STR("$var"), &set, true); - CHECK_XPATH_NUMBER_VAR(doc, STR("$var"), &set, 3); - CHECK_XPATH_STRING_VAR(doc, STR("$var"), &set, STR("3")); - CHECK_XPATH_NODESET_VAR(doc, STR("$var"), &set) % 2; -} - -TEST(xpath_variables_evaluate_node_set_fail) -{ - xpath_variable_set set; - set.set(STR("var"), false); - - xpath_query q(STR("$var"), &set); - -#ifdef PUGIXML_NO_EXCEPTIONS - CHECK(q.evaluate_node_set(xml_node()).empty()); -#else - try - { - q.evaluate_node_set(xml_node()); - - CHECK_FORCE_FAIL("Expected exception"); - } - catch (const xpath_exception&) - { - } -#endif -} - -TEST(xpath_variables_multiple_documents) -{ - xml_document doc; - doc.append_child().set_name(STR("node")); - - xml_document doc1; - doc1.append_child().set_name(STR("node")); - - xml_document doc2; - doc2.append_child().set_name(STR("node")); - - xpath_variable_set set; - set.set(STR("var1"), doc1.select_nodes(STR("*"))); - set.set(STR("var2"), doc2.select_nodes(STR("*"))); - - xpath_node_set ns = doc.select_nodes(STR("$var1 | $var2 | node"), &set); - ns.sort(); - - CHECK(ns.size() == 3); - CHECK(ns[0] != ns[1] && ns[0] != ns[2]); - - xml_node n0 = doc.child(STR("node")), n1 = doc1.child(STR("node")), n2 = doc2.child(STR("node")); - - CHECK(n0 == ns[0].node() || n0 == ns[1].node() || n0 == ns[2].node()); - CHECK(n1 == ns[0].node() || n1 == ns[1].node() || n1 == ns[2].node()); - CHECK(n2 == ns[0].node() || n2 == ns[1].node() || n2 == ns[2].node()); -} - -TEST(xpath_variables_long_name) -{ - xpath_variable_set set; - set.set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), true); - - CHECK_XPATH_BOOLEAN_VAR(xml_node(), STR("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), &set, true); -} - -TEST_XML(xpath_variables_select, "") -{ - xpath_variable_set set; - set.set(STR("one"), 1.0); - - xpath_node_set ns = doc.select_nodes(STR("node[@attr=$one+1]"), &set); - CHECK(ns.size() == 1 && ns[0].node() == doc.last_child()); - - xpath_node n = doc.select_single_node(STR("node[@attr=$one+1]"), &set); - CHECK(n == ns[0]); -} - -TEST(xpath_variables_empty_name) -{ - xpath_variable_set set; - CHECK(!set.add(STR(""), xpath_type_number)); -} - -TEST_XML(xpath_variables_inside_filter, "") -{ - xpath_variable_set set; - set.set(STR("one"), 1.0); - - xpath_node_set ns = doc.select_nodes(STR("(node[@key = $one])[@value = $one]"), &set); - CHECK(ns.size() == 1 && ns[0].node() == doc.last_child()); -} - -TEST_XML(xpath_variables_step, "") -{ - xpath_variable_set set; - set.set(STR("root"), doc.select_nodes(STR("node"))); - - CHECK_XPATH_NODESET_VAR(xml_node(), STR("$root/child"), &set) % 3 % 4 % 5; - CHECK_XPATH_NODESET_VAR(xml_node(), STR("$root//child"), &set) % 3 % 4 % 5 % 6; -} - -TEST_XML(xpath_variables_index, "") -{ - xpath_variable_set set; - set.set(STR("index"), 2.0); - - CHECK_XPATH_NODESET_VAR(doc, STR("node/child[$index]"), &set) % 4; - CHECK_XPATH_NODESET_VAR(doc, STR("node/child[position()=$index]"), &set) % 4; -} - -TEST(xpath_variables_qname) -{ - xpath_variable_set set; - set.set(STR("foo:bar"), true); - - CHECK_XPATH_BOOLEAN_VAR(xml_node(), STR("$foo:bar"), &set, true); -} - -TEST(xpath_variables_name_error) -{ - xpath_variable_set set; - set.set(STR("foo:"), true); - set.set(STR(":bar"), true); - set.set(STR("foo:*"), true); - set.set(STR("foo"), true); - set.set(STR("3"), true); - - CHECK_XPATH_FAIL_VAR(STR("$foo:"), &set); - CHECK_XPATH_FAIL_VAR(STR("$:bar"), &set); - CHECK_XPATH_FAIL_VAR(STR("$foo:*"), &set); - CHECK_XPATH_FAIL_VAR(STR("$foo:bar:baz"), &set); - CHECK_XPATH_FAIL_VAR(STR("$ foo"), &set); - - CHECK_XPATH_FAIL_VAR(STR("$3"), &set); -} - -TEST(xpath_variables_empty_string) -{ - xpath_variable_set set; - set.add(STR("empty"), xpath_type_string); - - CHECK_XPATH_BOOLEAN_VAR(xml_node(), STR("$empty = substring-before('a', 'z')"), &set, true); -} - -TEST(xpath_variables_name_underscore) -{ - xpath_variable_set set; - set.set(STR("_foo_bar"), true); - - CHECK_XPATH_BOOLEAN_VAR(xml_node(), STR("$_foo_bar"), &set, true); -} - -TEST(xpath_variables_name_case) -{ - xpath_variable_set set; - set.set(STR("i"), 5.0); - set.set(STR("I"), 2.0); - - CHECK_XPATH_NUMBER_VAR(xml_node(), STR("$i div $I"), &set, 2.5); -} - -TEST(xpath_variables_name_unicode) -{ -#ifdef PUGIXML_WCHAR_MODE - #ifdef U_LITERALS - const char_t* name = L"\u0400\u203D"; - #else - const char_t* name = L"\x0400\x203D"; - #endif -#else - const char_t* name = "\xd0\x80\xe2\x80\xbd"; -#endif - - xpath_variable_set set; - set.set(name, STR("value")); - - std::basic_string var = STR("$"); - var += name; - - CHECK_XPATH_STRING_VAR(xml_node(), var.c_str(), &set, STR("value")); -} - -TEST_XML(xpath_variables_count_sum, "122334") -{ - xpath_variable_set set; - set.set(STR("c12"), doc.select_nodes(STR("node/c1 | node/c2"))); - set.set(STR("c3"), doc.select_nodes(STR("node/c3"))); - set.set(STR("c"), doc.select_nodes(STR("node/*"))); - - CHECK_XPATH_NUMBER_VAR(xml_node(), STR("sum($c12) * count($c) - sum($c3)"), &set, 71); -} -#endif +#ifndef PUGIXML_NO_XPATH + +#include "common.hpp" + +#include + +TEST(xpath_variables_type_none) +{ + xpath_variable_set set; + + xpath_variable* var = set.add(STR("target"), xpath_type_none); + CHECK(!var); +} + +TEST(xpath_variables_type_boolean) +{ + xpath_variable_set set; + + xpath_variable* var = set.add(STR("target"), xpath_type_boolean); + CHECK(var); + + CHECK(var->type() == xpath_type_boolean); + CHECK_STRING(var->name(), STR("target")); + + CHECK(var->get_boolean() == false); + CHECK_DOUBLE_NAN(var->get_number()); + CHECK_STRING(var->get_string(), STR("")); + CHECK(var->get_node_set().empty()); + + CHECK(var->set(true)); + CHECK(!var->set(1.0)); + CHECK(!var->set(STR("abc"))); + CHECK(!var->set(xpath_node_set())); + + CHECK(var->get_boolean() == true); + CHECK_DOUBLE_NAN(var->get_number()); + CHECK_STRING(var->get_string(), STR("")); + CHECK(var->get_node_set().empty()); +} + +TEST(xpath_variables_type_number) +{ + xpath_variable_set set; + + xpath_variable* var = set.add(STR("target"), xpath_type_number); + CHECK(var); + + CHECK(var->type() == xpath_type_number); + CHECK_STRING(var->name(), STR("target")); + + CHECK(var->get_boolean() == false); + CHECK_DOUBLE(var->get_number(), 0); + CHECK_STRING(var->get_string(), STR("")); + CHECK(var->get_node_set().empty()); + + CHECK(!var->set(true)); + CHECK(var->set(1.0)); + CHECK(!var->set(STR("abc"))); + CHECK(!var->set(xpath_node_set())); + + CHECK(var->get_boolean() == false); + CHECK_DOUBLE(var->get_number(), 1); + CHECK_STRING(var->get_string(), STR("")); + CHECK(var->get_node_set().empty()); +} + +TEST(xpath_variables_type_string) +{ + xpath_variable_set set; + + xpath_variable* var = set.add(STR("target"), xpath_type_string); + CHECK(var); + + CHECK(var->type() == xpath_type_string); + CHECK_STRING(var->name(), STR("target")); + + CHECK(var->get_boolean() == false); + CHECK_DOUBLE_NAN(var->get_number()); + CHECK_STRING(var->get_string(), STR("")); + CHECK(var->get_node_set().empty()); + + CHECK(!var->set(true)); + CHECK(!var->set(1.0)); + CHECK(var->set(STR("abc"))); + CHECK(!var->set(xpath_node_set())); + + CHECK(var->get_boolean() == false); + CHECK_DOUBLE_NAN(var->get_number()); + CHECK_STRING(var->get_string(), STR("abc")); + CHECK(var->get_node_set().empty()); +} + +TEST_XML(xpath_variables_type_node_set, "") +{ + xpath_variable_set set; + + xpath_variable* var = set.add(STR("target"), xpath_type_node_set); + CHECK(var); + + CHECK(var->type() == xpath_type_node_set); + CHECK_STRING(var->name(), STR("target")); + + CHECK(var->get_boolean() == false); + CHECK_DOUBLE_NAN(var->get_number()); + CHECK_STRING(var->get_string(), STR("")); + CHECK(var->get_node_set().empty()); + + CHECK(!var->set(true)); + CHECK(!var->set(1.0)); + CHECK(!var->set(STR("abc"))); + CHECK(var->set(doc.select_nodes(STR("*")))); + + CHECK(var->get_boolean() == false); + CHECK_DOUBLE_NAN(var->get_number()); + CHECK_STRING(var->get_string(), STR("")); + CHECK(var->get_node_set().size() == 1 && var->get_node_set()[0] == doc.first_child()); +} + +TEST(xpath_variables_set_operations) +{ + xpath_variable_set set; + + xpath_variable* v1 = set.add(STR("var1"), xpath_type_number); + CHECK(v1); + + xpath_variable* v2 = set.add(STR("var2"), xpath_type_string); + CHECK(v2); + + CHECK(v1 != v2); + + CHECK(set.add(STR("var1"), xpath_type_number) == v1); + CHECK(set.add(STR("var2"), xpath_type_string) == v2); + CHECK(set.add(STR("var2"), xpath_type_node_set) == 0); + + CHECK(set.get(STR("var1")) == v1); + CHECK(set.get(STR("var2")) == v2); + CHECK(set.get(STR("var")) == 0); + CHECK(set.get(STR("var11")) == 0); + + CHECK(static_cast(set).get(STR("var1")) == v1); + CHECK(static_cast(set).get(STR("var3")) == 0); +} + +TEST_XML(xpath_variables_set_operations_set, "") +{ + xpath_variable_set set; + + xpath_variable* v1 = set.add(STR("var1"), xpath_type_number); + CHECK(v1); + + xpath_variable* v2 = set.add(STR("var2"), xpath_type_string); + CHECK(v2); + + CHECK(set.set(STR("var1"), 1.0)); + CHECK_DOUBLE(v1->get_number(), 1.0); + + CHECK(set.set(STR("var2"), STR("value"))); + CHECK_STRING(v2->get_string(), STR("value")); + + CHECK(!set.set(STR("var1"), true)); + + CHECK(set.set(STR("var3"), doc.select_nodes(STR("*")))); + + xpath_variable* v3 = set.get(STR("var3")); + + CHECK(v3); + CHECK(v3->type() == xpath_type_node_set); + CHECK(v3->get_node_set().size() == 1); +} + +TEST(xpath_variables_set_out_of_memory) +{ + test_runner::_memory_fail_threshold = 1; + + xpath_variable_set set; + + xpath_variable* var = set.add(STR("target"), xpath_type_number); + CHECK(!var); +} + +TEST(xpath_variables_out_of_memory) +{ + test_runner::_memory_fail_threshold = 64; + + xpath_variable_set set; + + xpath_variable* var = set.add(STR("target"), xpath_type_string); + CHECK(var); + + CHECK(!var->set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))); +} + +TEST_XML(xpath_variables_evaluate, "") +{ + xpath_variable_set set; + set.set(STR("var1"), true); + set.set(STR("var2"), 0.5); + set.set(STR("var3"), STR("value")); + set.set(STR("var4"), doc.select_nodes(STR("*"))); + + CHECK_XPATH_BOOLEAN_VAR(doc, STR("$var1"), &set, true); + CHECK_XPATH_NUMBER_VAR(doc, STR("$var2"), &set, 0.5); + CHECK_XPATH_STRING_VAR(doc, STR("$var3"), &set, STR("value")); + CHECK_XPATH_NODESET_VAR(doc, STR("$var4"), &set) % 2; +} + +TEST_XML(xpath_variables_evaluate_conversion, "3") +{ + xpath_variable_set set; + set.set(STR("var"), doc.select_nodes(STR("*"))); + + CHECK_XPATH_BOOLEAN_VAR(doc, STR("$var"), &set, true); + CHECK_XPATH_NUMBER_VAR(doc, STR("$var"), &set, 3); + CHECK_XPATH_STRING_VAR(doc, STR("$var"), &set, STR("3")); + CHECK_XPATH_NODESET_VAR(doc, STR("$var"), &set) % 2; +} + +TEST(xpath_variables_evaluate_node_set_fail) +{ + xpath_variable_set set; + set.set(STR("var"), false); + + xpath_query q(STR("$var"), &set); + +#ifdef PUGIXML_NO_EXCEPTIONS + CHECK(q.evaluate_node_set(xml_node()).empty()); +#else + try + { + q.evaluate_node_set(xml_node()); + + CHECK_FORCE_FAIL("Expected exception"); + } + catch (const xpath_exception&) + { + } +#endif +} + +TEST(xpath_variables_multiple_documents) +{ + xml_document doc; + doc.append_child().set_name(STR("node")); + + xml_document doc1; + doc1.append_child().set_name(STR("node")); + + xml_document doc2; + doc2.append_child().set_name(STR("node")); + + xpath_variable_set set; + set.set(STR("var1"), doc1.select_nodes(STR("*"))); + set.set(STR("var2"), doc2.select_nodes(STR("*"))); + + xpath_node_set ns = doc.select_nodes(STR("$var1 | $var2 | node"), &set); + ns.sort(); + + CHECK(ns.size() == 3); + CHECK(ns[0] != ns[1] && ns[0] != ns[2]); + + xml_node n0 = doc.child(STR("node")), n1 = doc1.child(STR("node")), n2 = doc2.child(STR("node")); + + CHECK(n0 == ns[0].node() || n0 == ns[1].node() || n0 == ns[2].node()); + CHECK(n1 == ns[0].node() || n1 == ns[1].node() || n1 == ns[2].node()); + CHECK(n2 == ns[0].node() || n2 == ns[1].node() || n2 == ns[2].node()); +} + +TEST(xpath_variables_long_name) +{ + xpath_variable_set set; + set.set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), true); + + CHECK_XPATH_BOOLEAN_VAR(xml_node(), STR("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), &set, true); +} + +TEST_XML(xpath_variables_select, "") +{ + xpath_variable_set set; + set.set(STR("one"), 1.0); + + xpath_node_set ns = doc.select_nodes(STR("node[@attr=$one+1]"), &set); + CHECK(ns.size() == 1 && ns[0].node() == doc.last_child()); + + xpath_node n = doc.select_single_node(STR("node[@attr=$one+1]"), &set); + CHECK(n == ns[0]); +} + +TEST(xpath_variables_empty_name) +{ + xpath_variable_set set; + CHECK(!set.add(STR(""), xpath_type_number)); +} + +TEST_XML(xpath_variables_inside_filter, "") +{ + xpath_variable_set set; + set.set(STR("one"), 1.0); + + xpath_node_set ns = doc.select_nodes(STR("(node[@key = $one])[@value = $one]"), &set); + CHECK(ns.size() == 1 && ns[0].node() == doc.last_child()); +} + +TEST_XML(xpath_variables_step, "") +{ + xpath_variable_set set; + set.set(STR("root"), doc.select_nodes(STR("node"))); + + CHECK_XPATH_NODESET_VAR(xml_node(), STR("$root/child"), &set) % 3 % 4 % 5; + CHECK_XPATH_NODESET_VAR(xml_node(), STR("$root//child"), &set) % 3 % 4 % 5 % 6; +} + +TEST_XML(xpath_variables_index, "") +{ + xpath_variable_set set; + set.set(STR("index"), 2.0); + + CHECK_XPATH_NODESET_VAR(doc, STR("node/child[$index]"), &set) % 4; + CHECK_XPATH_NODESET_VAR(doc, STR("node/child[position()=$index]"), &set) % 4; +} + +TEST(xpath_variables_qname) +{ + xpath_variable_set set; + set.set(STR("foo:bar"), true); + + CHECK_XPATH_BOOLEAN_VAR(xml_node(), STR("$foo:bar"), &set, true); +} + +TEST(xpath_variables_name_error) +{ + xpath_variable_set set; + set.set(STR("foo:"), true); + set.set(STR(":bar"), true); + set.set(STR("foo:*"), true); + set.set(STR("foo"), true); + set.set(STR("3"), true); + + CHECK_XPATH_FAIL_VAR(STR("$foo:"), &set); + CHECK_XPATH_FAIL_VAR(STR("$:bar"), &set); + CHECK_XPATH_FAIL_VAR(STR("$foo:*"), &set); + CHECK_XPATH_FAIL_VAR(STR("$foo:bar:baz"), &set); + CHECK_XPATH_FAIL_VAR(STR("$ foo"), &set); + + CHECK_XPATH_FAIL_VAR(STR("$3"), &set); +} + +TEST(xpath_variables_empty_string) +{ + xpath_variable_set set; + set.add(STR("empty"), xpath_type_string); + + CHECK_XPATH_BOOLEAN_VAR(xml_node(), STR("$empty = substring-before('a', 'z')"), &set, true); +} + +TEST(xpath_variables_name_underscore) +{ + xpath_variable_set set; + set.set(STR("_foo_bar"), true); + + CHECK_XPATH_BOOLEAN_VAR(xml_node(), STR("$_foo_bar"), &set, true); +} + +TEST(xpath_variables_name_case) +{ + xpath_variable_set set; + set.set(STR("i"), 5.0); + set.set(STR("I"), 2.0); + + CHECK_XPATH_NUMBER_VAR(xml_node(), STR("$i div $I"), &set, 2.5); +} + +TEST(xpath_variables_name_unicode) +{ +#ifdef PUGIXML_WCHAR_MODE + #ifdef U_LITERALS + const char_t* name = L"\u0400\u203D"; + #else + const char_t* name = L"\x0400\x203D"; + #endif +#else + const char_t* name = "\xd0\x80\xe2\x80\xbd"; +#endif + + xpath_variable_set set; + set.set(name, STR("value")); + + std::basic_string var = STR("$"); + var += name; + + CHECK_XPATH_STRING_VAR(xml_node(), var.c_str(), &set, STR("value")); +} + +TEST_XML(xpath_variables_count_sum, "122334") +{ + xpath_variable_set set; + set.set(STR("c12"), doc.select_nodes(STR("node/c1 | node/c2"))); + set.set(STR("c3"), doc.select_nodes(STR("node/c3"))); + set.set(STR("c"), doc.select_nodes(STR("node/*"))); + + CHECK_XPATH_NUMBER_VAR(xml_node(), STR("sum($c12) * count($c) - sum($c3)"), &set, 71); +} +#endif