diff options
-rw-r--r-- | src/pugixml.cpp | 180 |
1 files changed, 99 insertions, 81 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index c0a2980..0cbf088 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -276,11 +276,13 @@ PUGI__NS_BEGIN static const uintptr_t xml_memory_page_alignment = 64; static const uintptr_t xml_memory_page_pointer_mask = ~(xml_memory_page_alignment - 1); static const uintptr_t xml_memory_page_contents_shared_mask = 32; + static const uintptr_t xml_memory_page_contents_allocated_mask = 16; static const uintptr_t xml_memory_page_name_allocated_mask = 16; static const uintptr_t xml_memory_page_value_allocated_mask = 8; static const uintptr_t xml_memory_page_type_mask = 7; static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask; static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask; + static const uintptr_t xml_memory_page_contents_allocated_or_shared_mask = xml_memory_page_contents_allocated_mask | xml_memory_page_contents_shared_mask; #define PUGI__NODETYPE(n) static_cast<xml_node_type>(((n)->header & impl::xml_memory_page_type_mask) + 1) @@ -812,7 +814,7 @@ PUGI__NS_BEGIN template <int header_offset, int tag> class compact_string { public: - compact_string(): _data(0) + compact_string(): _data0(0), _data1(0), _data2(0) { } @@ -831,35 +833,49 @@ PUGI__NS_BEGIN { page->compact_string_base = value; - _data = 1; + _data0 = 1; + _data1 = 0; + _data2 = 0; } else { ptrdiff_t offset = value - page->compact_string_base; - if (offset >= 0 && offset <= 65533) - _data = static_cast<unsigned short>(offset + 1); + if (offset >= 0 && offset <= 1677213) + { + _data0 = static_cast<unsigned char>(offset + 1); + _data1 = static_cast<unsigned char>((offset + 1) >> 8); + _data2 = static_cast<unsigned char>((offset + 1) >> 16); + } else { *page->allocator->_hash->insert(this, tag) = value; - _data = 65535; + _data0 = 255; + _data1 = 255; + _data2 = 255; } } } else - _data = 0; + { + _data0 = 0; + _data1 = 0; + _data2 = 0; + } } operator char_t* const() const { - if (_data) + unsigned int data = _data0 + (_data1 << 8) + (_data2 << 16); + + if (data) { xml_memory_page* page = compact_get_page(this, header_offset); - if (_data < 65535) + if (data < 16777215) { - return page->compact_string_base + (_data - 1); + return page->compact_string_base + (data - 1); } else { @@ -876,7 +892,9 @@ PUGI__NS_BEGIN } private: - unsigned short _data; + unsigned char _data0; + unsigned char _data1; + unsigned char _data2; }; PUGI__NS_END @@ -898,10 +916,10 @@ namespace pugi impl::compact_header header; - unsigned char padding[3]; + unsigned char padding; - impl::compact_string<6, /*tag*/11> name; ///< Pointer to attribute name. - impl::compact_string<8, /*tag*/12> value; ///< Pointer to attribute value. + impl::compact_string<4, /*tag*/11> name; ///< Pointer to attribute name. + impl::compact_string<7, /*tag*/12> value; ///< Pointer to attribute value. impl::compact_pointer<xml_attribute_struct, 10, 0, /*tag*/13> prev_attribute_c; ///< Previous attribute (cyclic list) impl::compact_pointer<xml_attribute_struct, 11, +1, /*tag*/14> next_attribute; ///< Next attribute @@ -921,17 +939,18 @@ namespace pugi impl::compact_header header; - impl::compact_pointer<xml_node_struct, 3, -1, /*tag*/23> parent; ///< Pointer to parent + unsigned char padding; - impl::compact_string<4, /*tag*/21> name; ///< Pointer to element name. - impl::compact_string<6, /*tag*/22> value; ///< Pointer to any associated string data. + impl::compact_string<4, /*tag*/21> contents; ///< Pointer to element name. - impl::compact_pointer<xml_node_struct, 8, +1, /*tag*/24> first_child; ///< First child + impl::compact_pointer<xml_node_struct, 7, -1, /*tag*/22> parent; ///< Pointer to parent - impl::compact_pointer<xml_node_struct, 9, 0, /*tag*/25> prev_sibling_c; ///< Left brother (cyclic list) - impl::compact_pointer<xml_node_struct, 10, +1, /*tag*/26> next_sibling; ///< Right brother + impl::compact_pointer<xml_node_struct, 8, +1, /*tag*/23> first_child; ///< First child - impl::compact_pointer<xml_attribute_struct, 11, +1, /*tag*/27> first_attribute; ///< First attribute + impl::compact_pointer<xml_node_struct, 9, 0, /*tag*/24> prev_sibling_c; ///< Left brother (cyclic list) + impl::compact_pointer<xml_node_struct, 10, +1, /*tag*/25> next_sibling; ///< Right brother + + impl::compact_pointer<xml_attribute_struct, 11, +1, /*tag*/26> first_attribute; ///< First attribute }; } #else @@ -959,7 +978,7 @@ namespace pugi { /// Default ctor /// \param type - node type - xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(reinterpret_cast<uintptr_t>(page) | (type - 1)), parent(0), name(0), value(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) + xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(reinterpret_cast<uintptr_t>(page) | (type - 1)), parent(0), contents(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) { } @@ -967,8 +986,7 @@ namespace pugi xml_node_struct* parent; ///< Pointer to parent - char_t* name; ///< Pointer to element name. - char_t* value; ///< Pointer to any associated string data. + char_t* contents; ///< Pointer to element name/value xml_node_struct* first_child; ///< First child @@ -1052,8 +1070,7 @@ PUGI__NS_BEGIN { uintptr_t header = n->header; - if (header & impl::xml_memory_page_name_allocated_mask) alloc.deallocate_string(n->name); - if (header & impl::xml_memory_page_value_allocated_mask) alloc.deallocate_string(n->value); + if (header & impl::xml_memory_page_contents_allocated_mask) alloc.deallocate_string(n->contents); for (xml_attribute_struct* attr = n->first_attribute; attr; ) { @@ -2827,14 +2844,14 @@ PUGI__NS_BEGIN if (PUGI__OPTSET(parse_comments)) { PUGI__PUSHNODE(node_comment); // Append a new node on the tree. - cursor->value = s; // Save the offset. + cursor->contents = s; // Save the offset. } if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments)) { s = strconv_comment(s, endch); - if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value); + if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->contents); } else { @@ -2860,13 +2877,13 @@ PUGI__NS_BEGIN if (PUGI__OPTSET(parse_cdata)) { PUGI__PUSHNODE(node_cdata); // Append a new node on the tree. - cursor->value = s; // Save the offset. + cursor->contents = s; // Save the offset. if (PUGI__OPTSET(parse_eol)) { s = strconv_cdata(s, endch); - if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value); + if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->contents); } else { @@ -2910,7 +2927,7 @@ PUGI__NS_BEGIN PUGI__PUSHNODE(node_doctype); - cursor->value = mark; + cursor->contents = mark; PUGI__POPNODE(); } @@ -2956,7 +2973,7 @@ PUGI__NS_BEGIN PUGI__PUSHNODE(node_pi); } - cursor->name = target; + cursor->contents = target; PUGI__ENDSEG(); @@ -2990,7 +3007,7 @@ PUGI__NS_BEGIN else { // store value and step over > - cursor->value = value; + // TODO: node_pi value:cursor->value = value; PUGI__POPNODE(); PUGI__ENDSEG(); @@ -3035,7 +3052,7 @@ PUGI__NS_BEGIN { PUGI__PUSHNODE(node_element); // Append a new node to the tree. - cursor->name = s; + cursor->contents = s; PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. @@ -3149,7 +3166,7 @@ PUGI__NS_BEGIN { ++s; - char_t* name = cursor->name; + char_t* name = cursor->contents; if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, s); while (PUGI__IS_CHARTYPE(*s, ct_symbol)) @@ -3220,7 +3237,7 @@ PUGI__NS_BEGIN if (cursor->parent || PUGI__OPTSET(parse_fragment)) { PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. - cursor->value = s; // Save the offset. + cursor->contents = s; // Save the offset. s = strconv_pcdata(s); @@ -4088,8 +4105,7 @@ PUGI__NS_BEGIN PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc) { - node_copy_string(dn->name, dn->header, xml_memory_page_name_allocated_mask, sn->name, sn->header, shared_alloc); - node_copy_string(dn->value, dn->header, xml_memory_page_value_allocated_mask, sn->value, sn->header, shared_alloc); + node_copy_string(dn->contents, dn->header, xml_memory_page_contents_allocated_mask, sn->contents, sn->header, shared_alloc); for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute) { @@ -4680,6 +4696,20 @@ PUGI__NS_BEGIN return res; } + + inline bool has_name(xml_node_struct* node) + { + static const bool result[] = { false, false, true, false, false, false, true, true, false }; + + return result[PUGI__NODETYPE(node)]; + } + + inline bool has_value(xml_node_struct* node) + { + static const bool result[] = { false, false, false, true, true, true, false, false, true }; + + return result[PUGI__NODETYPE(node)]; + } PUGI__NS_END namespace pugi @@ -5080,7 +5110,7 @@ namespace pugi PUGI__FN const char_t* xml_node::name() const { - return (_root && _root->name) ? _root->name : PUGIXML_TEXT(""); + return (_root && impl::has_name(_root) && _root->contents) ? _root->contents : PUGIXML_TEXT(""); } PUGI__FN xml_node_type xml_node::type() const @@ -5090,7 +5120,7 @@ namespace pugi PUGI__FN const char_t* xml_node::value() const { - return (_root && _root->value) ? _root->value : PUGIXML_TEXT(""); + return (_root && impl::has_value(_root) && _root->contents) ? _root->contents : PUGIXML_TEXT(""); } PUGI__FN xml_node xml_node::child(const char_t* name_) const @@ -5098,7 +5128,7 @@ namespace pugi if (!_root) return xml_node(); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + if (impl::has_name(i) && i->contents && impl::strequal(name_, i->contents)) return xml_node(i); return xml_node(); } @@ -5119,7 +5149,7 @@ namespace pugi if (!_root) return xml_node(); for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + if (impl::has_name(i) && i->contents && impl::strequal(name_, i->contents)) return xml_node(i); return xml_node(); } @@ -5134,7 +5164,7 @@ namespace pugi if (!_root) return xml_node(); for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + if (impl::has_name(i) && i->contents && impl::strequal(name_, i->contents)) return xml_node(i); return xml_node(); } @@ -5171,8 +5201,8 @@ namespace pugi if (!_root) return PUGIXML_TEXT(""); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->value && impl::is_text_node(i)) - return i->value; + if (impl::has_value(i) && i->contents && impl::is_text_node(i)) + return i->contents; return PUGIXML_TEXT(""); } @@ -5209,7 +5239,7 @@ namespace pugi case node_pi: case node_declaration: case node_element: - return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs); + return impl::strcpy_insitu(_root->contents, _root->header, impl::xml_memory_page_contents_allocated_mask, rhs); default: return false; @@ -5225,7 +5255,7 @@ namespace pugi case node_pcdata: case node_comment: case node_doctype: - return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs); + return impl::strcpy_insitu(_root->contents, _root->header, impl::xml_memory_page_contents_allocated_mask, rhs); default: return false; @@ -5613,15 +5643,15 @@ namespace pugi if (!extra) return impl::make_parse_result(status_out_of_memory); // save name; name of the root has to be NULL before parsing - otherwise closing node mismatches will not be detected at the top level - char_t* rootname = _root->name; - _root->name = 0; + char_t* rootname = _root->contents; + _root->contents = 0; // parse char_t* buffer = 0; xml_parse_result res = impl::load_buffer_impl(doc, _root, const_cast<void*>(contents), size, options, encoding, false, false, &buffer); // restore name - _root->name = rootname; + _root->contents = rootname; // add extra buffer to the list extra->buffer = buffer; @@ -5636,7 +5666,7 @@ namespace pugi if (!_root) return xml_node(); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) + if (impl::has_name(i) && i->contents && impl::strequal(name_, i->contents)) { for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value : PUGIXML_TEXT(""))) @@ -5714,7 +5744,7 @@ namespace pugi { for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling) { - if (j->name && impl::strequalrange(j->name, path_segment, static_cast<size_t>(path_segment_end - path_segment))) + if (impl::has_name(j) && j->contents && impl::strequalrange(j->contents, path_segment, static_cast<size_t>(path_segment_end - path_segment))) { xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); @@ -5824,19 +5854,8 @@ namespace pugi case node_document: return 0; - case node_element: - case node_declaration: - case node_pi: - return (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) ? -1 : _root->name - buffer; - - case node_pcdata: - case node_cdata: - case node_comment: - case node_doctype: - return (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) ? -1 : _root->value - buffer; - default: - return -1; + return (_root->header & impl::xml_memory_page_contents_allocated_or_shared_mask) ? -1 : _root->contents - buffer; } } @@ -5902,49 +5921,49 @@ namespace pugi { xml_node_struct* d = _data(); - return (d && d->value) ? d->value : PUGIXML_TEXT(""); + return (d && d->contents) ? d->contents : PUGIXML_TEXT(""); } PUGI__FN const char_t* xml_text::as_string(const char_t* def) const { xml_node_struct* d = _data(); - return (d && d->value) ? d->value : def; + return (d && d->contents) ? d->contents : def; } PUGI__FN int xml_text::as_int(int def) const { xml_node_struct* d = _data(); - return impl::get_value_int(d ? PUGI__COMPACT(d->value) : 0, def); + return impl::get_value_int(d ? PUGI__COMPACT(d->contents) : 0, def); } PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const { xml_node_struct* d = _data(); - return impl::get_value_uint(d ? PUGI__COMPACT(d->value) : 0, def); + return impl::get_value_uint(d ? PUGI__COMPACT(d->contents) : 0, def); } PUGI__FN double xml_text::as_double(double def) const { xml_node_struct* d = _data(); - return impl::get_value_double(d ? PUGI__COMPACT(d->value) : 0, def); + return impl::get_value_double(d ? PUGI__COMPACT(d->contents) : 0, def); } PUGI__FN float xml_text::as_float(float def) const { xml_node_struct* d = _data(); - return impl::get_value_float(d ? PUGI__COMPACT(d->value) : 0, def); + return impl::get_value_float(d ? PUGI__COMPACT(d->contents) : 0, def); } PUGI__FN bool xml_text::as_bool(bool def) const { xml_node_struct* d = _data(); - return impl::get_value_bool(d ? PUGI__COMPACT(d->value) : 0, def); + return impl::get_value_bool(d ? PUGI__COMPACT(d->contents) : 0, def); } #ifdef PUGIXML_HAS_LONG_LONG @@ -5952,14 +5971,14 @@ namespace pugi { xml_node_struct* d = _data(); - return impl::get_value_llong(d ? PUGI__COMPACT(d->value) : 0, def); + return impl::get_value_llong(d ? PUGI__COMPACT(d->contents) : 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 ? PUGI__COMPACT(d->value) : 0, def); + return impl::get_value_ullong(d ? PUGI__COMPACT(d->contents) : 0, def); } #endif @@ -5967,35 +5986,35 @@ namespace pugi { xml_node_struct* dn = _data_new(); - return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + return dn ? impl::strcpy_insitu(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; } PUGI__FN bool xml_text::set(int 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; + return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; } PUGI__FN bool xml_text::set(unsigned int 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; + return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; } PUGI__FN bool xml_text::set(double 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; + return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; } PUGI__FN bool xml_text::set(bool 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; + return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; } #ifdef PUGIXML_HAS_LONG_LONG @@ -6003,14 +6022,14 @@ namespace pugi { 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; + return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_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; + return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; } #endif @@ -7358,8 +7377,7 @@ PUGI__NS_BEGIN { if ((get_document(node).header & xml_memory_page_contents_shared_mask) == 0) { - if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return node->name; - if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return node->value; + if (node->contents && (node->header & impl::xml_memory_page_contents_allocated_or_shared_mask) == 0) return node->contents; } return 0; |