diff options
| author | arseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640> | 2009-01-06 13:14:13 +0000 | 
|---|---|---|
| committer | arseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640> | 2009-01-06 13:14:13 +0000 | 
| commit | e305a07249fa8b772319d12f7657373cbb71173d (patch) | |
| tree | 1f22396cebd552183ed261f92978744b5f8d2ae8 /src | |
| parent | 5054325378a67e1480fe2474836f6f5a919dc4bc (diff) | |
Custom memory management functions implemented
git-svn-id: http://pugixml.googlecode.com/svn/trunk@105 99668b35-9821-0410-8761-19e4c4f06640
Diffstat (limited to 'src')
| -rw-r--r-- | src/pugixml.cpp | 110 | ||||
| -rw-r--r-- | src/pugixml.hpp | 32 | 
2 files changed, 75 insertions, 67 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 99a13c2..ad57086 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -17,8 +17,8 @@  #include <stdio.h>
  #include <string.h>
 +// For placement new
  #include <new>
 -#include <exception>
  #if !defined(PUGIXML_NO_XPATH) && defined(PUGIXML_NO_EXCEPTIONS)
  #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]; }
 +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
  {
  	struct xml_document_struct;
 @@ -75,7 +91,9 @@ namespace pugi  			}
  			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->size = size;
 @@ -193,17 +211,17 @@ namespace pugi  	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)
  	{
 -		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()
  	{
 -		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
  		{
 -			char* buf;
 -
 -		#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
 +			char* buf = static_cast<char*>(global_allocate(source_size + 1));
 +			if (!buf) return false;
  			strcpy(buf, source);
 -			if (!insitu) delete[] dest;
 +			if (!insitu) global_deallocate(dest);
  			dest = buf;
  			insitu = false;
 @@ -2625,7 +2630,7 @@ namespace pugi  	void xml_document::destroy()
  	{
 -		delete[] _buffer;
 +		global_deallocate(_buffer);
  		_buffer = 0;
  		if (_root) _root->destroy();
 @@ -2635,7 +2640,7 @@ namespace pugi  		while (current)
  		{
  			xml_memory_block* next = current->next;
 -			delete current;
 +			global_deallocate(current);
  			current = next;
  		}
 @@ -2659,27 +2664,14 @@ namespace pugi  		if (!stream.good()) return false;
 -		char* s;
 -
 -	#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
 +		char* s = static_cast<char*>(global_allocate(length + 1));
 +		if (!s) return false;
  		stream.read(s, length);
  		if (stream.gcount() > length || stream.gcount() == 0)
  		{
 -			delete[] s;
 +			global_deallocate(s);
  			return false;
  		}
 @@ -2693,21 +2685,8 @@ namespace pugi  	{
  		destroy();
 -		char* s;
 -
 -	#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
 +		char* s = static_cast<char*>(global_allocate(strlen(contents) + 1));
 +		if (!s) return false;
  		strcpy(s, contents);
 @@ -2731,29 +2710,20 @@ namespace pugi  			return false;
  		}
 -		char* s;
 +		char* s = static_cast<char*>(global_allocate(length + 1));
 -	#ifndef PUGIXML_NO_EXCEPTIONS
 -		try
 -		{
 -	#endif
 -			s = new char[length + 1];
 -			if (!s) return false;
 -	#ifndef PUGIXML_NO_EXCEPTIONS
 -		}
 -		catch (const std::bad_alloc&)
 +		if (!s)
  		{
  			fclose(file);
  			return false;
  		}
 -	#endif
  		size_t read = fread(s, (size_t)length, 1, file);
  		fclose(file);
  		if (read != 1)
  		{
 -			delete[] s;
 +			global_deallocate(s);
  			return false;
  		}
 @@ -2778,7 +2748,7 @@ namespace pugi  		bool res = parse(xmlstr, options);
  		if (res) _buffer = xmlstr;
 -		else delete[] xmlstr;
 +		else global_deallocate(xmlstr);
  		return res;
  	}
 @@ -2851,4 +2821,10 @@ namespace pugi  		return result;
  	}
  #endif
 +
 +    void set_memory_management_functions(allocation_function allocate, deallocation_function deallocate)
 +    {
 +    	global_allocate = allocate;
 +    	global_deallocate = deallocate;
 +    }
  }
 diff --git a/src/pugixml.hpp b/src/pugixml.hpp index b1096fe..fd25077 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1745,6 +1745,38 @@ namespace pugi  	 */  	std::wstring as_utf16(const char* str);  #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  | 
