Minor allocation refactoring and optimization
git-svn-id: http://pugixml.googlecode.com/svn/trunk@404 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
9441757ef6
commit
4a90b861d9
245
src/pugixml.cpp
245
src/pugixml.cpp
@ -55,6 +55,16 @@ using std::memcpy;
|
|||||||
typedef size_t uintptr_t;
|
typedef size_t uintptr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Inlining controls
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
||||||
|
# define PUGIXML_NO_INLINE __declspec(noinline)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# define PUGIXML_NO_INLINE __attribute__((noinline))
|
||||||
|
#else
|
||||||
|
# define PUGIXML_NO_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Simple static assertion
|
||||||
#define STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; }
|
#define STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; }
|
||||||
|
|
||||||
// Memory allocation
|
// Memory allocation
|
||||||
@ -243,13 +253,24 @@ namespace pugi
|
|||||||
|
|
||||||
struct xml_allocator
|
struct xml_allocator
|
||||||
{
|
{
|
||||||
xml_allocator(xml_memory_page* root): _root(root)
|
xml_allocator(xml_memory_page* root): _root(root), _busy_size(root ? root->busy_size : 0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~xml_allocator()
|
||||||
|
{
|
||||||
|
if (_root) _root->busy_size = _busy_size;
|
||||||
|
}
|
||||||
|
|
||||||
xml_memory_page* allocate_page(size_t data_size)
|
xml_memory_page* allocate_page(size_t data_size)
|
||||||
{
|
{
|
||||||
size_t size = sizeof(xml_memory_page) + data_size; // $$$ slightly incorrect
|
#ifdef __GNUC__
|
||||||
|
// To avoid offsetof warning (xml_memory_page is not POD)
|
||||||
|
xml_memory_page* dummy_page = 0;
|
||||||
|
size_t size = ((size_t)(uintptr_t)&dummy_page->data) + data_size;
|
||||||
|
#else
|
||||||
|
size_t size = offsetof(xml_memory_page, data) + data_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
// allocate block with some alignment, leaving memory for worst-case padding
|
// allocate block with some alignment, leaving memory for worst-case padding
|
||||||
void* memory = global_allocate(size + xml_memory_page_alignment);
|
void* memory = global_allocate(size + xml_memory_page_alignment);
|
||||||
@ -271,26 +292,25 @@ namespace pugi
|
|||||||
global_deallocate(page->memory);
|
global_deallocate(page->memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* allocate_memory_oob(size_t size, xml_memory_page*& out_page)
|
PUGIXML_NO_INLINE void* allocate_memory_oob(size_t size, xml_memory_page*& out_page)
|
||||||
{
|
{
|
||||||
const size_t large_allocation_threshold = xml_memory_page_size / 4;
|
const size_t large_allocation_threshold = xml_memory_page_size / 4;
|
||||||
|
|
||||||
xml_memory_page* page;
|
xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size);
|
||||||
|
|
||||||
if (size <= large_allocation_threshold)
|
if (size <= large_allocation_threshold)
|
||||||
{
|
{
|
||||||
page = allocate_page(xml_memory_page_size);
|
_root->busy_size = _busy_size;
|
||||||
|
|
||||||
// insert page at the end of linked list
|
// insert page at the end of linked list
|
||||||
page->prev = _root;
|
page->prev = _root;
|
||||||
_root->next = page;
|
_root->next = page;
|
||||||
_root = page;
|
_root = page;
|
||||||
|
|
||||||
|
_busy_size = size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// standalone page
|
|
||||||
page = allocate_page(size);
|
|
||||||
|
|
||||||
// insert page before the end of linked list
|
// insert page before the end of linked list
|
||||||
assert(_root->prev);
|
assert(_root->prev);
|
||||||
|
|
||||||
@ -310,11 +330,11 @@ namespace pugi
|
|||||||
|
|
||||||
void* allocate_memory(size_t size, xml_memory_page*& out_page)
|
void* allocate_memory(size_t size, xml_memory_page*& out_page)
|
||||||
{
|
{
|
||||||
if (_root->busy_size + size > xml_memory_page_size) return allocate_memory_oob(size, out_page);
|
if (_busy_size + size > xml_memory_page_size) return allocate_memory_oob(size, out_page);
|
||||||
|
|
||||||
void* buf = _root->data + _root->busy_size;
|
void* buf = _root->data + _busy_size;
|
||||||
|
|
||||||
_root->busy_size += size;
|
_busy_size += size;
|
||||||
|
|
||||||
out_page = _root;
|
out_page = _root;
|
||||||
|
|
||||||
@ -326,6 +346,8 @@ namespace pugi
|
|||||||
assert(ptr >= page->data && ptr < page->data + xml_memory_page_size);
|
assert(ptr >= page->data && ptr < page->data + xml_memory_page_size);
|
||||||
(void)!ptr;
|
(void)!ptr;
|
||||||
|
|
||||||
|
if (page == _root) page->busy_size = _busy_size;
|
||||||
|
|
||||||
page->freed_size += size;
|
page->freed_size += size;
|
||||||
assert(page->freed_size <= page->busy_size);
|
assert(page->freed_size <= page->busy_size);
|
||||||
|
|
||||||
@ -337,6 +359,7 @@ namespace pugi
|
|||||||
|
|
||||||
// top page freed, just reset sizes
|
// top page freed, just reset sizes
|
||||||
page->busy_size = page->freed_size = 0;
|
page->busy_size = page->freed_size = 0;
|
||||||
|
_busy_size = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -353,10 +376,6 @@ namespace pugi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_document_struct* allocate_document();
|
|
||||||
xml_node_struct* allocate_node(xml_node_type type);
|
|
||||||
xml_attribute_struct* allocate_attribute();
|
|
||||||
|
|
||||||
char_t* allocate_string(size_t length)
|
char_t* allocate_string(size_t length)
|
||||||
{
|
{
|
||||||
// get actual size, rounded up to pointer alignment boundary
|
// get actual size, rounded up to pointer alignment boundary
|
||||||
@ -385,6 +404,7 @@ namespace pugi
|
|||||||
}
|
}
|
||||||
|
|
||||||
xml_memory_page* _root;
|
xml_memory_page* _root;
|
||||||
|
size_t _busy_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A 'name=value' XML attribute structure.
|
/// A 'name=value' XML attribute structure.
|
||||||
@ -395,14 +415,6 @@ namespace pugi
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy(xml_allocator& alloc)
|
|
||||||
{
|
|
||||||
if (header & xml_memory_page_name_allocated_mask) alloc.deallocate_string(name);
|
|
||||||
if (header & xml_memory_page_value_allocated_mask) alloc.deallocate_string(value);
|
|
||||||
|
|
||||||
alloc.deallocate_memory(this, sizeof(xml_attribute_struct), reinterpret_cast<xml_memory_page*>(header & xml_memory_page_pointer_mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t header;
|
uintptr_t header;
|
||||||
|
|
||||||
char_t* name; ///< Pointer to attribute name.
|
char_t* name; ///< Pointer to attribute name.
|
||||||
@ -421,68 +433,6 @@ namespace pugi
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy(xml_allocator& alloc)
|
|
||||||
{
|
|
||||||
destroy(alloc, sizeof(xml_node_struct));
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy(xml_allocator& alloc, size_t size)
|
|
||||||
{
|
|
||||||
if (header & xml_memory_page_name_allocated_mask) alloc.deallocate_string(name);
|
|
||||||
if (header & xml_memory_page_value_allocated_mask) alloc.deallocate_string(value);
|
|
||||||
|
|
||||||
for (xml_attribute_struct* attr = first_attribute; attr; )
|
|
||||||
{
|
|
||||||
xml_attribute_struct* next = attr->next_attribute;
|
|
||||||
|
|
||||||
attr->destroy(alloc);
|
|
||||||
|
|
||||||
attr = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (xml_node_struct* node = first_child; node; )
|
|
||||||
{
|
|
||||||
xml_node_struct* next = node->next_sibling;
|
|
||||||
|
|
||||||
node->destroy(alloc);
|
|
||||||
|
|
||||||
node = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
alloc.deallocate_memory(this, size, reinterpret_cast<xml_memory_page*>(header & xml_memory_page_pointer_mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
xml_node_struct* append_node(xml_allocator& alloc, xml_node_type type = node_element)
|
|
||||||
{
|
|
||||||
xml_node_struct* child = alloc.allocate_node(type);
|
|
||||||
child->parent = this;
|
|
||||||
|
|
||||||
if (last_child)
|
|
||||||
{
|
|
||||||
last_child->next_sibling = child;
|
|
||||||
child->prev_sibling = last_child;
|
|
||||||
last_child = child;
|
|
||||||
}
|
|
||||||
else first_child = last_child = child;
|
|
||||||
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
|
|
||||||
xml_attribute_struct* append_attribute(xml_allocator& alloc)
|
|
||||||
{
|
|
||||||
xml_attribute_struct* a = alloc.allocate_attribute();
|
|
||||||
|
|
||||||
if (last_attribute)
|
|
||||||
{
|
|
||||||
last_attribute->next_attribute = a;
|
|
||||||
a->prev_attribute = last_attribute;
|
|
||||||
last_attribute = a;
|
|
||||||
}
|
|
||||||
else first_attribute = last_attribute = a;
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t header;
|
uintptr_t header;
|
||||||
|
|
||||||
xml_node_struct* parent; ///< Pointer to parent
|
xml_node_struct* parent; ///< Pointer to parent
|
||||||
@ -509,29 +459,104 @@ namespace pugi
|
|||||||
xml_allocator allocator;
|
xml_allocator allocator;
|
||||||
const char_t* buffer;
|
const char_t* buffer;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
xml_document_struct* xml_allocator::allocate_document()
|
// Low-level DOM operations
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using namespace pugi;
|
||||||
|
|
||||||
|
inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc)
|
||||||
{
|
{
|
||||||
xml_memory_page* page;
|
xml_memory_page* page;
|
||||||
void* memory = allocate_memory(sizeof(xml_document_struct), page);
|
void* memory = alloc.allocate_memory(sizeof(xml_attribute_struct), page);
|
||||||
|
|
||||||
return new (memory) xml_document_struct(page);
|
return new (memory) xml_attribute_struct(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_node_struct* xml_allocator::allocate_node(xml_node_type type)
|
inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type)
|
||||||
{
|
{
|
||||||
xml_memory_page* page;
|
xml_memory_page* page;
|
||||||
void* memory = allocate_memory(sizeof(xml_node_struct), 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_attribute_struct* xml_allocator::allocate_attribute()
|
inline xml_document_struct* allocate_document(xml_allocator& alloc)
|
||||||
{
|
{
|
||||||
xml_memory_page* page;
|
xml_memory_page* page;
|
||||||
void* memory = allocate_memory(sizeof(xml_attribute_struct), page);
|
void* memory = alloc.allocate_memory(sizeof(xml_document_struct), page);
|
||||||
|
|
||||||
return new (memory) xml_attribute_struct(page);
|
return new (memory) xml_document_struct(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc)
|
||||||
|
{
|
||||||
|
uintptr_t header = a->header;
|
||||||
|
|
||||||
|
if (header & xml_memory_page_name_allocated_mask) alloc.deallocate_string(a->name);
|
||||||
|
if (header & xml_memory_page_value_allocated_mask) alloc.deallocate_string(a->value);
|
||||||
|
|
||||||
|
alloc.deallocate_memory(a, sizeof(xml_attribute_struct), reinterpret_cast<xml_memory_page*>(header & xml_memory_page_pointer_mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void destroy_node(xml_node_struct* n, xml_allocator& alloc)
|
||||||
|
{
|
||||||
|
uintptr_t header = n->header;
|
||||||
|
|
||||||
|
if (header & xml_memory_page_name_allocated_mask) alloc.deallocate_string(n->name);
|
||||||
|
if (header & xml_memory_page_value_allocated_mask) alloc.deallocate_string(n->value);
|
||||||
|
|
||||||
|
for (xml_attribute_struct* attr = n->first_attribute; attr; )
|
||||||
|
{
|
||||||
|
xml_attribute_struct* next = attr->next_attribute;
|
||||||
|
|
||||||
|
destroy_attribute(attr, alloc);
|
||||||
|
|
||||||
|
attr = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (xml_node_struct* child = n->first_child; child; )
|
||||||
|
{
|
||||||
|
xml_node_struct* next = child->next_sibling;
|
||||||
|
|
||||||
|
destroy_node(child, alloc);
|
||||||
|
|
||||||
|
child = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
alloc.deallocate_memory(n, sizeof(xml_node_struct), reinterpret_cast<xml_memory_page*>(header & xml_memory_page_pointer_mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
PUGIXML_NO_INLINE xml_node_struct* append_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element)
|
||||||
|
{
|
||||||
|
xml_node_struct* child = allocate_node(alloc, type);
|
||||||
|
child->parent = node;
|
||||||
|
|
||||||
|
if (node->last_child)
|
||||||
|
{
|
||||||
|
node->last_child->next_sibling = child;
|
||||||
|
child->prev_sibling = node->last_child;
|
||||||
|
node->last_child = child;
|
||||||
|
}
|
||||||
|
else node->first_child = node->last_child = child;
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
PUGIXML_NO_INLINE xml_attribute_struct* append_attribute_ll(xml_node_struct* node, xml_allocator& alloc)
|
||||||
|
{
|
||||||
|
xml_attribute_struct* a = allocate_attribute(alloc);
|
||||||
|
|
||||||
|
if (node->last_attribute)
|
||||||
|
{
|
||||||
|
node->last_attribute->next_attribute = a;
|
||||||
|
a->prev_attribute = node->last_attribute;
|
||||||
|
node->last_attribute = a;
|
||||||
|
}
|
||||||
|
else node->first_attribute = node->last_attribute = a;
|
||||||
|
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1683,12 +1708,12 @@ namespace
|
|||||||
|
|
||||||
struct xml_parser
|
struct xml_parser
|
||||||
{
|
{
|
||||||
xml_allocator& alloc;
|
xml_allocator alloc;
|
||||||
|
|
||||||
// Parser utilities.
|
// Parser utilities.
|
||||||
#define SKIPWS() { while (is_chartype(*s, ct_space)) ++s; }
|
#define SKIPWS() { while (is_chartype(*s, ct_space)) ++s; }
|
||||||
#define OPTSET(OPT) ( optmsk & OPT )
|
#define OPTSET(OPT) ( optmsk & OPT )
|
||||||
#define PUSHNODE(TYPE) { cursor = cursor->append_node(alloc,TYPE); }
|
#define PUSHNODE(TYPE) { cursor = append_node(cursor, alloc, TYPE); }
|
||||||
#define POPNODE() { cursor = cursor->parent; }
|
#define POPNODE() { cursor = cursor->parent; }
|
||||||
#define SCANFOR(X) { while (*s != 0 && !(X)) ++s; }
|
#define SCANFOR(X) { while (*s != 0 && !(X)) ++s; }
|
||||||
#define SCANWHILE(X) { while ((X)) ++s; }
|
#define SCANWHILE(X) { while ((X)) ++s; }
|
||||||
@ -1696,7 +1721,7 @@ namespace
|
|||||||
#define THROW_ERROR(err, m) return make_parse_result(err, m - buffer_start, __LINE__)
|
#define THROW_ERROR(err, m) return make_parse_result(err, m - buffer_start, __LINE__)
|
||||||
#define CHECK_ERROR(err, m) { if (*s == 0) THROW_ERROR(err, m); }
|
#define CHECK_ERROR(err, m) { if (*s == 0) THROW_ERROR(err, m); }
|
||||||
|
|
||||||
xml_parser(xml_allocator& alloc): alloc(alloc)
|
xml_parser(const xml_allocator& alloc): alloc(alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2005,7 +2030,7 @@ namespace
|
|||||||
|
|
||||||
if (is_chartype(*s, ct_start_symbol)) // <... #...
|
if (is_chartype(*s, ct_start_symbol)) // <... #...
|
||||||
{
|
{
|
||||||
xml_attribute_struct* a = cursor->append_attribute(alloc); // Make space for this attribute.
|
xml_attribute_struct* a = append_attribute_ll(cursor, alloc); // Make space for this attribute.
|
||||||
a->name = s; // Save the offset.
|
a->name = s; // Save the offset.
|
||||||
|
|
||||||
SCANWHILE(is_chartype(*s, ct_symbol)); // Scan for a terminator.
|
SCANWHILE(is_chartype(*s, ct_symbol)); // Scan for a terminator.
|
||||||
@ -2207,8 +2232,8 @@ namespace
|
|||||||
// perform actual parsing
|
// perform actual parsing
|
||||||
xml_parse_result result = parser.parse(buffer, xmldoc, optmsk, endch);
|
xml_parse_result result = parser.parse(buffer, xmldoc, optmsk, endch);
|
||||||
|
|
||||||
// fixup page live_sizes $$$
|
// update allocator state
|
||||||
// for (xml_memory_page* page = alloc._root; page; page = page->prev) page->live_size = page->busy_size;
|
alloc = parser.alloc;
|
||||||
|
|
||||||
// since we removed last character, we have to handle the only possible false positive
|
// since we removed last character, we have to handle the only possible false positive
|
||||||
if (result && endch == '<')
|
if (result && endch == '<')
|
||||||
@ -2221,10 +2246,6 @@ namespace
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
xml_parser(const xml_parser&);
|
|
||||||
const xml_parser& operator=(const xml_parser&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Output facilities
|
// Output facilities
|
||||||
@ -3435,7 +3456,7 @@ namespace pugi
|
|||||||
{
|
{
|
||||||
if (type() != node_element && type() != node_declaration) return xml_attribute();
|
if (type() != node_element && type() != node_declaration) return xml_attribute();
|
||||||
|
|
||||||
xml_attribute a(_root->append_attribute(get_allocator()));
|
xml_attribute a(append_attribute_ll(_root, get_allocator()));
|
||||||
a.set_name(name);
|
a.set_name(name);
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
@ -3452,7 +3473,7 @@ namespace pugi
|
|||||||
|
|
||||||
if (cur != _root->first_attribute) return xml_attribute();
|
if (cur != _root->first_attribute) return xml_attribute();
|
||||||
|
|
||||||
xml_attribute a(get_allocator().allocate_attribute());
|
xml_attribute a(allocate_attribute(get_allocator()));
|
||||||
a.set_name(name);
|
a.set_name(name);
|
||||||
|
|
||||||
if (attr._attr->prev_attribute)
|
if (attr._attr->prev_attribute)
|
||||||
@ -3478,7 +3499,7 @@ namespace pugi
|
|||||||
|
|
||||||
if (cur != _root->first_attribute) return xml_attribute();
|
if (cur != _root->first_attribute) return xml_attribute();
|
||||||
|
|
||||||
xml_attribute a(get_allocator().allocate_attribute());
|
xml_attribute a(allocate_attribute(get_allocator()));
|
||||||
a.set_name(name);
|
a.set_name(name);
|
||||||
|
|
||||||
if (attr._attr->next_attribute)
|
if (attr._attr->next_attribute)
|
||||||
@ -3527,7 +3548,7 @@ namespace pugi
|
|||||||
{
|
{
|
||||||
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
||||||
|
|
||||||
return xml_node(_root->append_node(get_allocator(), type));
|
return xml_node(append_node(_root, get_allocator(), type));
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_node xml_node::insert_child_before(xml_node_type type, const xml_node& node)
|
xml_node xml_node::insert_child_before(xml_node_type type, const xml_node& node)
|
||||||
@ -3535,7 +3556,7 @@ namespace pugi
|
|||||||
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
||||||
if (node.parent() != *this) return xml_node();
|
if (node.parent() != *this) return xml_node();
|
||||||
|
|
||||||
xml_node n(get_allocator().allocate_node(type));
|
xml_node n(allocate_node(get_allocator(), type));
|
||||||
n._root->parent = _root;
|
n._root->parent = _root;
|
||||||
|
|
||||||
if (node._root->prev_sibling)
|
if (node._root->prev_sibling)
|
||||||
@ -3555,7 +3576,7 @@ namespace pugi
|
|||||||
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
||||||
if (node.parent() != *this) return xml_node();
|
if (node.parent() != *this) return xml_node();
|
||||||
|
|
||||||
xml_node n(get_allocator().allocate_node(type));
|
xml_node n(allocate_node(get_allocator(), type));
|
||||||
n._root->parent = _root;
|
n._root->parent = _root;
|
||||||
|
|
||||||
if (node._root->next_sibling)
|
if (node._root->next_sibling)
|
||||||
@ -3619,7 +3640,7 @@ namespace pugi
|
|||||||
if (a._attr->prev_attribute) a._attr->prev_attribute->next_attribute = a._attr->next_attribute;
|
if (a._attr->prev_attribute) a._attr->prev_attribute->next_attribute = a._attr->next_attribute;
|
||||||
else _root->first_attribute = a._attr->next_attribute;
|
else _root->first_attribute = a._attr->next_attribute;
|
||||||
|
|
||||||
a._attr->destroy(get_allocator());
|
destroy_attribute(a._attr, get_allocator());
|
||||||
}
|
}
|
||||||
|
|
||||||
void xml_node::remove_child(const char_t* name)
|
void xml_node::remove_child(const char_t* name)
|
||||||
@ -3637,7 +3658,7 @@ namespace pugi
|
|||||||
if (n._root->prev_sibling) n._root->prev_sibling->next_sibling = n._root->next_sibling;
|
if (n._root->prev_sibling) n._root->prev_sibling->next_sibling = n._root->next_sibling;
|
||||||
else _root->first_child = n._root->next_sibling;
|
else _root->first_child = n._root->next_sibling;
|
||||||
|
|
||||||
n._root->destroy(get_allocator());
|
destroy_node(n._root, get_allocator());
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_node xml_node::find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const
|
xml_node xml_node::find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const
|
||||||
@ -4071,7 +4092,7 @@ namespace pugi
|
|||||||
// allocate new root
|
// allocate new root
|
||||||
xml_allocator alloc(_memory.next ? _memory.next : &_memory);
|
xml_allocator alloc(_memory.next ? _memory.next : &_memory);
|
||||||
|
|
||||||
_root = alloc.allocate_document();
|
_root = allocate_document(alloc);
|
||||||
|
|
||||||
// setup allocator
|
// setup allocator
|
||||||
xml_allocator& a = static_cast<xml_document_struct*>(_root)->allocator;
|
xml_allocator& a = static_cast<xml_document_struct*>(_root)->allocator;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user