From f9bbc39bd9a14124c1cba696c99d051a39e34b60 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sat, 8 Feb 2014 20:36:09 +0000 Subject: Implement long long support if PUGIXML_HAS_LONG_LONG is defined (autodetection is not implemented yet) git-svn-id: http://pugixml.googlecode.com/svn/trunk@962 99668b35-9821-0410-8761-19e4c4f06640 --- src/pugixml.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++++ src/pugixml.hpp | 30 ++++++++++ tests/test_dom_modify.cpp | 34 ++++++++++- tests/test_dom_text.cpp | 91 +++++++++++++++++++++++++++++- tests/test_dom_traverse.cpp | 55 ++++++++++++++++++ 5 files changed, 341 insertions(+), 3 deletions(-) diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 78fe50a..874d611 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -3386,6 +3386,34 @@ PUGI__NS_BEGIN return (first == '1' || first == 't' || first == 'T' || first == 'y' || first == 'Y'); } +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long get_value_llong(const char_t* value, long long def) + { + if (!value) return def; + + int base = get_integer_base(value); + + #ifdef PUGIXML_WCHAR_MODE + return wcstoll(value, 0, base); + #else + return strtoll(value, 0, base); + #endif + } + + PUGI__FN unsigned long long get_value_ullong(const char_t* value, unsigned long long def) + { + if (!value) return def; + + int base = get_integer_base(value); + + #ifdef PUGIXML_WCHAR_MODE + return wcstoull(value, 0, base); + #else + return strtoull(value, 0, base); + #endif + } +#endif + // set value with conversion functions PUGI__FN bool set_value_buffer(char_t*& dest, uintptr_t& header, uintptr_t header_mask, char (&buf)[128]) { @@ -3428,6 +3456,24 @@ PUGI__NS_BEGIN return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); } +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, long long value) + { + char buf[128]; + sprintf(buf, "%lld", value); + + return set_value_buffer(dest, header, header_mask, buf); + } + + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, unsigned long long value) + { + char buf[128]; + sprintf(buf, "%llu", value); + + return set_value_buffer(dest, header, header_mask, buf); + } +#endif + // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) { @@ -3891,6 +3937,18 @@ namespace pugi return impl::get_value_bool(_attr ? _attr->value : 0, def); } +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long xml_attribute::as_llong(long long def) const + { + return impl::get_value_llong(_attr ? _attr->value : 0, def); + } + + PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const + { + return impl::get_value_ullong(_attr ? _attr->value : 0, def); + } +#endif + PUGI__FN bool xml_attribute::empty() const { return !_attr; @@ -3946,6 +4004,20 @@ namespace pugi return *this; } +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long long rhs) + { + set_value(rhs); + return *this; + } +#endif + PUGI__FN bool xml_attribute::set_name(const char_t* rhs) { if (!_attr) return false; @@ -3988,6 +4060,22 @@ namespace pugi return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); } +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN bool xml_attribute::set_value(long long rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + + PUGI__FN bool xml_attribute::set_value(unsigned long long rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } +#endif + #ifdef __BORLANDC__ PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs) { @@ -4936,6 +5024,22 @@ namespace pugi return impl::get_value_bool(d ? d->value : 0, def); } +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long xml_text::as_llong(long long def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_llong(d ? d->value : 0, def); + } + + PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_ullong(d ? d->value : 0, def); + } +#endif + PUGI__FN bool xml_text::set(const char_t* rhs) { xml_node_struct* dn = _data_new(); @@ -4971,6 +5075,22 @@ namespace pugi return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; } +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN bool xml_text::set(long long rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + + PUGI__FN bool xml_text::set(unsigned long long rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } +#endif + PUGI__FN xml_text& xml_text::operator=(const char_t* rhs) { set(rhs); @@ -5001,6 +5121,20 @@ namespace pugi return *this; } +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN xml_text& xml_text::operator=(long long rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(unsigned long long rhs) + { + set(rhs); + return *this; + } +#endif + PUGI__FN xml_node xml_text::data() const { return xml_node(_data()); diff --git a/src/pugixml.hpp b/src/pugixml.hpp index db1507a..ae43fd2 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -320,6 +320,11 @@ namespace pugi double as_double(double def = 0) const; float as_float(float def = 0) const; + #ifdef PUGIXML_HAS_LONG_LONG + long long as_llong(long long def = 0) const; + unsigned long long as_ullong(unsigned long long def = 0) const; + #endif + // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty bool as_bool(bool def = false) const; @@ -333,6 +338,11 @@ namespace pugi bool set_value(double rhs); bool set_value(bool rhs); + #ifdef PUGIXML_HAS_LONG_LONG + bool set_value(long long rhs); + bool set_value(unsigned long long rhs); + #endif + // Set attribute value (equivalent to set_value without error checking) xml_attribute& operator=(const char_t* rhs); xml_attribute& operator=(int rhs); @@ -340,6 +350,11 @@ namespace pugi xml_attribute& operator=(double rhs); xml_attribute& operator=(bool rhs); + #ifdef PUGIXML_HAS_LONG_LONG + xml_attribute& operator=(long long rhs); + xml_attribute& operator=(unsigned long long rhs); + #endif + // Get next/previous attribute in the attribute list of the parent node xml_attribute next_attribute() const; xml_attribute previous_attribute() const; @@ -637,6 +652,11 @@ namespace pugi double as_double(double def = 0) const; float as_float(float def = 0) const; + #ifdef PUGIXML_HAS_LONG_LONG + long long as_llong(long long def = 0) const; + unsigned long long as_ullong(unsigned long long def = 0) const; + #endif + // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty bool as_bool(bool def = false) const; @@ -649,6 +669,11 @@ namespace pugi bool set(double rhs); bool set(bool rhs); + #ifdef PUGIXML_HAS_LONG_LONG + bool set(long long rhs); + bool set(unsigned long long rhs); + #endif + // Set text (equivalent to set without error checking) xml_text& operator=(const char_t* rhs); xml_text& operator=(int rhs); @@ -656,6 +681,11 @@ namespace pugi xml_text& operator=(double rhs); xml_text& operator=(bool rhs); + #ifdef PUGIXML_HAS_LONG_LONG + xml_text& operator=(long long rhs); + xml_text& operator=(unsigned long long rhs); + #endif + // Get the data node (node_pcdata or node_cdata) for this object xml_node data() const; }; diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index 620504a..c7a3989 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -15,7 +15,7 @@ TEST_XML(dom_attr_assign, "") node.append_attribute(STR("attr4")) = 4294967295u; node.append_attribute(STR("attr5")) = 4294967294u; - xml_attribute() = 2147483647; + xml_attribute() = 4294967295u; node.append_attribute(STR("attr6")) = 0.5; xml_attribute() = 0.5; @@ -50,6 +50,38 @@ TEST_XML(dom_attr_set_value, "") CHECK_NODE(node, STR("")); } +#ifdef PUGIXML_HAS_LONG_LONG +TEST_XML(dom_attr_assign_llong, "") +{ + xml_node node = doc.child(STR("node")); + + node.append_attribute(STR("attr1")) = -9223372036854775807ll; + node.append_attribute(STR("attr2")) = -9223372036854775807ll - 1; + xml_attribute() = -9223372036854775807ll - 1; + + node.append_attribute(STR("attr3")) = 18446744073709551615ull; + node.append_attribute(STR("attr4")) = 18446744073709551614ull; + xml_attribute() = 18446744073709551615ull; + + CHECK_NODE(node, STR("")); +} + +TEST_XML(dom_attr_set_value_llong, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.append_attribute(STR("attr1")).set_value(-9223372036854775807ll)); + CHECK(node.append_attribute(STR("attr2")).set_value(-9223372036854775807ll - 1)); + CHECK(!xml_attribute().set_value(-9223372036854775807ll - 1)); + + CHECK(node.append_attribute(STR("attr3")).set_value(18446744073709551615ull)); + CHECK(node.append_attribute(STR("attr4")).set_value(18446744073709551614ull)); + CHECK(!xml_attribute().set_value(18446744073709551615ull)); + + CHECK_NODE(node, STR("")); +} +#endif + TEST_XML(dom_node_set_name, "text") { CHECK(doc.child(STR("node")).set_name(STR("n"))); diff --git a/tests/test_dom_text.cpp b/tests/test_dom_text.cpp index 2e38f29..fb65b03 100644 --- a/tests/test_dom_text.cpp +++ b/tests/test_dom_text.cpp @@ -155,6 +155,56 @@ TEST_XML(dom_text_as_bool, "01true1-1-922337203685477580892233720368547758070") +{ + xml_node node = doc.child(STR("node")); + + CHECK(xml_text().as_llong() == 0); + CHECK(node.child(STR("text1")).text().as_llong() == 1); + CHECK(node.child(STR("text2")).text().as_llong() == -1); + CHECK(node.child(STR("text3")).text().as_llong() == -9223372036854775807ll - 1); + CHECK(node.child(STR("text4")).text().as_llong() == 9223372036854775807ll); + CHECK(node.child(STR("text5")).text().as_llong() == 0); +} + +TEST_XML(dom_text_as_llong_hex, "07770x5ab0XFf-0x20-0x80000000000000000x") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.child(STR("text1")).text().as_llong() == 777); // no octal support! intentional + CHECK(node.child(STR("text2")).text().as_llong() == 1451); + CHECK(node.child(STR("text3")).text().as_llong() == 255); + CHECK(node.child(STR("text4")).text().as_llong() == -32); + CHECK(node.child(STR("text5")).text().as_llong() == -9223372036854775807ll - 1); + CHECK(node.child(STR("text6")).text().as_llong() == 0); +} + +TEST_XML(dom_text_as_ullong, "019223372036854775807184467440737095516150") +{ + xml_node node = doc.child(STR("node")); + + CHECK(xml_text().as_ullong() == 0); + CHECK(node.child(STR("text1")).text().as_ullong() == 0); + CHECK(node.child(STR("text2")).text().as_ullong() == 1); + CHECK(node.child(STR("text3")).text().as_ullong() == 9223372036854775807ll); + CHECK(node.child(STR("text4")).text().as_ullong() == 18446744073709551615ull); + CHECK(node.child(STR("text5")).text().as_ullong() == 0); +} + +TEST_XML(dom_text_as_ullong_hex, "07770x5ab0XFf0x200xFFFFFFFFFFFFFFFF0x") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.child(STR("text1")).text().as_ullong() == 777); // no octal support! intentional + CHECK(node.child(STR("text2")).text().as_ullong() == 1451); + CHECK(node.child(STR("text3")).text().as_ullong() == 255); + CHECK(node.child(STR("text4")).text().as_ullong() == 32); + CHECK(node.child(STR("text5")).text().as_ullong() == 18446744073709551615ull); + CHECK(node.child(STR("text6")).text().as_ullong() == 0); +} +#endif + TEST_XML(dom_text_get_no_state, "") { xml_node node = doc.child(STR("node")); @@ -208,7 +258,7 @@ TEST_XML(dom_text_assign, "") node.append_child(STR("text4")).text() = 4294967295u; node.append_child(STR("text5")).text() = 4294967294u; - xml_text() = 2147483647; + xml_text() = 4294967295u; node.append_child(STR("text6")).text() = 0.5; xml_text() = 0.5; @@ -232,7 +282,7 @@ TEST_XML(dom_text_set_value, "") CHECK(node.append_child(STR("text4")).text().set(4294967295u)); CHECK(node.append_child(STR("text5")).text().set(4294967294u)); - CHECK(!xml_text().set(2147483647)); + CHECK(!xml_text().set(4294967295u)); CHECK(node.append_child(STR("text6")).text().set(0.5)); CHECK(!xml_text().set(0.5)); @@ -243,6 +293,38 @@ TEST_XML(dom_text_set_value, "") CHECK_NODE(node, STR("v1-2147483647-2147483648429496729542949672940.5true")); } +#ifdef PUGIXML_HAS_LONG_LONG +TEST_XML(dom_text_assign_llong, "") +{ + xml_node node = doc.child(STR("node")); + + node.append_child(STR("text1")).text() = -9223372036854775807ll; + node.append_child(STR("text2")).text() = -9223372036854775807ll - 1; + xml_text() = -9223372036854775807ll - 1; + + node.append_child(STR("text3")).text() = 18446744073709551615ull; + node.append_child(STR("text4")).text() = 18446744073709551614ull; + xml_text() = 18446744073709551615ull; + + CHECK_NODE(node, STR("-9223372036854775807-92233720368547758081844674407370955161518446744073709551614")); +} + +TEST_XML(dom_text_set_value_llong, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.append_child(STR("text1")).text().set(-9223372036854775807ll)); + CHECK(node.append_child(STR("text2")).text().set(-9223372036854775807ll - 1)); + CHECK(!xml_text().set(-9223372036854775807ll - 1)); + + CHECK(node.append_child(STR("text3")).text().set(18446744073709551615ull)); + CHECK(node.append_child(STR("text4")).text().set(18446744073709551614ull)); + CHECK(!xml_text().set(18446744073709551615ull)); + + CHECK_NODE(node, STR("-9223372036854775807-92233720368547758081844674407370955161518446744073709551614")); +} +#endif + TEST_XML(dom_text_middle, "notthisonetext") { xml_node node = doc.child(STR("node")); @@ -285,4 +367,9 @@ TEST(dom_text_defaults) CHECK(text.as_double(42) == 42); CHECK(text.as_float(42) == 42); CHECK(text.as_bool(true) == true); + +#ifdef PUGIXML_HAS_LONG_LONG + CHECK(text.as_llong(42) == 42); + CHECK(text.as_ullong(42) == 42); +#endif } diff --git a/tests/test_dom_traverse.cpp b/tests/test_dom_traverse.cpp index 9c7c9ec..43fec80 100644 --- a/tests/test_dom_traverse.cpp +++ b/tests/test_dom_traverse.cpp @@ -179,6 +179,56 @@ TEST_XML(dom_attr_as_bool, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(xml_attribute().as_llong() == 0); + CHECK(node.attribute(STR("attr1")).as_llong() == 1); + CHECK(node.attribute(STR("attr2")).as_llong() == -1); + CHECK(node.attribute(STR("attr3")).as_llong() == -9223372036854775807ll - 1); + CHECK(node.attribute(STR("attr4")).as_llong() == 9223372036854775807ll); + CHECK(node.attribute(STR("attr5")).as_llong() == 0); +} + +TEST_XML(dom_attr_as_llong_hex, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_llong() == 777); // no octal support! intentional + CHECK(node.attribute(STR("attr2")).as_llong() == 1451); + CHECK(node.attribute(STR("attr3")).as_llong() == 255); + CHECK(node.attribute(STR("attr4")).as_llong() == -32); + CHECK(node.attribute(STR("attr5")).as_llong() == -9223372036854775807ll - 1); + CHECK(node.attribute(STR("attr6")).as_llong() == 0); +} + +TEST_XML(dom_attr_as_ullong, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(xml_attribute().as_ullong() == 0); + CHECK(node.attribute(STR("attr1")).as_ullong() == 0); + CHECK(node.attribute(STR("attr2")).as_ullong() == 1); + CHECK(node.attribute(STR("attr3")).as_ullong() == 9223372036854775807ull); + CHECK(node.attribute(STR("attr4")).as_ullong() == 18446744073709551615ull); + CHECK(node.attribute(STR("attr5")).as_ullong() == 0); +} + +TEST_XML(dom_attr_as_ullong_hex, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_ullong() == 777); // no octal support! intentional + CHECK(node.attribute(STR("attr2")).as_ullong() == 1451); + CHECK(node.attribute(STR("attr3")).as_ullong() == 255); + CHECK(node.attribute(STR("attr4")).as_ullong() == 32); + CHECK(node.attribute(STR("attr5")).as_ullong() == 18446744073709551615ull); + CHECK(node.attribute(STR("attr6")).as_ullong() == 0); +} +#endif + TEST(dom_attr_defaults) { xml_attribute attr; @@ -189,6 +239,11 @@ TEST(dom_attr_defaults) CHECK(attr.as_double(42) == 42); CHECK(attr.as_float(42) == 42); CHECK(attr.as_bool(true) == true); + +#ifdef PUGIXML_HAS_LONG_LONG + CHECK(attr.as_llong(42) == 42); + CHECK(attr.as_ullong(42) == 42); +#endif } TEST_XML(dom_attr_iterator, "") -- cgit v1.2.3