Custom memory management functions implemented
git-svn-id: http://pugixml.googlecode.com/svn/trunk@105 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
5054325378
commit
e305a07249
110
src/pugixml.cpp
110
src/pugixml.cpp
@ -17,8 +17,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
// For placement new
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
#if !defined(PUGIXML_NO_XPATH) && defined(PUGIXML_NO_EXCEPTIONS)
|
#if !defined(PUGIXML_NO_XPATH) && defined(PUGIXML_NO_EXCEPTIONS)
|
||||||
#error No exception mode can't be used with XPath support
|
#error No exception mode can't be used with XPath support
|
||||||
@ -47,6 +47,22 @@ using std::memcpy;
|
|||||||
|
|
||||||
#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]; }
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void* default_allocate(size_t size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_deallocate(void* ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pugi::allocation_function global_allocate = default_allocate;
|
||||||
|
pugi::deallocation_function global_deallocate = default_deallocate;
|
||||||
|
}
|
||||||
|
|
||||||
namespace pugi
|
namespace pugi
|
||||||
{
|
{
|
||||||
struct xml_document_struct;
|
struct xml_document_struct;
|
||||||
@ -75,7 +91,9 @@ namespace pugi
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_root->next = new xml_memory_block();
|
void* new_block = global_allocate(sizeof(xml_memory_block));
|
||||||
|
|
||||||
|
_root->next = new (new_block) xml_memory_block();
|
||||||
_root = _root->next;
|
_root = _root->next;
|
||||||
|
|
||||||
_root->size = size;
|
_root->size = size;
|
||||||
@ -193,17 +211,17 @@ namespace pugi
|
|||||||
|
|
||||||
xml_document_struct* xml_allocator::allocate_document()
|
xml_document_struct* xml_allocator::allocate_document()
|
||||||
{
|
{
|
||||||
return new(memalloc(sizeof(xml_document_struct))) xml_document_struct;
|
return new (memalloc(sizeof(xml_document_struct))) xml_document_struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_node_struct* xml_allocator::allocate_node(xml_node_type type)
|
xml_node_struct* xml_allocator::allocate_node(xml_node_type type)
|
||||||
{
|
{
|
||||||
return new(memalloc(sizeof(xml_node_struct))) xml_node_struct(type);
|
return new (memalloc(sizeof(xml_node_struct))) xml_node_struct(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_attribute_struct* xml_allocator::allocate_attribute()
|
xml_attribute_struct* xml_allocator::allocate_attribute()
|
||||||
{
|
{
|
||||||
return new(memalloc(sizeof(xml_attribute_struct))) xml_attribute_struct;
|
return new (memalloc(sizeof(xml_attribute_struct))) xml_attribute_struct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,25 +284,12 @@ namespace
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char* buf;
|
char* buf = static_cast<char*>(global_allocate(source_size + 1));
|
||||||
|
if (!buf) return false;
|
||||||
#ifndef PUGIXML_NO_EXCEPTIONS
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
buf = new char[source_size + 1];
|
|
||||||
if (!buf) return false;
|
|
||||||
#ifndef PUGIXML_NO_EXCEPTIONS
|
|
||||||
}
|
|
||||||
catch (const std::bad_alloc&)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
strcpy(buf, source);
|
strcpy(buf, source);
|
||||||
|
|
||||||
if (!insitu) delete[] dest;
|
if (!insitu) global_deallocate(dest);
|
||||||
|
|
||||||
dest = buf;
|
dest = buf;
|
||||||
insitu = false;
|
insitu = false;
|
||||||
@ -2625,7 +2630,7 @@ namespace pugi
|
|||||||
|
|
||||||
void xml_document::destroy()
|
void xml_document::destroy()
|
||||||
{
|
{
|
||||||
delete[] _buffer;
|
global_deallocate(_buffer);
|
||||||
_buffer = 0;
|
_buffer = 0;
|
||||||
|
|
||||||
if (_root) _root->destroy();
|
if (_root) _root->destroy();
|
||||||
@ -2635,7 +2640,7 @@ namespace pugi
|
|||||||
while (current)
|
while (current)
|
||||||
{
|
{
|
||||||
xml_memory_block* next = current->next;
|
xml_memory_block* next = current->next;
|
||||||
delete current;
|
global_deallocate(current);
|
||||||
current = next;
|
current = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2659,27 +2664,14 @@ namespace pugi
|
|||||||
|
|
||||||
if (!stream.good()) return false;
|
if (!stream.good()) return false;
|
||||||
|
|
||||||
char* s;
|
char* s = static_cast<char*>(global_allocate(length + 1));
|
||||||
|
if (!s) return false;
|
||||||
#ifndef PUGIXML_NO_EXCEPTIONS
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
s = new char[length + 1];
|
|
||||||
if (!s) return false;
|
|
||||||
#ifndef PUGIXML_NO_EXCEPTIONS
|
|
||||||
}
|
|
||||||
catch (const std::bad_alloc&)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stream.read(s, length);
|
stream.read(s, length);
|
||||||
|
|
||||||
if (stream.gcount() > length || stream.gcount() == 0)
|
if (stream.gcount() > length || stream.gcount() == 0)
|
||||||
{
|
{
|
||||||
delete[] s;
|
global_deallocate(s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2693,21 +2685,8 @@ namespace pugi
|
|||||||
{
|
{
|
||||||
destroy();
|
destroy();
|
||||||
|
|
||||||
char* s;
|
char* s = static_cast<char*>(global_allocate(strlen(contents) + 1));
|
||||||
|
if (!s) return false;
|
||||||
#ifndef PUGIXML_NO_EXCEPTIONS
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
s = new char[strlen(contents) + 1];
|
|
||||||
if (!s) return false;
|
|
||||||
#ifndef PUGIXML_NO_EXCEPTIONS
|
|
||||||
}
|
|
||||||
catch (const std::bad_alloc&)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
strcpy(s, contents);
|
strcpy(s, contents);
|
||||||
|
|
||||||
@ -2731,29 +2710,20 @@ namespace pugi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* s;
|
char* s = static_cast<char*>(global_allocate(length + 1));
|
||||||
|
|
||||||
#ifndef PUGIXML_NO_EXCEPTIONS
|
if (!s)
|
||||||
try
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
s = new char[length + 1];
|
|
||||||
if (!s) return false;
|
|
||||||
#ifndef PUGIXML_NO_EXCEPTIONS
|
|
||||||
}
|
|
||||||
catch (const std::bad_alloc&)
|
|
||||||
{
|
{
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t read = fread(s, (size_t)length, 1, file);
|
size_t read = fread(s, (size_t)length, 1, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
if (read != 1)
|
if (read != 1)
|
||||||
{
|
{
|
||||||
delete[] s;
|
global_deallocate(s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2778,7 +2748,7 @@ namespace pugi
|
|||||||
bool res = parse(xmlstr, options);
|
bool res = parse(xmlstr, options);
|
||||||
|
|
||||||
if (res) _buffer = xmlstr;
|
if (res) _buffer = xmlstr;
|
||||||
else delete[] xmlstr;
|
else global_deallocate(xmlstr);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -2851,4 +2821,10 @@ namespace pugi
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void set_memory_management_functions(allocation_function allocate, deallocation_function deallocate)
|
||||||
|
{
|
||||||
|
global_allocate = allocate;
|
||||||
|
global_deallocate = deallocate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1745,6 +1745,38 @@ namespace pugi
|
|||||||
*/
|
*/
|
||||||
std::wstring as_utf16(const char* str);
|
std::wstring as_utf16(const char* str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory allocation function
|
||||||
|
*
|
||||||
|
* \param size - allocation size
|
||||||
|
* \return pointer to allocated memory on success, NULL on failure
|
||||||
|
*/
|
||||||
|
typedef void* (*allocation_function)(size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory deallocation function
|
||||||
|
*
|
||||||
|
* \param ptr - pointer to memory previously allocated by allocation function
|
||||||
|
*/
|
||||||
|
typedef void (*deallocation_function)(void* ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override default memory management functions
|
||||||
|
*
|
||||||
|
* All subsequent allocations/deallocations will be performed via supplied functions. Take care not to
|
||||||
|
* change memory management functions if any xml_document instances are still alive - this is considered
|
||||||
|
* undefined behaviour (expect crashes/memory damages/etc.).
|
||||||
|
*
|
||||||
|
* \param allocate - allocation function
|
||||||
|
* \param deallocate - deallocation function
|
||||||
|
*
|
||||||
|
* \note XPath-related allocations, as well as allocations in functions that return std::string (xml_node::path, as_utf8, as_utf16)
|
||||||
|
* are not performed via these functions.
|
||||||
|
* \note If you're using parse() with ownership transfer, you have to allocate the buffer you pass to parse() with allocation
|
||||||
|
* function you set via this function.
|
||||||
|
*/
|
||||||
|
void set_memory_management_functions(allocation_function allocate, deallocation_function deallocate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inline implementation
|
// Inline implementation
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user