summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640>2010-08-29 15:14:15 +0000
committerarseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640>2010-08-29 15:14:15 +0000
commit6b4a375ec3ff855b202dd2746d5a78212fdb1978 (patch)
treeaa0fbc19956fd1f88c00a0b152cbaba947885d82
parent56334ccd95750ed6deb737dc8e15cef09c46c6bf (diff)
XPath: Allocator now uses custom allocation functions and has single static page, added out of memory handling during parsing
git-svn-id: http://pugixml.googlecode.com/svn/trunk@647 99668b35-9821-0410-8761-19e4c4f06640
-rw-r--r--src/pugixpath.cpp86
1 files changed, 54 insertions, 32 deletions
diff --git a/src/pugixpath.cpp b/src/pugixpath.cpp
index 6663ef8..a30ec55 100644
--- a/src/pugixpath.cpp
+++ b/src/pugixpath.cpp
@@ -620,14 +620,10 @@ namespace pugi
}
#endif
- const size_t xpath_memory_block_size = 4096; ///< Memory block size, 4 kb
+ const size_t xpath_memory_block_size = 4096;
class xpath_allocator
{
- // disable copy ctor and assignment
- xpath_allocator(const xpath_allocator&);
- xpath_allocator& operator=(const xpath_allocator&);
-
struct memory_block
{
memory_block(): next(0), size(0)
@@ -641,23 +637,41 @@ namespace pugi
};
memory_block* _root;
+ memory_block _first;
public:
- xpath_allocator(): _root(0)
+ static xpath_allocator* create()
{
- _root = new memory_block;
+ void* memory = get_memory_allocation_function()(sizeof(xpath_allocator));
+
+ return new (memory) xpath_allocator();
}
-
- ~xpath_allocator()
+
+ static void destroy(xpath_allocator* alloc)
{
- while (_root)
+ if (!alloc) return;
+
+ // free all allocated pages
+ memory_block* cur = alloc->_root;
+ memory_block* first = &alloc->_first;
+
+ while (cur != first)
{
- memory_block* cur = _root->next;
- delete _root;
- _root = cur;
+ memory_block* next = cur->next;
+
+ get_memory_deallocation_function()(cur);
+
+ cur = next;
}
+
+ // free allocator memory (with the first page)
+ get_memory_deallocation_function()(alloc);
}
+ xpath_allocator(): _root(&_first)
+ {
+ }
+
void* allocate(size_t size)
{
// align size so that we're able to store pointers in subsequent blocks
@@ -671,13 +685,12 @@ namespace pugi
}
else
{
- memory_block* block;
+ size_t block_data_size = (size > xpath_memory_block_size) ? size : xpath_memory_block_size;
+ size_t block_size = block_data_size + offsetof(memory_block, data);
+
+ memory_block* block = static_cast<memory_block*>(get_memory_allocation_function()(block_size));
+ if (!block) return 0;
- if (size > xpath_memory_block_size)
- block = static_cast<memory_block*>(operator new(size + sizeof(memory_block) - xpath_memory_block_size));
- else
- block = new memory_block;
-
block->next = _root;
block->size = size;
@@ -957,11 +970,6 @@ namespace pugi
class xpath_lexer
{
- // disable copy ctor and assignment
- xpath_lexer(const xpath_lexer&);
- xpath_lexer& operator=(const xpath_lexer&);
-
- private:
const char_t* _cur;
const char_t* _cur_lexeme_pos;
xpath_lexer_string _cur_lexeme_contents;
@@ -2584,7 +2592,11 @@ namespace pugi
void* alloc_node()
{
- return _alloc.allocate(sizeof(xpath_ast_node));
+ void* result = _alloc.allocate(sizeof(xpath_ast_node));
+
+ if (!result) throw_error("Out of memory");
+
+ return result;
}
const char_t* alloc_string(const xpath_lexer_string& value)
@@ -2594,6 +2606,8 @@ namespace pugi
size_t length = static_cast<size_t>(value.end - value.begin);
char_t* c = static_cast<char_t*>(_alloc.allocate((length + 1) * sizeof(char_t)));
+ if (!c) throw_error("Out of memory");
+
memcpy(c, value.begin, length * sizeof(char_t));
c[length] = 0;
@@ -3373,9 +3387,6 @@ namespace pugi
static xpath_ast_node* parse(const char_t* query, xpath_allocator& alloc, xpath_parse_result* result)
{
- result->error = 0;
- result->offset = 0;
-
xpath_parser parser(query, alloc, result);
int error = setjmp(parser._error_handler);
@@ -3391,12 +3402,23 @@ namespace pugi
xpath_query::xpath_query(const char_t* query): _alloc(0), _root(0)
{
- _alloc = new xpath_allocator;
- _root = xpath_parser::parse(query, *_alloc, &_result);
+ _result.error = 0;
+ _result.offset = 0;
+
+ _alloc = xpath_allocator::create();
+
+ if (!_alloc)
+ {
+ _result.error = "Out of memory";
+ }
+ else
+ {
+ _root = xpath_parser::parse(query, *_alloc, &_result);
+ }
if (!_root)
{
- delete _alloc;
+ xpath_allocator::destroy(_alloc);
_alloc = 0;
#ifndef PUGIXML_NO_EXCEPTIONS
@@ -3407,7 +3429,7 @@ namespace pugi
xpath_query::~xpath_query()
{
- delete _alloc;
+ xpath_allocator::destroy(_alloc);
}
xpath_value_type xpath_query::return_type() const