2024-04-22 00:09:51 +08:00

524 lines
12 KiB
C

/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file valloc.c
* \unit valloc
* \brief Test how much space is allocated
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* memory alloc info type define */
typedef struct
{
char *file;
int line;
int size;
} minfo;
/* rbtree node type define */
typedef struct NODE
{
struct NODE *parent;
struct NODE *left;
struct NODE *right;
int color;
void* pointer;
minfo info;
} NODE;
/* rbtree type define */
typedef struct
{
NODE* root;
NODE* nil;
int size;
} RBTREE, *rbtree_t;
/* rbtree node color */
#define BLACK (0)
#define RED (1)
static rbtree_t mrbtree = NULL;
static rbtree_t rbtree_create(void)
{
rbtree_t rbtree;
rbtree = (rbtree_t)malloc(sizeof(RBTREE));
if (!rbtree) return NULL;
rbtree->nil = (NODE*)malloc(sizeof(NODE));
if (!rbtree->nil)
{
free(rbtree);
return NULL;
}
rbtree->nil->color = BLACK;
rbtree->root = rbtree->nil;
rbtree->size = 0;
return rbtree;
}
static void recursion_delete_node(rbtree_t rbtree, NODE* node)
{
if (node == rbtree->nil) return;
recursion_delete_node(rbtree, node->left);
recursion_delete_node(rbtree, node->right);
free(node);
}
static void rbtree_delete(rbtree_t rbtree)
{
if (!rbtree) return;
recursion_delete_node(rbtree, rbtree->root);;
free(rbtree->nil);
free(rbtree);
}
static NODE* rbtree_find_node(rbtree_t rbtree, void* pointer)
{
NODE* node = rbtree->root;
while (node != rbtree->nil)
{
if (pointer < node->pointer) node = node->left;
else if (pointer > node->pointer) node = node->right;
else return node;
}
return rbtree->nil;
}
static void left_rotate(rbtree_t rbtree, NODE* x)
{
NODE* y = x->right;
x->right = y->left;
if (y->left != rbtree->nil) y->left->parent = x;
y->parent = x->parent;
if (x->parent == rbtree->nil) rbtree->root = y;
else if (x == x->parent->left) x->parent->left = y;
else x->parent->right = y;
y->left = x;
x->parent = y;
}
static void right_rotate(rbtree_t rbtree, NODE* y)
{
NODE* x = y->left;
y->left = x->right;
if (x->right != rbtree->nil) x->right->parent = y;
x->parent = y->parent;
if (y->parent == rbtree->nil) rbtree->root = x;
else if (y == y->parent->right) y->parent->right = x;
else y->parent->left = x;
x->right = y;
y->parent = x;
}
static void rbtree_insert_fixup(rbtree_t rbtree, NODE* z)
{
NODE* y = NULL;
while (z->parent->color == RED)
{
if (z->parent == z->parent->parent->left)
{
y = z->parent->parent->right;
if (y->color == RED)
{
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else
{
if (z == z->parent->right)
{
z = z->parent;
left_rotate(rbtree, z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
right_rotate(rbtree, z->parent->parent);
}
}
else
{
y = z->parent->parent->left;
if (y->color == RED)
{
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else
{
if (z == z->parent->left)
{
z = z->parent;
right_rotate(rbtree, z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
left_rotate(rbtree, z->parent->parent);
}
}
}
rbtree->root->color = BLACK;
}
static void rbtree_insert_node(rbtree_t rbtree, NODE* z)
{
NODE* y = rbtree->nil;
NODE* x = rbtree->root;
while (x != rbtree->nil)
{
y = x;
if (z->pointer < x->pointer) x = x->left;
else if (z->pointer > x->pointer) x = x->right;
else return;
}
z->parent = y;
if (y == rbtree->nil) rbtree->root = z;
else if (z->pointer < y->pointer) y->left = z;
else y->right = z;
z->left = rbtree->nil;
z->right = rbtree->nil;
z->color = RED;
rbtree_insert_fixup(rbtree, z);
}
static minfo* rbtree_insert(rbtree_t rbtree, void* pointer, minfo info)
{
NODE* node;
int child = 0;
if (!rbtree) return NULL;
node = (NODE*)malloc(sizeof(NODE));
if (!node) return NULL;
node->pointer = pointer;
node->info = info;
rbtree_insert_node(rbtree, node);
rbtree->size++;
return &(node->info);
}
static void rbtree_erase_fixup(rbtree_t rbtree, NODE* x)
{
NODE* w = NULL;
while ((x != rbtree->root) && (x->color == BLACK))
{
if (x == x->parent->left)
{
w = x->parent->right;
if (w->color == RED)
{
w->color = BLACK;
x->parent->color = RED;
left_rotate(rbtree, x->parent);
w = x->parent->right;
}
if ((w->left->color == BLACK) && (w->right->color == BLACK))
{
w->color = RED;
x = x->parent;
}
else
{
if (w->right->color == BLACK)
{
w->left->color = BLACK;
w->color = RED;
right_rotate(rbtree, w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->right->color = BLACK;
left_rotate(rbtree, x->parent);
x = rbtree->root;
}
}
else
{
w = x->parent->left;
if (w->color == RED)
{
w->color = BLACK;
x->parent->color = RED;
right_rotate(rbtree, x->parent);
w = x->parent->left;
}
if ((w->left->color == BLACK) && (w->right->color == BLACK))
{
w->color = RED;
x = x->parent;
}
else
{
if (w->left->color == BLACK)
{
w->right->color = BLACK;
w->color = RED;
left_rotate(rbtree, w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
right_rotate(rbtree, x->parent);
x = rbtree->root;
}
}
}
x->color = BLACK;
}
static NODE* node_min(rbtree_t rbtree, NODE* x)
{
if (x == rbtree->nil) return x;
while (x->left != rbtree->nil) x = x->left;
return x;
}
static NODE* node_max(rbtree_t rbtree, NODE* x)
{
if (x == rbtree->nil) return x;
while (x->right != rbtree->nil) x = x->right;
return x;
}
static NODE* rbtree_successor(rbtree_t rbtree, NODE* x)
{
NODE* y = x->parent;
if (x->right != rbtree->nil) return node_min(rbtree, x->right);
while ((y != rbtree->nil) && (x == y->right))
{
x = y;
y = y->parent;
}
return y;
}
static NODE* rbtree_erase_node(rbtree_t rbtree, NODE* z)
{
NODE* y = rbtree->nil;
NODE* x = rbtree->nil;
if ((z->left == rbtree->nil) || (z->right == rbtree->nil)) y = z;
else y = rbtree_successor(rbtree, z);
if (y->left != rbtree->nil) x = y->left;
else if (y->right != rbtree->nil) x = y->right;
x->parent = y->parent;
if (y->parent == rbtree->nil) rbtree->root = x;
else if (y == y->parent->left) y->parent->left = x;
else y->parent->right = x;
if (y != z)
{
z->pointer = y->pointer;
z->info = y->info;
}
if (y->color == BLACK) rbtree_erase_fixup(rbtree, x);
return y;
}
static int rbtree_erase(rbtree_t rbtree, void* pointer)
{
NODE* node = NULL;
NODE* cur = NULL;
if (!rbtree) return 0;
node = rbtree_find_node(rbtree, pointer);
if (node == rbtree->nil) return 0;
cur = rbtree_erase_node(rbtree, node);
free(cur);
rbtree->size--;
return 1;
}
static int rbtree_size(rbtree_t rbtree)
{
if (!rbtree) return 0;
return rbtree->size;
}
static int rbtree_find(rbtree_t rbtree, void* pointer)
{
if (!rbtree) return 0;
return rbtree_find_node(rbtree, pointer)==rbtree->nil?0:1;
}
static minfo* rbtree_data(rbtree_t rbtree, void* pointer)
{
if (!rbtree) return NULL;
return &(rbtree_find_node(rbtree, pointer)->info);
}
static NODE* node_next(rbtree_t rbtree, NODE* node)
{
if (node->right != rbtree->nil)
{
node = node->right;
node = node_min(rbtree, node);
}
else
{
if (node == node->parent->left) node = node->parent;
else node = node->parent->parent;
}
return node;
}
static NODE* node_prev(rbtree_t rbtree, NODE* node)
{
if (node->left != rbtree->nil)
{
node = node->left;
node = node_max(rbtree, node);
}
else
{
if (node == node->parent->right) node = node->parent;
else node = node->parent->parent;
}
return node;
}
void* vm_malloc(size_t size, char *file, int line)
{
void* p;
minfo info;
if (!mrbtree)
{
mrbtree = rbtree_create();
if (!mrbtree) return NULL;
}
p = malloc(size);
if (!p) return NULL;
info.size = size;
info.file = file;
info.line = line;
if (!rbtree_insert(mrbtree, p, info))
{
free(p);
return NULL;
}
return p;
}
void* vm_calloc(size_t num, size_t size, char *file, int line)
{
void* p;
p = vm_malloc(num * size, file, line);
if (!p) return NULL;
memset(p, 0, num * size);
return p;
}
void vm_free(void* block)
{
if (!block) return;
if (rbtree_erase(mrbtree, block)) free(block);
if (rbtree_size(mrbtree) == 0)
{
rbtree_delete(mrbtree);
mrbtree = NULL;
}
}
void* vm_realloc(void* block, size_t size, char *file, int line)
{
void* p;
if (!block)
{
return vm_malloc(size, file, line);
}
if (size == 0)
{
vm_free(block);
return NULL;
}
if (!rbtree_find(mrbtree, block)) return NULL;
p = realloc(block, size);
if (!p) return NULL;
if (p == block)
{
minfo *info;
info = rbtree_data(mrbtree, block);
info->file = file;
info->line = line;
info->size = size;
}
else
{
minfo info;
rbtree_erase(mrbtree, block);
info.file = file;
info.line = line;
info.size = size;
rbtree_insert(mrbtree, p, info);
}
return p;
}
void v_check_unfree(void)
{
int size, i;
void *p;
NODE* node;
if (!mrbtree) return;
size = rbtree_size(mrbtree);
node = node_min(mrbtree, mrbtree->root);
for (i = 0; i < size; i++)
{
printf("address: %p, size: %d, file: %s, line: %d\r\n", node->pointer, node->info.size, node->info.file, node->info.line);
node = node_next(mrbtree, node);
}
}
int v_check_count(void)
{
if (!mrbtree) return 0;
return rbtree_size(mrbtree);
}
int v_check_used(void)
{
int size, i;
int used = 0;
NODE* node;
if (!mrbtree) return 0;
size = rbtree_size(mrbtree);
node = node_min(mrbtree, mrbtree->root);
for (i = 0; i < size; i++)
{
used += node->info.size;
node = node_next(mrbtree, node);
}
return used;
}