| 6390 | } |
| 6391 | |
| 6392 | void* reallocate(void* ptr, size_t old_size, size_t new_size) |
| 6393 | { |
| 6394 | // align size so that we're able to store pointers in subsequent blocks |
| 6395 | old_size = (old_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); |
| 6396 | new_size = (new_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); |
| 6397 | |
| 6398 | // we can only reallocate the last object |
| 6399 | assert(ptr == 0 || static_cast<char*>(ptr) + old_size == _root->data + _root_size); |
| 6400 | |
| 6401 | // adjust root size so that we have not allocated the object at all |
| 6402 | bool only_object = (_root_size == old_size); |
| 6403 | |
| 6404 | if (ptr) |
| 6405 | _root_size -= old_size; |
| 6406 | |
| 6407 | // allocate a new version (this will obviously reuse the memory if possible) |
| 6408 | void* result = allocate(new_size); |
| 6409 | assert(result); |
| 6410 | |
| 6411 | // we have a new block |
| 6412 | if (result != ptr && ptr) |
| 6413 | { |
| 6414 | // copy old data |
| 6415 | assert(new_size > old_size); |
| 6416 | memcpy(result, ptr, old_size); |
| 6417 | |
| 6418 | // free the previous page if it had no other objects |
| 6419 | if (only_object) |
| 6420 | { |
| 6421 | assert(_root->data == result); |
| 6422 | assert(_root->next); |
| 6423 | |
| 6424 | xpath_memory_block* next = _root->next->next; |
| 6425 | |
| 6426 | if (next) |
| 6427 | { |
| 6428 | // deallocate the whole page, unless it was the first one |
| 6429 | xml_memory::deallocate(_root->next); |
| 6430 | _root->next = next; |
| 6431 | } |
| 6432 | } |
| 6433 | } |
| 6434 | |
| 6435 | return result; |
| 6436 | } |
| 6437 | |
| 6438 | void revert(const xpath_allocator& state) |
| 6439 | { |