| 5731 | } |
| 5732 | |
| 5733 | void* reallocate(void* ptr, size_t old_size, size_t new_size) |
| 5734 | { |
| 5735 | // align size so that we're able to store pointers in subsequent blocks |
| 5736 | old_size = (old_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); |
| 5737 | new_size = (new_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); |
| 5738 | |
| 5739 | // we can only reallocate the last object |
| 5740 | assert(ptr == 0 || static_cast<char*>(ptr) + old_size == _root->data + _root_size); |
| 5741 | |
| 5742 | // adjust root size so that we have not allocated the object at all |
| 5743 | bool only_object = (_root_size == old_size); |
| 5744 | |
| 5745 | if (ptr) _root_size -= old_size; |
| 5746 | |
| 5747 | // allocate a new version (this will obviously reuse the memory if possible) |
| 5748 | void* result = allocate(new_size); |
| 5749 | assert(result); |
| 5750 | |
| 5751 | // we have a new block |
| 5752 | if (result != ptr && ptr) |
| 5753 | { |
| 5754 | // copy old data |
| 5755 | assert(new_size > old_size); |
| 5756 | memcpy(result, ptr, old_size); |
| 5757 | |
| 5758 | // free the previous page if it had no other objects |
| 5759 | if (only_object) |
| 5760 | { |
| 5761 | assert(_root->data == result); |
| 5762 | assert(_root->next); |
| 5763 | |
| 5764 | xpath_memory_block* next = _root->next->next; |
| 5765 | |
| 5766 | if (next) |
| 5767 | { |
| 5768 | // deallocate the whole page, unless it was the first one |
| 5769 | xml_memory::deallocate(_root->next); |
| 5770 | _root->next = next; |
| 5771 | } |
| 5772 | } |
| 5773 | } |
| 5774 | |
| 5775 | return result; |
| 5776 | } |
| 5777 | |
| 5778 | void revert(const xpath_allocator& state) |
| 5779 | { |