#include #include #include #include "_mem.h" // realloc mem. using if other ways not working void* fail_realloc(void* ptr, size_t newsize) { // Allocate a new block of memory with the new size. void* new_ptr = malloc(newsize); // If both the old pointer and the new pointer are not NULL: if (ptr != NULL && new_ptr != NULL) { // Copy the data from the old block to the new block. memcpy(new_ptr, ptr, min(newsize, GET_MEM_NODE_USED_MEM(GET_MEM_NODE_HEADER(ptr)))); } if (ptr) { free(ptr); // Free the old block. } return new_ptr; } void* realloc(void* ptr, size_t newsize) { void* new_ptr = NULL; struct mem_node* node = NULL; if (ptr && newsize) { // Get a pointer to the mem_node header from the user data pointer. node = GET_MEM_NODE_HEADER(ptr); if (node->size >= newsize) { // current node have enough mem // it work always if newsize is smaller // Update the free space in the current node. node->free = node->size - newsize; // Return the original pointer. new_ptr = ptr; } else if (node->next && MEM_NODE_IS_FREE(node->next) && node->size + node->next->size >= newsize) { // So what happens here is that the node merges with the next node if their volume is sufficient. // And a reallock is called in the hopes that the first condition will be met. // if merge failed realloc anyway return pointer, but it will got from `fail_realloc` // it faster than merge with last node, because its not make a copy/move new_ptr = realloc(GET_MEM_NODE_PTR(__mem_MERGE_MEM_NODES(node, node->next)), newsize); } else if (node->last && MEM_NODE_IS_FREE(node->last) && node->size + node->last->size >= newsize) { struct mem_node* l = node->last; l = __mem_MERGE_MEM_NODES(l, node); if (l) memmove(GET_MEM_NODE_PTR(l), ptr, GET_MEM_NODE_USED_MEM(node)); new_ptr = realloc(GET_MEM_NODE_PTR(l), newsize); } else { new_ptr = fail_realloc(ptr, newsize); } } else { new_ptr = fail_realloc(ptr, newsize); } // Return the new pointer. return new_ptr; }