#include #include #include #include "_mem.h" // realloc mem. using if other ways not working static 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); newsize = __mem_default_align(newsize); 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->last && MEM_NODE_IS_FREE(node->last) && node->size + node->last->size >= newsize) { // So what happens here is that the node merges with the last 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` 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); } } } if (new_ptr == NULL) { // Allocate a new block of memory with the new size. 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 the new pointer. return new_ptr; }