303 lines
6.8 KiB
C
303 lines
6.8 KiB
C
|
|
#include "memory.h"
|
||
|
|
#include <string.h>
|
||
|
|
#include <ctype.h>
|
||
|
|
|
||
|
|
struct memory_pool {
|
||
|
|
void **free_list;
|
||
|
|
size_t block_size;
|
||
|
|
size_t capacity;
|
||
|
|
size_t free_count;
|
||
|
|
mutex_t mutex;
|
||
|
|
};
|
||
|
|
|
||
|
|
memory_pool_t *mempool_create(size_t block_size, size_t initial_count) {
|
||
|
|
memory_pool_t *pool = calloc(1, sizeof(memory_pool_t));
|
||
|
|
if (!pool) return NULL;
|
||
|
|
|
||
|
|
pool->block_size = block_size;
|
||
|
|
pool->capacity = initial_count;
|
||
|
|
pool->free_count = initial_count;
|
||
|
|
|
||
|
|
pool->free_list = calloc(initial_count, sizeof(void *));
|
||
|
|
if (!pool->free_list) {
|
||
|
|
free(pool);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (size_t i = 0; i < initial_count; i++) {
|
||
|
|
pool->free_list[i] = malloc(block_size);
|
||
|
|
if (!pool->free_list[i]) {
|
||
|
|
for (size_t j = 0; j < i; j++) {
|
||
|
|
free(pool->free_list[j]);
|
||
|
|
}
|
||
|
|
free(pool->free_list);
|
||
|
|
free(pool);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pal_mutex_init(&pool->mutex);
|
||
|
|
return pool;
|
||
|
|
}
|
||
|
|
|
||
|
|
void mempool_destroy(memory_pool_t *pool) {
|
||
|
|
if (!pool) return;
|
||
|
|
|
||
|
|
pal_mutex_lock(&pool->mutex);
|
||
|
|
for (size_t i = 0; i < pool->free_count; i++) {
|
||
|
|
free(pool->free_list[i]);
|
||
|
|
}
|
||
|
|
free(pool->free_list);
|
||
|
|
pal_mutex_unlock(&pool->mutex);
|
||
|
|
pal_mutex_destroy(&pool->mutex);
|
||
|
|
free(pool);
|
||
|
|
}
|
||
|
|
|
||
|
|
void *mempool_alloc(memory_pool_t *pool) {
|
||
|
|
if (!pool) return malloc(64);
|
||
|
|
|
||
|
|
pal_mutex_lock(&pool->mutex);
|
||
|
|
|
||
|
|
void *ptr;
|
||
|
|
if (pool->free_count > 0) {
|
||
|
|
ptr = pool->free_list[--pool->free_count];
|
||
|
|
} else {
|
||
|
|
ptr = malloc(pool->block_size);
|
||
|
|
}
|
||
|
|
|
||
|
|
pal_mutex_unlock(&pool->mutex);
|
||
|
|
return ptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
void mempool_free(memory_pool_t *pool, void *ptr) {
|
||
|
|
if (!ptr) return;
|
||
|
|
if (!pool) {
|
||
|
|
free(ptr);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
pal_mutex_lock(&pool->mutex);
|
||
|
|
|
||
|
|
if (pool->free_count < pool->capacity) {
|
||
|
|
pool->free_list[pool->free_count++] = ptr;
|
||
|
|
} else {
|
||
|
|
void **new_list = realloc(pool->free_list, (pool->capacity * 2) * sizeof(void *));
|
||
|
|
if (new_list) {
|
||
|
|
pool->free_list = new_list;
|
||
|
|
pool->capacity *= 2;
|
||
|
|
pool->free_list[pool->free_count++] = ptr;
|
||
|
|
} else {
|
||
|
|
free(ptr);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pal_mutex_unlock(&pool->mutex);
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t mempool_available(memory_pool_t *pool) {
|
||
|
|
if (!pool) return 0;
|
||
|
|
pal_mutex_lock(&pool->mutex);
|
||
|
|
size_t count = pool->free_count;
|
||
|
|
pal_mutex_unlock(&pool->mutex);
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
buffer_t *buffer_create(size_t initial_capacity) {
|
||
|
|
buffer_t *buf = calloc(1, sizeof(buffer_t));
|
||
|
|
if (!buf) return NULL;
|
||
|
|
|
||
|
|
if (initial_capacity > 0) {
|
||
|
|
buf->data = malloc(initial_capacity);
|
||
|
|
if (!buf->data) {
|
||
|
|
free(buf);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
buf->capacity = initial_capacity;
|
||
|
|
buf->data[0] = '\0';
|
||
|
|
}
|
||
|
|
|
||
|
|
return buf;
|
||
|
|
}
|
||
|
|
|
||
|
|
void buffer_destroy(buffer_t *buf) {
|
||
|
|
if (!buf) return;
|
||
|
|
free(buf->data);
|
||
|
|
free(buf);
|
||
|
|
}
|
||
|
|
|
||
|
|
int buffer_reserve(buffer_t *buf, size_t capacity) {
|
||
|
|
if (!buf) return NWEDAV_ERROR;
|
||
|
|
if (buf->capacity >= capacity) return NWEDAV_OK;
|
||
|
|
|
||
|
|
size_t new_cap = buf->capacity ? buf->capacity : 64;
|
||
|
|
while (new_cap < capacity) {
|
||
|
|
new_cap *= 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *new_data = realloc(buf->data, new_cap);
|
||
|
|
if (!new_data) return NWEDAV_ERROR_MEMORY;
|
||
|
|
|
||
|
|
buf->data = new_data;
|
||
|
|
buf->capacity = new_cap;
|
||
|
|
return NWEDAV_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
int buffer_append(buffer_t *buf, const void *data, size_t len) {
|
||
|
|
if (!buf || !data || len == 0) return NWEDAV_OK;
|
||
|
|
|
||
|
|
if (buffer_reserve(buf, buf->size + len + 1) != NWEDAV_OK) {
|
||
|
|
return NWEDAV_ERROR_MEMORY;
|
||
|
|
}
|
||
|
|
|
||
|
|
memcpy(buf->data + buf->size, data, len);
|
||
|
|
buf->size += len;
|
||
|
|
buf->data[buf->size] = '\0';
|
||
|
|
return NWEDAV_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
int buffer_append_str(buffer_t *buf, const char *str) {
|
||
|
|
if (!str) return NWEDAV_OK;
|
||
|
|
return buffer_append(buf, str, strlen(str));
|
||
|
|
}
|
||
|
|
|
||
|
|
int buffer_append_fmt(buffer_t *buf, const char *fmt, ...) {
|
||
|
|
if (!buf || !fmt) return NWEDAV_ERROR;
|
||
|
|
|
||
|
|
va_list ap;
|
||
|
|
va_start(ap, fmt);
|
||
|
|
int needed = vsnprintf(NULL, 0, fmt, ap);
|
||
|
|
va_end(ap);
|
||
|
|
|
||
|
|
if (needed < 0) return NWEDAV_ERROR;
|
||
|
|
|
||
|
|
if (buffer_reserve(buf, buf->size + needed + 1) != NWEDAV_OK) {
|
||
|
|
return NWEDAV_ERROR_MEMORY;
|
||
|
|
}
|
||
|
|
|
||
|
|
va_start(ap, fmt);
|
||
|
|
vsnprintf(buf->data + buf->size, needed + 1, fmt, ap);
|
||
|
|
va_end(ap);
|
||
|
|
|
||
|
|
buf->size += needed;
|
||
|
|
return NWEDAV_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
void buffer_consume(buffer_t *buf, size_t len) {
|
||
|
|
if (!buf || len == 0) return;
|
||
|
|
|
||
|
|
if (len >= buf->size) {
|
||
|
|
buf->size = 0;
|
||
|
|
if (buf->data) buf->data[0] = '\0';
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
memmove(buf->data, buf->data + len, buf->size - len);
|
||
|
|
buf->size -= len;
|
||
|
|
buf->data[buf->size] = '\0';
|
||
|
|
}
|
||
|
|
|
||
|
|
void buffer_reset(buffer_t *buf) {
|
||
|
|
if (!buf) return;
|
||
|
|
buf->size = 0;
|
||
|
|
if (buf->data) buf->data[0] = '\0';
|
||
|
|
}
|
||
|
|
|
||
|
|
char *buffer_detach(buffer_t *buf) {
|
||
|
|
if (!buf) return NULL;
|
||
|
|
char *data = buf->data;
|
||
|
|
buf->data = NULL;
|
||
|
|
buf->size = 0;
|
||
|
|
buf->capacity = 0;
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *str_dup(const char *str) {
|
||
|
|
if (!str) return NULL;
|
||
|
|
size_t len = strlen(str);
|
||
|
|
char *dup = malloc(len + 1);
|
||
|
|
if (dup) {
|
||
|
|
memcpy(dup, str, len + 1);
|
||
|
|
}
|
||
|
|
return dup;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *str_ndup(const char *str, size_t n) {
|
||
|
|
if (!str) return NULL;
|
||
|
|
size_t len = strlen(str);
|
||
|
|
if (n < len) len = n;
|
||
|
|
char *dup = malloc(len + 1);
|
||
|
|
if (dup) {
|
||
|
|
memcpy(dup, str, len);
|
||
|
|
dup[len] = '\0';
|
||
|
|
}
|
||
|
|
return dup;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *str_lower(char *str) {
|
||
|
|
if (!str) return NULL;
|
||
|
|
for (char *p = str; *p; p++) {
|
||
|
|
*p = tolower((unsigned char)*p);
|
||
|
|
}
|
||
|
|
return str;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *str_upper(char *str) {
|
||
|
|
if (!str) return NULL;
|
||
|
|
for (char *p = str; *p; p++) {
|
||
|
|
*p = toupper((unsigned char)*p);
|
||
|
|
}
|
||
|
|
return str;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *str_trim(char *str) {
|
||
|
|
if (!str) return NULL;
|
||
|
|
|
||
|
|
while (isspace((unsigned char)*str)) str++;
|
||
|
|
|
||
|
|
if (*str == '\0') return str;
|
||
|
|
|
||
|
|
char *end = str + strlen(str) - 1;
|
||
|
|
while (end > str && isspace((unsigned char)*end)) end--;
|
||
|
|
end[1] = '\0';
|
||
|
|
|
||
|
|
return str;
|
||
|
|
}
|
||
|
|
|
||
|
|
int str_starts_with(const char *str, const char *prefix) {
|
||
|
|
if (!str || !prefix) return 0;
|
||
|
|
size_t prefix_len = strlen(prefix);
|
||
|
|
return strncmp(str, prefix, prefix_len) == 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int str_ends_with(const char *str, const char *suffix) {
|
||
|
|
if (!str || !suffix) return 0;
|
||
|
|
size_t str_len = strlen(str);
|
||
|
|
size_t suffix_len = strlen(suffix);
|
||
|
|
if (suffix_len > str_len) return 0;
|
||
|
|
return strcmp(str + str_len - suffix_len, suffix) == 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int str_casecmp(const char *a, const char *b) {
|
||
|
|
if (!a && !b) return 0;
|
||
|
|
if (!a) return -1;
|
||
|
|
if (!b) return 1;
|
||
|
|
|
||
|
|
#ifdef _WIN32
|
||
|
|
return _stricmp(a, b);
|
||
|
|
#else
|
||
|
|
return strcasecmp(a, b);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
int str_ncasecmp(const char *a, const char *b, size_t n) {
|
||
|
|
if (!a && !b) return 0;
|
||
|
|
if (!a) return -1;
|
||
|
|
if (!b) return 1;
|
||
|
|
|
||
|
|
#ifdef _WIN32
|
||
|
|
return _strnicmp(a, b, n);
|
||
|
|
#else
|
||
|
|
return strncasecmp(a, b, n);
|
||
|
|
#endif
|
||
|
|
}
|