From fdd1b34244597551db114412bda104ca829465c8 Mon Sep 17 00:00:00 2001 From: Francesco Date: Sat, 9 Aug 2025 21:28:48 +0200 Subject: [PATCH] remove myclib --- include/myclib/hashmap/myhashmap.c | 332 ----------------------------- include/myclib/hashmap/myhashmap.h | 144 ------------- include/myclib/queue/myqueue.c | 89 -------- include/myclib/queue/myqueue.h | 68 ------ include/myclib/string/mystring.c | 181 ---------------- include/myclib/string/mystring.h | 73 ------- 6 files changed, 887 deletions(-) delete mode 100644 include/myclib/hashmap/myhashmap.c delete mode 100644 include/myclib/hashmap/myhashmap.h delete mode 100644 include/myclib/queue/myqueue.c delete mode 100644 include/myclib/queue/myqueue.h delete mode 100644 include/myclib/string/mystring.c delete mode 100644 include/myclib/string/mystring.h diff --git a/include/myclib/hashmap/myhashmap.c b/include/myclib/hashmap/myhashmap.c deleted file mode 100644 index ddaf5cb..0000000 --- a/include/myclib/hashmap/myhashmap.c +++ /dev/null @@ -1,332 +0,0 @@ -#include "myhashmap.h" - -#include -#include -#include -#include - -static size_t mcl_get_mutex(mcl_hashmap *hashmap, size_t hash) { return hash % hashmap->num_locks; } - -static size_t mcl_get_bucket_index(mcl_hashmap *hashmap, void *key) { - unsigned int hash = hashmap->hash_fn(key); - return hash % MYCLIB_HASHMAP_SIZE; -} - -static void mcl_free_bucket_content(mcl_hashmap *hashmap, mcl_bucket *bucket) { - if (bucket == NULL) { - return; - } - - /* Free key if free function is provided */ - if (hashmap->free_key_fn != NULL && bucket->key != NULL) { - hashmap->free_key_fn(bucket->key); - } - - /* Free value if free function is provided */ - if (hashmap->free_value_fn != NULL && bucket->value != NULL) { - hashmap->free_value_fn(bucket->value); - } -} - -static mcl_bucket *mcl_find_bucket(mcl_hashmap *hashmap, void *key, mcl_bucket **prev) { - size_t index = mcl_get_bucket_index(hashmap, key); - mcl_bucket *bucket = &hashmap->map[index]; - - *prev = NULL; - - /* Return NULL if first bucket is empty */ - if (bucket->key == NULL) { - return NULL; - } - - /* Search through the collision chain */ - while (bucket != NULL) { - if (hashmap->equal_fn(bucket->key, key)) { - return bucket; - } - *prev = bucket; - bucket = bucket->next; - } - - return NULL; -} - -mcl_hashmap *mcl_hm_init(mcl_hash_fn *hash_fn, mcl_equal_fn *equal_fn, mcl_free_key_fn *free_key_fn, mcl_free_value_fn *free_value_fn, size_t key_size, - size_t value_size) { - mcl_hashmap *hashmap = malloc(sizeof(mcl_hashmap)); - if (hashmap == NULL) { - return NULL; - } - - hashmap->hash_fn = hash_fn; - hashmap->equal_fn = equal_fn; - hashmap->free_key_fn = free_key_fn; - hashmap->free_value_fn = free_value_fn; - hashmap->key_size = key_size; - hashmap->value_size = value_size; - - hashmap->num_locks = 64; - hashmap->locks = malloc(sizeof(pthread_mutex_t) * hashmap->num_locks); - if (hashmap->locks == NULL) { - free(hashmap); - - return NULL; - } - - int ret; - for (size_t i = 0; i < hashmap->num_locks; ++i) { - ret = pthread_mutex_init(&(hashmap->locks[i]), NULL); - if (ret != 0) { - /* Mutex failed */ - for (size_t j = 0; j < i; ++j) { - pthread_mutex_destroy(&(hashmap->locks[j])); - } - - free(hashmap->locks); - free(hashmap); - } - } - - memset(hashmap->map, 0, sizeof(hashmap->map)); - - return hashmap; -} - -void mcl_hm_free(mcl_hashmap *hashmap) { - if (hashmap == NULL) { - return; - } - - /* Iterate through all buckets in the hash map */ - for (size_t i = 0; i < MYCLIB_HASHMAP_SIZE; ++i) { - mcl_bucket *bucket = &hashmap->map[i]; - - /* Free the first bucket if it contains data */ - if (bucket->key != NULL) { - mcl_free_bucket_content(hashmap, bucket); - } - - /* Free all chained buckets */ - bucket = bucket->next; - while (bucket != NULL) { - mcl_bucket *next = bucket->next; - mcl_free_bucket_content(hashmap, bucket); - free(bucket); - bucket = next; - } - } - - /* Free the mutex */ - for (size_t i = 0; i < hashmap->num_locks; ++i) { - pthread_mutex_destroy(&(hashmap->locks[i])); - } - free(hashmap->locks); - - /* Free the hash map structure itself */ - free(hashmap); -} - -void mcl_hm_free_bucket(mcl_bucket *bucket) { - if (bucket == NULL) { - return; - } - - free(bucket->key); - free(bucket->value); - free(bucket); -} - -bool mcl_hm_set(mcl_hashmap *hashmap, void *key, void *value) { - if (hashmap == NULL || key == NULL || value == NULL) { - return false; - } - - size_t mutex_id = mcl_get_mutex(hashmap, hashmap->hash_fn(key)); - pthread_mutex_t *mutex = &(hashmap->locks[mutex_id]); - pthread_mutex_lock(mutex); - - mcl_bucket *prev; - mcl_bucket *existing = mcl_find_bucket(hashmap, key, &prev); - - if (existing != NULL) { - /* Key exists, update value */ - if (hashmap->free_value_fn != NULL && existing->value != NULL) { - hashmap->free_value_fn(existing->value); - } - - existing->value = malloc(hashmap->value_size); - if (existing->value == NULL) { - pthread_mutex_unlock(mutex); - - return false; - } - - memcpy(existing->value, value, hashmap->value_size); - pthread_mutex_unlock(mutex); - - return true; - } - - /* Key doesn't exist, need to insert new bucket */ - size_t index = mcl_get_bucket_index(hashmap, key); - mcl_bucket *bucket = &hashmap->map[index]; - - if (bucket->key == NULL) { - /* First bucket is empty, use it */ - bucket->key = malloc(hashmap->key_size); - if (bucket->key == NULL) { - pthread_mutex_unlock(mutex); - - return false; - } - - bucket->value = malloc(hashmap->value_size); - if (bucket->value == NULL) { - free(bucket->key); - bucket->key = NULL; - pthread_mutex_unlock(mutex); - - return false; - } - - memcpy(bucket->key, key, hashmap->key_size); - memcpy(bucket->value, value, hashmap->value_size); - bucket->next = NULL; - pthread_mutex_unlock(mutex); - - return true; - } - - /* Create new bucket and insert at head of collision chain */ - mcl_bucket *new_bucket = malloc(sizeof(mcl_bucket)); - if (new_bucket == NULL) { - pthread_mutex_unlock(mutex); - - return false; - } - - new_bucket->key = malloc(hashmap->key_size); - if (new_bucket->key == NULL) { - free(new_bucket); - pthread_mutex_unlock(mutex); - - return false; - } - - new_bucket->value = malloc(hashmap->value_size); - if (new_bucket->value == NULL) { - free(new_bucket->key); - free(new_bucket); - pthread_mutex_unlock(mutex); - - return false; - } - - memcpy(new_bucket->key, key, hashmap->key_size); - memcpy(new_bucket->value, value, hashmap->value_size); - new_bucket->next = bucket->next; - bucket->next = new_bucket; - pthread_mutex_unlock(mutex); - - return true; -} - -static mcl_bucket *mcl_get_bucket_copy(mcl_bucket *from, size_t key_size, size_t value_size) { - mcl_bucket *copy = malloc(sizeof(mcl_bucket)); - if (copy == NULL) { - return NULL; - } - memcpy(copy, from, sizeof(mcl_bucket)); - - copy->key = malloc(key_size); - if (copy->key == NULL) { - free(copy); - - return NULL; - } - memcpy(copy->key, from->key, key_size); - - copy->value = malloc(value_size); - if (copy->value == NULL) { - free(copy->key); - free(copy); - - return NULL; - } - memcpy(copy->value, from->value, value_size); - - return copy; -} - -mcl_bucket *mcl_hm_get(mcl_hashmap *hashmap, void *key) { - if (hashmap == NULL || key == NULL) { - return NULL; - } - - size_t mutex_id = mcl_get_mutex(hashmap, hashmap->hash_fn(key)); - pthread_mutex_t *mutex = &(hashmap->locks[mutex_id]); - pthread_mutex_lock(mutex); - - mcl_bucket *prev; - mcl_bucket *found = mcl_find_bucket(hashmap, key, &prev); - - if (found) { - mcl_bucket *copy = mcl_get_bucket_copy(found, hashmap->key_size, hashmap->value_size); - - pthread_mutex_unlock(mutex); - - return copy; - } - - pthread_mutex_unlock(mutex); - - return NULL; -} - -bool mcl_hm_remove(mcl_hashmap *hashmap, void *key) { - if (hashmap == NULL || key == NULL) { - return false; - } - - size_t mutex_id = mcl_get_mutex(hashmap, hashmap->hash_fn(key)); - pthread_mutex_t *mutex = &(hashmap->locks[mutex_id]); - pthread_mutex_lock(mutex); - - mcl_bucket *prev; - mcl_bucket *to_remove = mcl_find_bucket(hashmap, key, &prev); - - if (to_remove == NULL) { - pthread_mutex_unlock(mutex); - - return false; - } - - /* Free the content of the bucket */ - mcl_free_bucket_content(hashmap, to_remove); - - /* Handle removal based on position in chain */ - if (prev == NULL) { - /* Removing first bucket in chain */ - if (to_remove->next != NULL) { - /* Move next bucket's content to first bucket and free the next bucket */ - mcl_bucket *next_bucket = to_remove->next; - to_remove->key = next_bucket->key; - to_remove->value = next_bucket->value; - to_remove->next = next_bucket->next; - free(next_bucket); - } else { - /* No next bucket, mark first bucket as empty */ - to_remove->key = NULL; - to_remove->value = NULL; - to_remove->next = NULL; - } - } else { - /* Removing bucket from middle/end of chain */ - prev->next = to_remove->next; - free(to_remove); - } - - pthread_mutex_unlock(mutex); - - return true; -} diff --git a/include/myclib/hashmap/myhashmap.h b/include/myclib/hashmap/myhashmap.h deleted file mode 100644 index 3826603..0000000 --- a/include/myclib/hashmap/myhashmap.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef MYCLIB_HASHMAP_H -#define MYCLIB_HASHMAP_H - -#include -#include -#include - -#define MYCLIB_HASHMAP_SIZE 1024 /**< Number of buckets in the hash map */ - -/** - * @brief A single bucket in the hash map - * - * Each bucket can hold one key-value pair and points to the next bucket - * in case of hash collisions (separate chaining). - */ -typedef struct mcl_bucket_t { - void *key; /**< Pointer to the key */ - void *value; /**< Pointer to the value */ - struct mcl_bucket_t *next; /**< Pointer to the next bucket in case of collision */ -} mcl_bucket; - -/** - * @brief Function pointer type for a hash function - * - * @param[in] key Pointer to the key to hash - * @return The computed hash as an unsigned integer - */ -typedef unsigned int mcl_hash_fn(const void *key); - -/** - * @brief Function pointer type for a key comparison function - * - * @param[in] key_a Pointer to the first key - * @param[in] key_b Pointer to the second key - * @return true if the keys are considered equal, false otherwise - */ -typedef bool mcl_equal_fn(const void *key_a, const void *key_b); - -/** - * @brief Function pointer type for freeing a key - * - * @param[in] key Pointer to the key to free - */ -typedef void mcl_free_key_fn(void *key); - -/** - * @brief Function pointer type for freeing a value - * - * @param[in] value Pointer to the value to free - */ -typedef void mcl_free_value_fn(void *value); - -/** - * @brief Main structure representing the hash map - * - * Contains function pointers for hash computation, key comparison, - * and memory management, along with the bucket array. - */ -typedef struct mcl_hashmap_t { - mcl_hash_fn *hash_fn; /**< Hash function */ - mcl_equal_fn *equal_fn; /**< Equality comparison function */ - mcl_free_key_fn *free_key_fn; /**< Key deallocation function (optional) */ - mcl_free_value_fn *free_value_fn; /**< Value deallocation function (optional) */ - size_t key_size; /**< Size in bytes of the key */ - size_t value_size; /**< Size in bytes of the value */ - mcl_bucket map[MYCLIB_HASHMAP_SIZE]; /**< Array of bucket chains */ - pthread_mutex_t *locks; /**< Mutex array */ - size_t num_locks; /**< Number of mutex */ -} mcl_hashmap; - -/** - * @brief Initialize a new hash map with user-defined behavior functions - * - * Creates a new hash map and initializes it with the provided function pointers. - * The free functions can be NULL if no automatic memory management is needed. - * Keys and values will be copied into the hashmap using memcpy with the specified sizes. - * - * @param[in] hash_fn Function used to hash keys (required) - * @param[in] equal_fn Function used to compare keys (required) - * @param[in] free_key_fn Function used to free keys (optional, can be NULL) - * @param[in] free_value_fn Function used to free values (optional, can be NULL) - * @param[in] key_size Size in bytes of each key to be stored - * @param[in] value_size Size in bytes of each value to be stored - * @return A pointer to the newly initialized hash map, or NULL on failure - */ -mcl_hashmap *mcl_hm_init(mcl_hash_fn *hash_fn, mcl_equal_fn *equal_fn, mcl_free_key_fn *free_key_fn, mcl_free_value_fn *free_value_fn, size_t key_size, - size_t value_size); - -/** - * @brief Free all resources used by the hash map - * - * Iterates through all buckets, frees keys and values using the provided - * free functions (if not NULL), and deallocates the hash map structure. - * - * @param[in] hashmap Pointer to the hash map to free - */ -void mcl_hm_free(mcl_hashmap *hashmap); - -/** - * @brief Free a bucket returned by mcl_hm_get() - * - * @param[in] bucket Pointer to the bucket to free - */ -void mcl_hm_free_bucket(mcl_bucket *bucket); - -/** - * @brief Insert or update a key-value pair in the hash map - * - * If the key already exists, the old value is freed (if free_value_fn is provided) - * and replaced with the new value. If the key doesn't exist, a new entry is created. - * Both key and value are copied into the hashmap using memcpy. - * - * @param[in] hashmap Pointer to the hash map - * @param[in] key Pointer to the key to insert (will be copied, must not be NULL) - * @param[in] value Pointer to the value to insert (will be copied, must not be NULL) - * @return true if the operation succeeded, false on failure (NULL hashmap/key/value or memory allocation failure) - */ -bool mcl_hm_set(mcl_hashmap *hashmap, void *key, void *value); - -/** - * @brief Retrieve a bucket by key - * - * Searches for the given key in the hash map and returns the bucket containing it. - * The caller can then access both the key and value from the returned bucket. - * - * @param[in] hashmap Pointer to the hash map - * @param[in] key Pointer to the key to search for - * @return Pointer to the copy of the bucket, to avoid race conditions, or NULL if not found or on invalid input - */ -mcl_bucket *mcl_hm_get(mcl_hashmap *hashmap, void *key); - -/** - * @brief Remove a key-value pair from the hash map - * - * Searches for the given key and removes it from the hash map. Both the key - * and value are freed using the provided free functions (if not NULL). - * - * @param[in] hashmap Pointer to the hash map - * @param[in] key Pointer to the key to remove - * @return true if the key was found and removed, false if not found or on invalid input - */ -bool mcl_hm_remove(mcl_hashmap *hashmap, void *key); - -#endif /* MYCLIB_HASHMAP_H */ diff --git a/include/myclib/queue/myqueue.c b/include/myclib/queue/myqueue.c deleted file mode 100644 index 49fe73e..0000000 --- a/include/myclib/queue/myqueue.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "myqueue.h" - -#include -#include - -mcl_queue *mcl_queue_init(size_t queue_size, size_t elem_size) { - mcl_queue *queue = malloc(sizeof(mcl_queue)); - if (queue == NULL) { - return NULL; - } - - queue->buffer = malloc(queue_size * elem_size); - if (queue->buffer == NULL) { - free(queue); - - return NULL; - } - - queue->front = 0; - queue->rear = 0; - queue->size = 0; - queue->capacity = queue_size; - queue->elem_size = elem_size; - - return queue; -} - -int mcl_queue_push(mcl_queue *queue, const void *elem) { - if (queue->size == queue->capacity) { - /* Queue full */ - return -1; - } - - /* Copy the elem in the buffer */ - void *dest = (void *)queue->buffer + (queue->rear * queue->elem_size); - memcpy(dest, elem, queue->elem_size); - - queue->size++; - queue->rear = (queue->rear + 1) % queue->capacity; - - return 0; -} - -int mcl_queue_pop(mcl_queue *queue, void *out_elem) { - if (queue->size == 0) { - /* Queue empty */ - return -1; - } - - void *src = (void *)queue->buffer + (queue->front * queue->elem_size); - memcpy(out_elem, src, queue->elem_size); - - queue->front = (queue->front + 1) % queue->capacity; - queue->size--; - - return 0; -} - -void *mcl_queue_get_front(mcl_queue *queue) { - if (queue->size == 0) { - return NULL; - } - - return (void *)queue->buffer + (queue->front * queue->elem_size); -} - -void *mcl_queue_get_rear(mcl_queue *queue) { - if (queue->size == 0) { - return NULL; - } - - size_t rear_index; - if (queue->rear == 0) { - rear_index = queue->capacity - 1; - } else { - rear_index = queue->rear - 1; - } - - return (void *)queue->buffer + (rear_index * queue->elem_size); -} - -void mcl_queue_free(mcl_queue *queue) { - if (queue == NULL) { - return; - } - - free(queue->buffer); - free(queue); -} diff --git a/include/myclib/queue/myqueue.h b/include/myclib/queue/myqueue.h deleted file mode 100644 index 42d4bfd..0000000 --- a/include/myclib/queue/myqueue.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef MYCLIB_QUEUE_H -#define MYCLIB_QUEUE_H - -#include - -/** - * @brief A generic circular queue (ring buffer). - */ -typedef struct mcl_queue_t { - size_t front; /**< Index of the first element (read position). */ - size_t rear; /**< Index where the next element will be written (write position). */ - size_t size; /**< Current number of elements in the queue. */ - size_t capacity; /**< Maximum number of elements the queue can hold. */ - size_t elem_size; /**< Size in bytes of each element in the queue. */ - void *buffer; /**< Pointer to the memory buffer that stores the elements. */ -} mcl_queue; - -/** - * @brief Create and initialize a new queue. - * - * @param queue_size Number of elements the queue can hold. - * @param elem_size Size (in bytes) of each element in the queue. - * @return Pointer to the new queue, or NULL if allocation fails. - */ -mcl_queue *mcl_queue_init(size_t queue_size, size_t elem_size); - -/** - * @brief Add an element to the queue. - * - * @param queue Pointer to the queue. - * @param elem Pointer to the element to insert. - * @return 0 on success, -1 if the queue is full. - */ -int mcl_queue_push(mcl_queue *queue, const void *elem); - -/** - * @brief Remove an element from the queue. - * - * @param queue Pointer to the queue. - * @param out_elem Pointer where the removed element will be copied. - * @return 0 on success, -1 if the queue is empty. - */ -int mcl_queue_pop(mcl_queue *queue, void *out_elem); - -/** - * @brief Get a pointer to the front element of the queue (oldest one). - * - * @param queue Pointer to the queue. - * @return Pointer to the front element, or NULL if the queue is empty. - */ -void *mcl_queue_get_front(mcl_queue *queue); - -/** - * @brief Get a pointer to the rear element of the queue (most recently added). - * - * @param queue Pointer to the queue. - * @return Pointer to the rear element, or NULL if the queue is empty. - */ -void *mcl_queue_get_rear(mcl_queue *queue); - -/** - * @brief Free all memory used by the queue. - * - * @param queue Pointer to the queue to free. - */ -void mcl_queue_free(mcl_queue *queue); - -#endif diff --git a/include/myclib/string/mystring.c b/include/myclib/string/mystring.c deleted file mode 100644 index fbc3400..0000000 --- a/include/myclib/string/mystring.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "mystring.h" - -#include -#include -#include -#include - -mcl_string *mcl_string_new(const char *text, long initial_capacity) { - if (text == NULL) { - return NULL; - } - - /* Allocate string struct */ - mcl_string *str = malloc(sizeof(mcl_string)); - if (str == NULL) { - return NULL; - } - - /* Init pthread mutex */ - int ret = pthread_mutex_init(&str->lock, NULL); - if (ret != 0) { - free(str); - - return NULL; - } - - /* Calculate size and capacity */ - str->size = strlen(text); - size_t capacity = initial_capacity; - - if (capacity != -1 && capacity - 1 < str->size) { - free(str); - - return NULL; - } - - if (capacity == -1) { - capacity = (unsigned long)pow(2, (unsigned)log2(str->size) + 1); - } - - str->capacity = capacity; - - /* Allocate data buffer */ - str->data = malloc(sizeof(char) * str->capacity); - if (str->data == NULL) { - free(str); - - return NULL; - } - - /* Copy the text and ensure null termination */ - memset(str->data, 0, str->capacity); - memcpy(str->data, text, str->size); - str->data[str->size] = '\0'; - - return str; -} - -int mcl_string_append(mcl_string *string, const char *text) { - if (string == NULL || text == NULL) { - return -1; - } - - /* Lock resource */ - int ret = pthread_mutex_lock(&string->lock); - if (ret != 0) { - return -1; - } - - /* Handle empty case */ - size_t text_len = strlen(text); - if (text_len == 0) { - pthread_mutex_unlock(&string->lock); - - return 0; - } - - size_t new_size = text_len + string->size; - - /* Check if we need to resize */ - if (new_size + 1 > string->capacity) { - size_t new_capacity = (unsigned long)pow(2, (unsigned)log2(new_size) + 1); - /* Reallocate the buffer */ - void *new_data = realloc(string->data, sizeof(char) * new_capacity); - if (!new_data) { - pthread_mutex_unlock(&string->lock); - - return -1; - } - - string->data = new_data; - string->capacity = new_capacity; - - /* Init to 0 the new capacity */ - memset(string->data + string->size, 0, string->capacity - string->size); - } - - /* Append text */ - memcpy(string->data + string->size, text, text_len); - string->size = new_size; - string->data[string->size] = '\0'; - - /* Unlock resource */ - ret = pthread_mutex_unlock(&string->lock); - if (ret != 0) { - return -1; - } - - return 0; -} - -void mcl_string_free(mcl_string *string) { - if (string == NULL) { - return; - } - - int ret = pthread_mutex_lock(&string->lock); - if (ret != 0) { - return; - } - - if (string->data) { - free(string->data); - } - - pthread_mutex_unlock(&string->lock); - pthread_mutex_destroy(&string->lock); - - free(string); -} - -size_t mcl_string_length(mcl_string *string) { - if (string == NULL) { - return 0; - } - - int ret = pthread_mutex_lock(&string->lock); - if (ret != 0) { - return 0; - } - - size_t len = string->size; - - pthread_mutex_unlock(&string->lock); - - return len; -} - -size_t mcl_string_capacity(mcl_string *string) { - if (string == NULL) { - return 0; - } - - int ret = pthread_mutex_lock(&string->lock); - if (ret != 0) { - return 0; - } - - size_t cap = string->capacity; - - pthread_mutex_unlock(&string->lock); - - return cap; -} - -const char *mcl_string_cstr(mcl_string *string) { - if (string == NULL || string->data == NULL) { - return ""; - } - - int ret = pthread_mutex_lock(&string->lock); - if (ret != 0) { - return NULL; - } - - char *data = string->data; - - pthread_mutex_unlock(&string->lock); - - return data; -} diff --git a/include/myclib/string/mystring.h b/include/myclib/string/mystring.h deleted file mode 100644 index b13d40b..0000000 --- a/include/myclib/string/mystring.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef MYCLIB_STRING_H -#define MYCLIB_STRING_H - -#include -#include - -/** - * @brief Thread-safe dynamic string structure - */ -typedef struct mcl_string_t { - size_t size; /**< Current length of the string (excluding null terminator) */ - size_t capacity; /**< Allocated capacity */ - char *data; /**< Pointer to string data */ - pthread_mutex_t lock; /**< Mutex for thread safety */ -} mcl_string; - -/** - * @brief Create a new string initialized with given text - * - * @param text Initial text (cannot be NULL) - * @param initial_capacity Initial buffer capacity; pass -1 to auto-calculate - * @return Pointer to new string, or NULL on failure - * - * @note Caller must free the string with mcl_string_free() - */ -mcl_string *mcl_string_new(const char *text, long initial_capacity); - -/** - * @brief Append text to an existing string - * - * @param string The string to append to - * @param text Text to append (can be empty) - * @return 0 on success, -1 on failure - * - * @note Original string remains unchanged if append fails - */ -int mcl_string_append(mcl_string *string, const char *text); - -/** - * @brief Free a string and its resources - * - * @param string String to free (NULL is safe) - */ -void mcl_string_free(mcl_string *string); - -/** - * @brief Get the current length of the string - * - * @param string String to query - * @return Length of string, or 0 if NULL - */ -size_t mcl_string_length(mcl_string *string); - -/** - * @brief Get the current capacity of the string buffer - * - * @param string String to query - * @return Capacity, or 0 if NULL - */ -size_t mcl_string_capacity(mcl_string *string); - -/** - * @brief Get a read-only C-string pointer - * - * @param string String to access - * @return Null-terminated string pointer, or "" if NULL - * - * @warning Do not modify returned pointer. - * Pointer may become invalid after string modifications. - */ -const char *mcl_string_cstr(mcl_string *string); - -#endif /* MYCLIB_STRING_H */