Created
July 18, 2023 22:47
-
-
Save interval1066/527a2af67ff7f01428bcddff77ca1177 to your computer and use it in GitHub Desktop.
Constantly trying to find was to make things simpler here's a proposal for a pointer manager for C projects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <stdlib.h> | |
#include <stddef.h> | |
typedef struct | |
{ | |
void (*print)(void*); | |
void (*destroy)(void*); | |
} BaseObject; | |
typedef struct | |
{ | |
void** pointers; | |
size_t capacity; | |
size_t count; | |
} PointerManager; | |
void | |
pointer_manager_init(PointerManager* manager, size_t capacity) { | |
manager->pointers = calloc(capacity, sizeof(void*)); | |
manager->capacity = capacity; | |
manager->count = 0; | |
} | |
void | |
pointer_manager_destroy(PointerManager* manager) | |
{ | |
for (size_t i = 0; i < manager->count; ++i) { | |
if (manager->pointers[i] != NULL) { | |
BaseObject* obj = (BaseObject*)manager->pointers[i]; | |
obj->destroy(manager->pointers[i]); | |
} | |
} | |
free(manager->pointers); | |
} | |
void* | |
pointer_manager_create(PointerManager* manager, void (*print)(void*), void (*destroy)(void*)) | |
{ | |
if (manager->count >= manager->capacity) { | |
return NULL; // Capacity reached, unable to create more pointers | |
} | |
BaseObject* obj = malloc(sizeof(BaseObject)); | |
obj->print = print; | |
obj->destroy = destroy; | |
manager->pointers[manager->count++] = obj; | |
return obj; | |
} | |
void | |
pointer_manager_destroy_entry(PointerManager* manager, void* ptr) | |
{ | |
for (size_t i = 0; i < manager->count; ++i) { | |
if (manager->pointers[i] == ptr) { | |
if (manager->pointers[i] != NULL) { | |
BaseObject* obj = (BaseObject*)manager->pointers[i]; | |
obj->destroy(manager->pointers[i]); | |
} | |
manager->pointers[i] = NULL; | |
break; | |
} | |
} | |
} | |
Usage: | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include "pmgr.h" | |
typedef struct | |
{ | |
BaseObject base; | |
int value; | |
} ObjectA; | |
typedef struct | |
{ | |
BaseObject base; | |
char data; | |
} ObjectB; | |
typedef struct | |
{ | |
BaseObject base; | |
float number; | |
} ObjectC; | |
void objectA_print(void* obj) | |
{ | |
ObjectA* objectA = (ObjectA*)obj; | |
printf("Object A - Value: %d\n", objectA->value); | |
} | |
void objectA_destroy(void* obj) | |
{ | |
free(obj); | |
} | |
void objectB_print(void* obj) | |
{ | |
ObjectB* objectB = (ObjectB*)obj; | |
printf("Object B - Data: %c\n", objectB->data); | |
} | |
void objectB_destroy(void* obj) | |
{ | |
free(obj); | |
} | |
void objectC_print(void* obj) | |
{ | |
ObjectC* objectC = (ObjectC*)obj; | |
printf("Object C - Number: %.2f\n", objectC->number); | |
} | |
void objectC_destroy(void* obj) | |
{ | |
free(obj); | |
} | |
int main() { | |
PointerManager manager; | |
pointer_manager_init(&manager, 10); | |
// Example usage | |
ObjectA* objA = pointer_manager_create(&manager, objectA_print, objectA_destroy); | |
if (objA != NULL) { | |
objA->value = 42; | |
objA->base.print(objA); | |
} | |
ObjectB* objB = pointer_manager_create(&manager, objectB_print, objectB_destroy); | |
if (objB != NULL) { | |
objB->data = 'X'; | |
objB->base.print(objB); | |
} | |
ObjectC* objC = pointer_manager_create(&manager, objectC_print, objectC_destroy); | |
if (objC != NULL) { | |
objC->number = 3.14f; | |
objC->base.print(objC); | |
} | |
pointer_manager_destroy_entry(&manager, objA); | |
pointer_manager_destroy_entry(&manager, objB); | |
pointer_manager_destroy_entry(&manager, objC); | |
pointer_manager_destroy(&manager); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Recently on an embedded C project and the complexity was daunting, due in part to all the conscious pointer management the developer had to do. Here's my attempt to reign it in.