Revert to name/value storage inside node

This temporarily increases the node size to 16 bytes - we'll bring it back.

It allows us to remove the horrible node_pi hack and to reduce the amount of
changes against master. This comes at the price of not decreasing basline
xml_node_struct size.

The compact xml_node_struct is also increased by this change but a followup
change will reduce *both* xml_attribute_struct and xml_node_struct (to 8/12
bytes).
This commit is contained in:
Arseny Kapoulkine 2015-05-01 20:03:17 -07:00
parent dede617d9f
commit bc5eb22b71

View File

@ -409,22 +409,18 @@ PUGI__NS_BEGIN
#endif #endif
; ;
static const uintptr_t xml_memory_page_alignment = 32; 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_pointer_mask = ~(xml_memory_page_alignment - 1);
// extra metadata bits for xml_node_struct // extra metadata bits
static const uintptr_t xml_memory_page_contents_shared_mask = 16; static const uintptr_t xml_memory_page_contents_shared_mask = 32;
static const uintptr_t xml_memory_page_contents_allocated_mask = 8; 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_type_mask = 7;
// extra metadata bits for xml_attribute_struct
static const uintptr_t xml_memory_page_name_allocated_mask = 2;
static const uintptr_t xml_memory_page_value_allocated_mask = 1;
// combined masks for string uniqueness // combined masks for string uniqueness
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_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_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;
// all allocated blocks have a certain guaranteed alignment // all allocated blocks have a certain guaranteed alignment
static const uintptr_t xml_memory_block_alignment = static const uintptr_t xml_memory_block_alignment =
@ -989,34 +985,24 @@ namespace pugi
{ {
xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type - 1) xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type - 1)
{ {
PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 12); PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 16);
} }
impl::compact_header header; impl::compact_header header;
impl::compact_string<3> contents; impl::compact_string<3> name;
impl::compact_string<6> value;
impl::compact_pointer_parent<xml_node_struct, 6> parent; unsigned char padding;
impl::compact_pointer<xml_node_struct, 8, 0> first_child; impl::compact_pointer_parent<xml_node_struct, 10> parent;
impl::compact_pointer<xml_node_struct, 9> prev_sibling_c; impl::compact_pointer<xml_node_struct, 12, 0> first_child;
impl::compact_pointer<xml_node_struct, 10, 0> next_sibling;
impl::compact_pointer<xml_attribute_struct, 11, 0> first_attribute; impl::compact_pointer<xml_node_struct, 13> prev_sibling_c;
}; impl::compact_pointer<xml_node_struct, 14, 0> next_sibling;
struct xml_node_pi_struct: xml_node_struct impl::compact_pointer<xml_attribute_struct, 15, 0> first_attribute;
{
xml_node_pi_struct(impl::xml_memory_page* page): xml_node_struct(page, node_pi), pi_header(page, 0)
{
PUGI__STATIC_ASSERT(sizeof(xml_node_pi_struct) == 20);
}
impl::compact_header pi_header;
impl::compact_string<3> pi_value;
unsigned char padding[2];
}; };
} }
#else #else
@ -1039,13 +1025,14 @@ namespace pugi
struct xml_node_struct struct xml_node_struct
{ {
xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(reinterpret_cast<uintptr_t>(page) | (type - 1)), contents(0), parent(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)), name(0), value(0), parent(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0)
{ {
} }
uintptr_t header; uintptr_t header;
char_t* contents; char_t* name;
char_t* value;
xml_node_struct* parent; xml_node_struct* parent;
@ -1056,16 +1043,6 @@ namespace pugi
xml_attribute_struct* first_attribute; xml_attribute_struct* first_attribute;
}; };
struct xml_node_pi_struct: xml_node_struct
{
xml_node_pi_struct(impl::xml_memory_page* page): xml_node_struct(page, node_pi), pi_header(reinterpret_cast<uintptr_t>(page)), pi_value(0)
{
}
uintptr_t pi_header;
char_t* pi_value;
};
} }
#endif #endif
@ -1121,20 +1098,10 @@ PUGI__NS_BEGIN
inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type) inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type)
{ {
if (type != node_pi) xml_memory_page* page;
{ void* memory = alloc.allocate_memory(sizeof(xml_node_struct), page);
xml_memory_page* page;
void* memory = alloc.allocate_memory(sizeof(xml_node_struct), page);
return new (memory) xml_node_struct(page, type); return new (memory) xml_node_struct(page, type);
}
else
{
xml_memory_page* page;
void* memory = alloc.allocate_memory(sizeof(xml_node_pi_struct), page);
return new (memory) xml_node_pi_struct(page);
}
} }
inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc) inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc)
@ -1150,16 +1117,11 @@ PUGI__NS_BEGIN
inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) inline void destroy_node(xml_node_struct* n, xml_allocator& alloc)
{ {
if (n->header & impl::xml_memory_page_contents_allocated_mask) if (n->header & impl::xml_memory_page_name_allocated_mask)
alloc.deallocate_string(n->contents); alloc.deallocate_string(n->name);
if (PUGI__NODETYPE(n) == node_pi) if (n->header & impl::xml_memory_page_value_allocated_mask)
{ alloc.deallocate_string(n->value);
xml_node_pi_struct* pn = static_cast<xml_node_pi_struct*>(n);
if (pn->pi_header & impl::xml_memory_page_contents_allocated_mask)
alloc.deallocate_string(pn->pi_value);
}
for (xml_attribute_struct* attr = n->first_attribute; attr; ) for (xml_attribute_struct* attr = n->first_attribute; attr; )
{ {
@ -3016,14 +2978,14 @@ PUGI__NS_BEGIN
if (PUGI__OPTSET(parse_comments)) if (PUGI__OPTSET(parse_comments))
{ {
PUGI__PUSHNODE(node_comment); // Append a new node on the tree. PUGI__PUSHNODE(node_comment); // Append a new node on the tree.
cursor->contents = s; // Save the offset. cursor->value = s; // Save the offset.
} }
if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments)) if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments))
{ {
s = strconv_comment(s, endch); s = strconv_comment(s, endch);
if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->contents); if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value);
} }
else else
{ {
@ -3049,13 +3011,13 @@ PUGI__NS_BEGIN
if (PUGI__OPTSET(parse_cdata)) if (PUGI__OPTSET(parse_cdata))
{ {
PUGI__PUSHNODE(node_cdata); // Append a new node on the tree. PUGI__PUSHNODE(node_cdata); // Append a new node on the tree.
cursor->contents = s; // Save the offset. cursor->value = s; // Save the offset.
if (PUGI__OPTSET(parse_eol)) if (PUGI__OPTSET(parse_eol))
{ {
s = strconv_cdata(s, endch); s = strconv_cdata(s, endch);
if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->contents); if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value);
} }
else else
{ {
@ -3099,7 +3061,7 @@ PUGI__NS_BEGIN
PUGI__PUSHNODE(node_doctype); PUGI__PUSHNODE(node_doctype);
cursor->contents = mark; cursor->value = mark;
} }
} }
else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s); else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s);
@ -3143,7 +3105,7 @@ PUGI__NS_BEGIN
PUGI__PUSHNODE(node_pi); PUGI__PUSHNODE(node_pi);
} }
cursor->contents = target; cursor->name = target;
PUGI__ENDSEG(); PUGI__ENDSEG();
@ -3177,7 +3139,7 @@ PUGI__NS_BEGIN
else else
{ {
// store value and step over > // store value and step over >
static_cast<xml_node_pi_struct*>(cursor)->pi_value = value; cursor->value = value;
PUGI__POPNODE(); PUGI__POPNODE();
@ -3223,7 +3185,7 @@ PUGI__NS_BEGIN
{ {
PUGI__PUSHNODE(node_element); // Append a new node to the tree. PUGI__PUSHNODE(node_element); // Append a new node to the tree.
cursor->contents = s; cursor->name = s;
PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator.
PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. PUGI__ENDSEG(); // Save char in 'ch', terminate & step over.
@ -3333,7 +3295,7 @@ PUGI__NS_BEGIN
{ {
++s; ++s;
char_t* name = cursor->contents; char_t* name = cursor->name;
if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, s); if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, s);
while (PUGI__IS_CHARTYPE(*s, ct_symbol)) while (PUGI__IS_CHARTYPE(*s, ct_symbol))
@ -3404,7 +3366,7 @@ PUGI__NS_BEGIN
if (cursor->parent || PUGI__OPTSET(parse_fragment)) if (cursor->parent || PUGI__OPTSET(parse_fragment))
{ {
PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree.
cursor->contents = s; // Save the offset. cursor->value = s; // Save the offset.
s = strconv_pcdata(s); s = strconv_pcdata(s);
@ -4067,7 +4029,7 @@ PUGI__NS_BEGIN
PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth)
{ {
const char_t* default_name = PUGIXML_TEXT(":anonymous"); const char_t* default_name = PUGIXML_TEXT(":anonymous");
const char_t* name = node->contents ? node->contents : default_name; const char_t* name = node->name ? node->name : default_name;
writer.write('<'); writer.write('<');
writer.write_string(name); writer.write_string(name);
@ -4092,7 +4054,7 @@ PUGI__NS_BEGIN
PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node) PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node)
{ {
const char_t* default_name = PUGIXML_TEXT(":anonymous"); const char_t* default_name = PUGIXML_TEXT(":anonymous");
const char_t* name = node->contents ? node->contents : default_name; const char_t* name = node->name ? node->name : default_name;
writer.write('<', '/'); writer.write('<', '/');
writer.write_string(name); writer.write_string(name);
@ -4106,25 +4068,25 @@ PUGI__NS_BEGIN
switch (PUGI__NODETYPE(node)) switch (PUGI__NODETYPE(node))
{ {
case node_pcdata: case node_pcdata:
text_output(writer, node->contents ? node->contents + 0 : PUGIXML_TEXT(""), ctx_special_pcdata, flags); text_output(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""), ctx_special_pcdata, flags);
break; break;
case node_cdata: case node_cdata:
text_output_cdata(writer, node->contents ? node->contents + 0 : PUGIXML_TEXT("")); text_output_cdata(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""));
break; break;
case node_comment: case node_comment:
node_output_comment(writer, node->contents ? node->contents + 0 : PUGIXML_TEXT("")); node_output_comment(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""));
break; break;
case node_pi: case node_pi:
writer.write('<', '?'); writer.write('<', '?');
writer.write_string(node->contents ? node->contents : default_name); writer.write_string(node->name ? node->name : default_name);
if (static_cast<xml_node_pi_struct*>(node)->pi_value) if (node->value)
{ {
writer.write(' '); writer.write(' ');
node_output_pi_value(writer, static_cast<xml_node_pi_struct*>(node)->pi_value); node_output_pi_value(writer, node->value);
} }
writer.write('?', '>'); writer.write('?', '>');
@ -4132,7 +4094,7 @@ PUGI__NS_BEGIN
case node_declaration: case node_declaration:
writer.write('<', '?'); writer.write('<', '?');
writer.write_string(node->contents ? node->contents : default_name); writer.write_string(node->name ? node->name : default_name);
node_output_attributes(writer, node, PUGIXML_TEXT(""), 0, flags | format_raw, 0); node_output_attributes(writer, node, PUGIXML_TEXT(""), 0, flags | format_raw, 0);
writer.write('?', '>'); writer.write('?', '>');
break; break;
@ -4141,10 +4103,10 @@ PUGI__NS_BEGIN
writer.write('<', '!', 'D', 'O', 'C'); writer.write('<', '!', 'D', 'O', 'C');
writer.write('T', 'Y', 'P', 'E'); writer.write('T', 'Y', 'P', 'E');
if (node->contents) if (node->value)
{ {
writer.write(' '); writer.write(' ');
writer.write_string(node->contents); writer.write_string(node->value);
} }
writer.write('>'); writer.write('>');
@ -4332,15 +4294,8 @@ PUGI__NS_BEGIN
PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc) PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc)
{ {
node_copy_string(dn->contents, dn->header, xml_memory_page_contents_allocated_mask, sn->contents, sn->header, 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);
if (PUGI__NODETYPE(dn) == node_pi)
{
xml_node_pi_struct* dnp = static_cast<xml_node_pi_struct*>(dn);
xml_node_pi_struct* snp = static_cast<xml_node_pi_struct*>(sn);
node_copy_string(dnp->pi_value, dnp->pi_header, xml_memory_page_contents_allocated_mask, snp->pi_value, snp->pi_header, shared_alloc);
}
for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute) for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute)
{ {
@ -4939,20 +4894,6 @@ PUGI__NS_BEGIN
return res; 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 PUGI__NS_END
namespace pugi namespace pugi
@ -5366,7 +5307,7 @@ namespace pugi
PUGI__FN const char_t* xml_node::name() const PUGI__FN const char_t* xml_node::name() const
{ {
return (_root && impl::has_name(_root) && _root->contents) ? _root->contents + 0 : PUGIXML_TEXT(""); return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT("");
} }
PUGI__FN xml_node_type xml_node::type() const PUGI__FN xml_node_type xml_node::type() const
@ -5376,15 +5317,7 @@ namespace pugi
PUGI__FN const char_t* xml_node::value() const PUGI__FN const char_t* xml_node::value() const
{ {
if (!_root) return PUGIXML_TEXT(""); return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT("");
if (impl::has_value(_root) && _root->contents)
return _root->contents;
if (PUGI__NODETYPE(_root) == node_pi && static_cast<xml_node_pi_struct*>(_root)->pi_value)
return static_cast<xml_node_pi_struct*>(_root)->pi_value;
return PUGIXML_TEXT("");
} }
PUGI__FN xml_node xml_node::child(const char_t* name_) const PUGI__FN xml_node xml_node::child(const char_t* name_) const
@ -5392,7 +5325,7 @@ namespace pugi
if (!_root) return xml_node(); if (!_root) return xml_node();
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
if (impl::has_name(i) && i->contents && impl::strequal(name_, i->contents)) return xml_node(i); if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
return xml_node(); return xml_node();
} }
@ -5413,7 +5346,7 @@ namespace pugi
if (!_root) return xml_node(); if (!_root) return xml_node();
for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
if (impl::has_name(i) && i->contents && impl::strequal(name_, i->contents)) return xml_node(i); if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
return xml_node(); return xml_node();
} }
@ -5428,7 +5361,7 @@ namespace pugi
if (!_root) return xml_node(); if (!_root) return xml_node();
for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
if (impl::has_name(i) && i->contents && impl::strequal(name_, i->contents)) return xml_node(i); if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
return xml_node(); return xml_node();
} }
@ -5461,8 +5394,8 @@ namespace pugi
if (!_root) return PUGIXML_TEXT(""); if (!_root) return PUGIXML_TEXT("");
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
if (impl::is_text_node(i) && i->contents) if (impl::is_text_node(i) && i->value)
return i->contents; return i->value;
return PUGIXML_TEXT(""); return PUGIXML_TEXT("");
} }
@ -5494,29 +5427,22 @@ namespace pugi
PUGI__FN bool xml_node::set_name(const char_t* rhs) PUGI__FN bool xml_node::set_name(const char_t* rhs)
{ {
if (!_root) return false; static const bool has_name[] = { false, false, true, false, false, false, true, true, false };
if (impl::has_name(_root)) if (!_root || !has_name[PUGI__NODETYPE(_root)])
return impl::strcpy_insitu(_root->contents, _root->header, impl::xml_memory_page_contents_allocated_mask, rhs); return false;
return false; return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs);
} }
PUGI__FN bool xml_node::set_value(const char_t* rhs) PUGI__FN bool xml_node::set_value(const char_t* rhs)
{ {
if (!_root) return false; static const bool has_value[] = { false, false, false, true, true, true, true, false, true };
if (impl::has_value(_root)) if (!_root || !has_value[PUGI__NODETYPE(_root)])
return impl::strcpy_insitu(_root->contents, _root->header, impl::xml_memory_page_contents_allocated_mask, rhs); return false;
if (PUGI__NODETYPE(_root) == node_pi) return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs);
{
xml_node_pi_struct* pn = static_cast<xml_node_pi_struct*>(_root);
return impl::strcpy_insitu(pn->pi_value, pn->pi_header, impl::xml_memory_page_contents_allocated_mask, rhs);
}
return false;
} }
PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_)
@ -5969,12 +5895,12 @@ namespace pugi
xml_node_struct* node; xml_node_struct* node;
char_t* name; char_t* name;
~name_sentry() { node->contents = name; } ~name_sentry() { node->name = name; }
}; };
name_sentry sentry = { _root, _root->contents }; name_sentry sentry = { _root, _root->name };
sentry.node->contents = 0; sentry.node->name = 0;
return impl::load_buffer_impl(doc, _root, const_cast<void*>(contents), size, options, encoding, false, false, &extra->buffer); return impl::load_buffer_impl(doc, _root, const_cast<void*>(contents), size, options, encoding, false, false, &extra->buffer);
} }
@ -5984,7 +5910,7 @@ namespace pugi
if (!_root) return xml_node(); if (!_root) return xml_node();
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
if (impl::has_name(i) && i->contents && impl::strequal(name_, i->contents)) if (i->name && impl::strequal(name_, i->name))
{ {
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) 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 + 0 : PUGIXML_TEXT(""))) if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
@ -6016,7 +5942,7 @@ namespace pugi
for (xml_node_struct* i = _root; i; i = i->parent) for (xml_node_struct* i = _root; i; i = i->parent)
{ {
offset += (i != _root); offset += (i != _root);
offset += (impl::has_name(i) && i->contents) ? impl::strlength(i->contents) : 0; offset += i->name ? impl::strlength(i->name) : 0;
} }
string_t result; string_t result;
@ -6027,12 +5953,12 @@ namespace pugi
if (j != _root) if (j != _root)
result[--offset] = delimiter; result[--offset] = delimiter;
if (impl::has_name(j) && j->contents && *j->contents) if (j->name && *j->name)
{ {
size_t length = impl::strlength(j->contents); size_t length = impl::strlength(j->name);
offset -= length; offset -= length;
memcpy(&result[offset], j->contents, length * sizeof(char_t)); memcpy(&result[offset], j->name, length * sizeof(char_t));
} }
} }
@ -6077,7 +6003,7 @@ namespace pugi
{ {
for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling) for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling)
{ {
if (impl::has_name(j) && j->contents && impl::strequalrange(j->contents, path_segment, static_cast<size_t>(path_segment_end - path_segment))) if (j->name && impl::strequalrange(j->name, path_segment, static_cast<size_t>(path_segment_end - path_segment)))
{ {
xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter);
@ -6188,10 +6114,13 @@ namespace pugi
// we need contents to be inside buffer and not shared // we need contents to be inside buffer and not shared
// if it's shared we don't know if this is the original node // if it's shared we don't know if this is the original node
if (!_root->contents) return -1; if (_root->name && (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0)
if (_root->header & impl::xml_memory_page_contents_allocated_or_shared_mask) return -1; return _root->name - doc.buffer;
return _root->contents - doc.buffer; if (_root->value && (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0)
return _root->value - doc.buffer;
return -1;
} }
#ifdef __BORLANDC__ #ifdef __BORLANDC__
@ -6256,49 +6185,49 @@ namespace pugi
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return (d && d->contents) ? d->contents + 0 : PUGIXML_TEXT(""); return (d && d->value) ? d->value + 0 : PUGIXML_TEXT("");
} }
PUGI__FN const char_t* xml_text::as_string(const char_t* def) const PUGI__FN const char_t* xml_text::as_string(const char_t* def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return (d && d->contents) ? d->contents : def; return (d && d->value) ? d->value : def;
} }
PUGI__FN int xml_text::as_int(int def) const PUGI__FN int xml_text::as_int(int def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return impl::get_value_int(d ? d->contents + 0 : 0, def); return impl::get_value_int(d ? d->value + 0 : 0, def);
} }
PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return impl::get_value_uint(d ? d->contents + 0 : 0, def); return impl::get_value_uint(d ? d->value + 0 : 0, def);
} }
PUGI__FN double xml_text::as_double(double def) const PUGI__FN double xml_text::as_double(double def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return impl::get_value_double(d ? d->contents + 0 : 0, def); return impl::get_value_double(d ? d->value + 0 : 0, def);
} }
PUGI__FN float xml_text::as_float(float def) const PUGI__FN float xml_text::as_float(float def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return impl::get_value_float(d ? d->contents + 0 : 0, def); return impl::get_value_float(d ? d->value + 0 : 0, def);
} }
PUGI__FN bool xml_text::as_bool(bool def) const PUGI__FN bool xml_text::as_bool(bool def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return impl::get_value_bool(d ? d->contents + 0 : 0, def); return impl::get_value_bool(d ? d->value + 0 : 0, def);
} }
#ifdef PUGIXML_HAS_LONG_LONG #ifdef PUGIXML_HAS_LONG_LONG
@ -6306,14 +6235,14 @@ namespace pugi
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return impl::get_value_llong(d ? d->contents + 0 : 0, def); return impl::get_value_llong(d ? d->value + 0 : 0, def);
} }
PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
return impl::get_value_ullong(d ? d->contents + 0 : 0, def); return impl::get_value_ullong(d ? d->value + 0 : 0, def);
} }
#endif #endif
@ -6321,42 +6250,42 @@ namespace pugi
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
return dn ? impl::strcpy_insitu(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
} }
PUGI__FN bool xml_text::set(int rhs) PUGI__FN bool xml_text::set(int rhs)
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; 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 int rhs) PUGI__FN bool xml_text::set(unsigned int rhs)
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; 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(float rhs) PUGI__FN bool xml_text::set(float rhs)
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; 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(double rhs) PUGI__FN bool xml_text::set(double rhs)
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; 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(bool rhs) PUGI__FN bool xml_text::set(bool rhs)
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
} }
#ifdef PUGIXML_HAS_LONG_LONG #ifdef PUGIXML_HAS_LONG_LONG
@ -6364,14 +6293,14 @@ namespace pugi
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; 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) PUGI__FN bool xml_text::set(unsigned long long rhs)
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
return dn ? impl::set_value_convert(dn->contents, dn->header, impl::xml_memory_page_contents_allocated_mask, rhs) : false; return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
} }
#endif #endif
@ -7734,7 +7663,8 @@ PUGI__NS_BEGIN
{ {
if ((get_document(node).header & xml_memory_page_contents_shared_mask) == 0) if ((get_document(node).header & xml_memory_page_contents_shared_mask) == 0)
{ {
if (node->contents && (node->header & impl::xml_memory_page_contents_allocated_or_shared_mask) == 0) return node->contents; 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;
} }
return 0; return 0;
@ -9482,7 +9412,7 @@ PUGI__NS_BEGIN
switch (_test) switch (_test)
{ {
case nodetest_name: case nodetest_name:
if (type == node_element && n->contents && strequal(n->contents, _data.nodetest)) if (type == node_element && n->name && strequal(n->name, _data.nodetest))
{ {
ns.push_back(xml_node(n), alloc); ns.push_back(xml_node(n), alloc);
return true; return true;
@ -9518,7 +9448,7 @@ PUGI__NS_BEGIN
break; break;
case nodetest_pi: case nodetest_pi:
if (type == node_pi && n->contents && strequal(n->contents, _data.nodetest)) if (type == node_pi && n->name && strequal(n->name, _data.nodetest))
{ {
ns.push_back(xml_node(n), alloc); ns.push_back(xml_node(n), alloc);
return true; return true;
@ -9534,7 +9464,7 @@ PUGI__NS_BEGIN
break; break;
case nodetest_all_in_namespace: case nodetest_all_in_namespace:
if (type == node_element && n->contents && starts_with(n->contents, _data.nodetest)) if (type == node_element && n->name && starts_with(n->name, _data.nodetest))
{ {
ns.push_back(xml_node(n), alloc); ns.push_back(xml_node(n), alloc);
return true; return true;