add JLANG_free and Object

This commit is contained in:
Jose Luis Montañes Ojados
2026-02-15 22:12:19 +01:00
parent c90883ac27
commit 5dc0946a19
4 changed files with 262 additions and 151 deletions

BIN
run.exe

Binary file not shown.

View File

@@ -1,4 +1,4 @@
#include "memory/allocator.h"
#include "objects/object.h"
int main() {
JLANG_memory_allocator *allocPtr = JLANG_CreateAllocator();
@@ -7,12 +7,24 @@ int main() {
printf("memoryPtr=%p\n", allocPtr->memory);
printf("size=%zu\n", allocPtr->size);
JLANG_visualize(allocPtr);
// Create object
Object *intVar1 = obj_new_int(allocPtr, 66);
obj_print(intVar1);
void *var1 = JLANG_malloc(allocPtr, 512);
printf("var1Ptr=%p\n", var1);
Object *stringVar1 = obj_new_string(allocPtr, "\nHello world!\n");
obj_print(stringVar1);
JLANG_visualize(allocPtr);
for (int i = 0; i < 10; i++) {
Object *intVar1 = obj_new_int(allocPtr, 66);
obj_print(intVar1);
}
obj_free(allocPtr, intVar1);
void* newPtr = JLANG_malloc(allocPtr, 8);
obj_print(stringVar1);
JLANG_visualize(allocPtr);
return 0;
}

View File

@@ -1,11 +1,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Custom Memory Allocator
Implementacion custom de un memory allocator que opera sobre un array de bytes usandolo como "heap"
Implementacion custom de un memory allocator que opera sobre un array de
bytes usandolo como "heap"
*/
#define JLANG_OK 0
@@ -15,99 +16,106 @@
#define JLANG_PAYLOAD 2
/*
La estructura de Metadata se encarga de almacenar el tamaño del bloque y si está en uso.
Se añadirá al principio de cada bloque
[BLOCK_METADATA] + [BLOCK_BYTES]
La estructura de Metadata se encarga de almacenar el tamaño del bloque y si
está en uso. Se añadirá al principio de cada bloque [BLOCK_METADATA] +
[BLOCK_BYTES]
*/
typedef struct
{
size_t size; // 8 bytes
int in_use; // 4 bytes
// --- aquí el compilador mete 4 bytes invisibles ---
typedef struct {
size_t size; // 8 bytes
int in_use; // 4 bytes
// --- aquí el compilador mete 4 bytes invisibles ---
} JLANG_metadata;
/*
La estructura de Memory Allocator se encarga de almancenar el array de memoria y el tamaño de esta.
La estructura de Memory Allocator se encarga de almancenar el array de
memoria y el tamaño de esta.
*/
typedef struct
{
char *memory; // 8 bytes
size_t size; // 8 bytes
typedef struct {
char *memory; // 8 bytes
size_t size; // 8 bytes
} JLANG_memory_allocator;
void *JLANG_CreateAllocator()
{
// Allocate memory in heap for JLANG_memory_allocator
JLANG_memory_allocator *allocator = (JLANG_memory_allocator *)malloc(sizeof(JLANG_memory_allocator));
void *JLANG_CreateAllocator() {
// Allocate memory in heap for JLANG_memory_allocator
JLANG_memory_allocator *allocator =
(JLANG_memory_allocator *)malloc(sizeof(JLANG_memory_allocator));
// Assign default free bytes
allocator->memory = (char *)malloc(1 * 1024);
allocator->size = 1 * 1024;
// Assign default free bytes
allocator->memory = (char *)malloc(1 * 1024);
allocator->size = 1 * 1024;
// ensure all memory is zero
for (int i = 0; i < 1 * 1024; i++)
{
allocator->memory[i] = 0;
}
// ensure all memory is zero
for (int i = 0; i < 1 * 1024; i++) {
allocator->memory[i] = 0;
}
return allocator;
return allocator;
}
size_t JLANG_used(void *ptr)
{
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
size_t JLANG_used(void *ptr) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size)
{
used += sizeof(JLANG_metadata) + currentHeader->size;
// Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size) {
used += sizeof(JLANG_metadata) + currentHeader->size;
// Current block is in_use, jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
}
// Current block is in_use, jump to next block
currentHeader =
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
currentHeader->size);
}
return used;
return used;
}
void *JLANG_last_free(void *ptr)
{
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
void *JLANG_last_free(void *ptr) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size)
{
used += sizeof(JLANG_metadata) + currentHeader->size;
// Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size) {
used += sizeof(JLANG_metadata) + currentHeader->size;
// Current block is in_use, jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
}
// Current block is in_use, jump to next block
currentHeader =
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
currentHeader->size);
}
return currentHeader;
return currentHeader;
}
void *JLANG_malloc(void *ptr, size_t size)
{
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
void *JLANG_malloc(void *ptr, size_t size) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// 1. Hay bloques disponibles??
size_t used = JLANG_used(ptr);
size_t available = allocPtr->size - used;
// 1. Hay bloques disponibles??
size_t used = JLANG_used(ptr);
size_t available = allocPtr->size - used;
// chequear si hay suficiente espacio libre
if (available > size + sizeof(JLANG_metadata))
{
JLANG_metadata *freeHeader = (JLANG_metadata *)JLANG_last_free(ptr);
freeHeader->size = size;
freeHeader->in_use = 1;
// chequear si hay suficiente espacio libre
if (available > size + sizeof(JLANG_metadata)) {
JLANG_metadata *freeHeader = (JLANG_metadata *)JLANG_last_free(ptr);
freeHeader->size = size;
freeHeader->in_use = 1;
return (char *)freeHeader + sizeof(JLANG_metadata);
}
return (char *)freeHeader + sizeof(JLANG_metadata);
}
return NULL; // TODO
return NULL; // TODO
}
void JLANG_free(void *ptr, void *blockPtr) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Get block header
JLANG_metadata *blockHeader =
(JLANG_metadata *)((char *)blockPtr - sizeof(JLANG_metadata));
// Set block as not_used
blockHeader->in_use = 0;
}
/*
@@ -116,101 +124,91 @@ void *JLANG_malloc(void *ptr, size_t size)
[FF FF FF FF FF FF FF ]
*/
int _ceil(float v)
{
int n = (int)v;
float r = v - n;
int _ceil(float v) {
int n = (int)v;
float r = v - n;
if (r > 0)
{
return n + 1;
}
return n;
if (r > 0) {
return n + 1;
}
return n;
}
void JLANG_visualize(void *ptr)
{
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
void JLANG_visualize(void *ptr) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Step 1. Get byte type
char *byteMapPtr = (char *)malloc(allocPtr->size);
memset(byteMapPtr, 0, allocPtr->size);
// Step 1. Get byte type
char *byteMapPtr = (char *)malloc(allocPtr->size);
memset(byteMapPtr, 0, allocPtr->size);
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
long used = 0;
while (used < allocPtr->size)
{
long blockIndex = (char *)currentHeader - (char *)allocPtr->memory;
printf("blockIndex=%u\n", blockIndex);
used += sizeof(JLANG_metadata) + currentHeader->size;
/*
HEADER
blockIndex + sizeof(JLANG_metadata)
*/
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
long used = 0;
while (used < allocPtr->size) {
long blockIndex = (char *)currentHeader - (char *)allocPtr->memory;
used += sizeof(JLANG_metadata) + currentHeader->size;
if (currentHeader->size > 0)
{
byteMapPtr[blockIndex] = JLANG_HEADER;
for (int i = 0; i < sizeof(JLANG_metadata); i++)
{
byteMapPtr[blockIndex + i] = JLANG_HEADER;
}
/*
HEADER
blockIndex + sizeof(JLANG_metadata)
*/
/*
PAYLOAD
*/
for (int i = 0; i < currentHeader->size; i++)
{
byteMapPtr[blockIndex + sizeof(JLANG_metadata) + i] = JLANG_PAYLOAD;
}
} else {
break;
}
if (currentHeader->size > 0) {
byteMapPtr[blockIndex] = JLANG_HEADER;
for (int i = 0; i < sizeof(JLANG_metadata); i++) {
byteMapPtr[blockIndex + i] = JLANG_HEADER;
}
// Jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
/*
PAYLOAD
*/
for (int i = 0; i < currentHeader->size; i++) {
byteMapPtr[blockIndex + sizeof(JLANG_metadata) + i] = JLANG_PAYLOAD;
}
} else {
break;
}
// Step 2. Draw
// Jump to next block
currentHeader =
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
currentHeader->size);
}
int bytePerRow = 40;
int totalRows = _ceil(allocPtr->size / bytePerRow);
printf("totalRows=%d\n", totalRows);
// Step 2. Draw
char *currentMemPtr = allocPtr->memory;
int bytePerRow = 40;
int totalRows = _ceil(allocPtr->size / bytePerRow);
printf("totalRows=%d\n", totalRows);
for (int i = 0; i < totalRows; i++)
{
printf("[");
for (int n = 0; n < bytePerRow; n++)
{
char *currentMemPtr = allocPtr->memory;
int index = n + i * bytePerRow;
for (int i = 0; i < totalRows; i++) {
printf("[");
for (int n = 0; n < bytePerRow; n++) {
switch (byteMapPtr[index])
{
case JLANG_HEADER:
printf("\033[46m");
break;
case JLANG_FREE:
printf("\033[32m");
break;
default:
printf("\033[41m");
break;
}
int index = n + i * bytePerRow;
printf("%.2x", (unsigned char) *(currentMemPtr + (n + i * bytePerRow)));
switch (byteMapPtr[index]) {
case JLANG_HEADER:
printf("\033[46m");
break;
case JLANG_FREE:
printf("\033[32m");
break;
default:
printf("\033[41m");
break;
}
if (n < bytePerRow - 1)
{
printf(" ");
}
printf("%.2x", (unsigned char)*(currentMemPtr + (n + i * bytePerRow)));
printf("\033[0m");
}
if (n < bytePerRow - 1) {
printf(" ");
}
printf("]\n");
printf("\033[0m");
}
printf("]\n");
}
}

101
src/objects/object.h Normal file
View File

@@ -0,0 +1,101 @@
#include "../memory/allocator.h"
typedef enum
{
OBJ_INT,
OBJ_FLOAT,
OBJ_STRING,
OBJ_LIST,
OBJ_NONE
} ObjectType;
typedef struct Object
{
ObjectType type;
union
{
int int_val;
double float_val;
struct
{
char *chars;
int length;
} string_val;
struct
{
struct Object **items;
int count;
int capacity;
} list_val;
} data;
} Object;
Object *obj_new_int(void *allocator, int value)
{
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
objPtr->type = OBJ_INT;
objPtr->data.int_val = value;
return objPtr;
}
Object *obj_new_float(void *allocator, float value)
{
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
objPtr->type = OBJ_FLOAT;
objPtr->data.float_val = value;
return objPtr;
}
Object *obj_new_string(void *allocator, const char *str)
{
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
objPtr->type = OBJ_STRING;
int len = strlen(str);
char *buffer = (char *)JLANG_malloc(allocator, len + 1);
memcpy(buffer, str, len + 1);
objPtr->data.string_val.chars = buffer;
objPtr->data.string_val.length = len;
return objPtr;
}
Object *obj_new_list(void *allocator)
{
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
objPtr->type = OBJ_LIST;
return objPtr;
}
void obj_free(void *allocator, Object* obj) {
if (obj->type == OBJ_STRING) {
JLANG_free(allocator, obj->data.string_val.chars);
}
JLANG_free(allocator, obj);
}
void obj_print(Object *obj)
{
switch (obj->type)
{
case OBJ_INT:
printf("%d", obj->data.int_val);
break;
case OBJ_FLOAT:
printf("%f", obj->data.float_val);
break;
case OBJ_LIST:
for (int i = 0; i < obj->data.list_val.count; i++)
{
obj_print(obj->data.list_val.items[i]);
}
break;
case OBJ_STRING:
printf("%s", obj->data.string_val.chars);
break;
default:
break;
}
}