/*
This is part of WHY2
Copyright (C) 2022 Václav Šmejkal
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*
bro this whole file is fucked up af...
...or maybe I am...
*/
#include
#include
#include
#include
#include
#include
//LOCAL
enum POINTER_TYPES
{
ALLOCATION,
FOPEN,
OPENDIR
};
typedef struct node
{
void *pointer;
char *identifier;
enum POINTER_TYPES type;
struct node *next;
} node_t; //SINGLE LINKED LIST
node_t *head = NULL;
void push_to_list(void *pointer, enum POINTER_TYPES type)
{
//CREATE NODE
node_t *new_node = malloc(sizeof(node_t));
node_t *buffer = head;
new_node -> pointer = pointer;
new_node -> identifier = why2_get_memory_identifier();
new_node -> type = type;
new_node -> next = NULL;
if (head == NULL) //INIT LIST
{
head = new_node;
} else
{
while (buffer -> next != NULL) buffer = buffer -> next; //GET TO THE END OF LIST
buffer -> next = new_node; //LINK
}
}
void remove_node(node_t *node)
{
if (node == NULL) return; //NULL NODE
node_t *buffer_1 = head;
node_t *buffer_2;
while (buffer_1 -> next != NULL) //GO TROUGH EVERY ELEMENT IN LIST
{
if (buffer_1 == node) break; //FOUND (IF THE WHILE GOES TROUGH THE WHOLE LIST WITHOUT THE break, I ASSUME THE LAST NODE IS THE CORRECT ONE)
buffer_1 = buffer_1 -> next;
}
if (node != buffer_1) return; //node WASN'T FOUND
if (buffer_1 == head) //node WAS THE FIRST NODE IN THE LIST
{
//UNLINK
head = buffer_1 -> next;
} else //wdyt
{
//GET THE NODE BEFORE node
buffer_2 = head;
while (buffer_2 -> next != buffer_1) buffer_2 = buffer_2 -> next;
//UNLINK
buffer_2 -> next = buffer_1 -> next;
}
//DEALLOCATION
free(node);
}
node_t *get_node(void *pointer)
{
if (head == NULL || pointer == NULL) return NULL; //EMPTY LIST
node_t *buffer = head;
while (buffer -> next != NULL)
{
if (buffer -> pointer == pointer) return buffer;
buffer = buffer -> next;
}
if (pointer != buffer -> pointer) buffer = NULL; //PREVENT FROM RETURNING INVALID NODE
return buffer;
}
//GLOBAL
void *why2_malloc(unsigned long size)
{
void *allocated = malloc(size);
push_to_list(allocated, ALLOCATION);
return allocated;
}
void *why2_calloc(unsigned long element, unsigned long size)
{
void *allocated = calloc(element, size);
push_to_list(allocated, ALLOCATION);
return allocated;
}
void *why2_realloc(void *pointer, unsigned long size)
{
if (pointer != NULL) why2_deallocate(pointer);
void *allocated = malloc(size);
push_to_list(allocated, ALLOCATION);
return allocated;
}
void *why2_recalloc(void *pointer, unsigned long size, unsigned long block_size)
{
if (pointer != NULL) why2_deallocate(pointer);
void *allocated = calloc(size, block_size);
push_to_list(allocated, ALLOCATION);
return allocated;
}
char *why2_strdup(char *string)
{
if (string == NULL) return NULL;
char *allocated = strdup(string);
push_to_list(allocated, ALLOCATION);
return allocated;
}
void *why2_fopen(char *name, char *modes)
{
void *opened = fopen(name, modes);
push_to_list(opened, FOPEN);
return opened;
}
void *why2_fdopen(int file, char *modes)
{
void *opened = fdopen(file, modes);
push_to_list(opened, FOPEN);
return opened;
}
void *why2_opendir(char *name)
{
void *opened = opendir(name);
push_to_list(opened, OPENDIR);
return opened;
}
void why2_deallocate(void *pointer)
{
if (pointer == NULL) return; //DEALLOCATING NULL
//VARIABLES
node_t *node = get_node(pointer);
if (node == NULL) return;
switch (node -> type) //DEALLOCATE BY THE CORRECT WAY
{
case ALLOCATION: //STANDARD MALLOC, CALLOC OR REALLOC
free(pointer);
break;
case FOPEN: //FOPEN OR FDOPEN
fclose(pointer);
break;
case OPENDIR: //OPENDIR SYSTEM CALL
closedir(pointer);
break;
}
remove_node(node); //REMOVE FROM LIST IF FOUND
}
void why2_clean_memory(char *identifier)
{
if (head == NULL) return; //LIST IS EMPTY
node_t *buffer = head;
void *pointer_buffer = NULL;
why2_bool force_deallocating = identifier == why2_get_default_memory_identifier();
while (buffer -> next != NULL) //GO TROUGH LIST
{
if (buffer -> identifier == identifier || force_deallocating) pointer_buffer = buffer -> pointer;
buffer = buffer -> next;
if (pointer_buffer != NULL)
{
why2_deallocate(pointer_buffer);
pointer_buffer = NULL;
}
}
if (buffer -> identifier == identifier || force_deallocating) why2_deallocate(buffer -> pointer); //LAST NODE
why2_reset_memory_identifier(); //THIS WILL CAUSE SEGFAULT IF YOU DIDN'T USE why2_set_memory_identifier
}
why2_bool why2_allocated(void *pointer)
{
return get_node(pointer) != NULL;
}