Initial commit, yay
This commit is contained in:
commit
25e26756cd
85 changed files with 7077 additions and 0 deletions
217
src/dynamicbuffer/dynamicbuffer.c
Normal file
217
src/dynamicbuffer/dynamicbuffer.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* This code is part of the strategy game operational-space.
|
||||
* operational-space comes with ABSOLUTELY NO WARRANTY and is licensed under GPL-2.0.
|
||||
* Copyright (C) 2024 VegOwOtenks, Sleppo04
|
||||
*
|
||||
* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include "dynamicbuffer.h"
|
||||
|
||||
int DynamicBuffer_Create(dynamic_buffer_t *destination, size_t initial_capacity)
|
||||
{
|
||||
return DynamicBuffer_CreateWithAllocator(destination, initial_capacity, NULL);
|
||||
}
|
||||
|
||||
int DynamicBuffer_CreateWithAllocator(dynamic_buffer_t *destination, size_t initial_capacity, allocator_t* allocator)
|
||||
{
|
||||
if (destination == NULL) {
|
||||
return EDESTADDRREQ;
|
||||
}
|
||||
// Some malloc() implementations return NULL and other return valid pointers on zero-byte-allocation, I'm not handling this shit
|
||||
if (initial_capacity == 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
dynamic_buffer_t local;
|
||||
|
||||
local.allocator = allocator;
|
||||
local.capacity = initial_capacity;
|
||||
local.used = 0;
|
||||
|
||||
if (allocator != NULL) {
|
||||
local.array = allocator->allocate(allocator, initial_capacity);
|
||||
} else {
|
||||
local.array = malloc(initial_capacity);
|
||||
}
|
||||
if (local.array == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
destination[0] = local;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int DynamicBuffer_EnsureUnusedCapacity(dynamic_buffer_t* buffer, size_t needed_unused)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
size_t unused_space = buffer->capacity - buffer->used;
|
||||
|
||||
if (needed_unused < unused_space) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
size_t needed_capacity = buffer->capacity + needed_unused;
|
||||
int resize_code = DynamicBuffer_Resize(buffer, needed_capacity);
|
||||
|
||||
if (resize_code) {
|
||||
// ENOMEM
|
||||
return resize_code;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int DynamicBuffer_EnsureCapacity(dynamic_buffer_t* buffer, size_t minimal_capacity)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (minimal_capacity < buffer->capacity) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int resize_code = DynamicBuffer_Resize(buffer, minimal_capacity);
|
||||
if (resize_code) {
|
||||
// ENOMEM
|
||||
return resize_code;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int DynamicBuffer_Resize(dynamic_buffer_t* buffer, size_t new_capacity)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (new_capacity == 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
char* new_array;
|
||||
if (buffer->allocator != NULL) {
|
||||
new_array = buffer->allocator->reallocate(buffer->allocator, buffer->array, buffer->capacity, new_capacity);
|
||||
} else {
|
||||
new_array = realloc(buffer->array, new_capacity);
|
||||
}
|
||||
if (new_array == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
buffer->array = new_array;
|
||||
buffer->capacity = new_capacity;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int DynamicBuffer_Prune(dynamic_buffer_t* buffer)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
return DynamicBuffer_Resize(buffer, buffer->used);
|
||||
}
|
||||
|
||||
int DynamicBuffer_Reset(dynamic_buffer_t* buffer)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
buffer->used = 0;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int DynamicBuffer_RewindBytes(dynamic_buffer_t* buffer, size_t bytes)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (buffer->used < bytes) {
|
||||
return EBOUNDS;
|
||||
}
|
||||
|
||||
buffer->used -= bytes;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int DynamicBuffer_Store(dynamic_buffer_t* buffer, const void* data, size_t data_size)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (data == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (data_size == 0) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int ensure_code = DynamicBuffer_EnsureUnusedCapacity(buffer, data_size);
|
||||
if (ensure_code) {
|
||||
// ENOMEM
|
||||
return ensure_code;
|
||||
}
|
||||
|
||||
void* destination = ((char*) buffer->array) + buffer->used;
|
||||
memcpy(destination, data, data_size);
|
||||
buffer->used += data_size;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
size_t DynamicBuffer_GetBlockCount(dynamic_buffer_t* buffer, size_t block_size)
|
||||
{
|
||||
return buffer->used / block_size;
|
||||
}
|
||||
|
||||
void* DynamicBuffer_ReadAt(dynamic_buffer_t* buffer, size_t offset)
|
||||
{
|
||||
if (offset >= buffer->used) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void*) (((char*) buffer->array) + offset);
|
||||
}
|
||||
|
||||
void* DynamicBuffer_ReadBlockAt(dynamic_buffer_t* buffer, size_t block_size, size_t index)
|
||||
{
|
||||
return DynamicBuffer_ReadAt(buffer, block_size * index);
|
||||
}
|
||||
|
||||
int DynamicBuffer_Destroy(dynamic_buffer_t* buffer)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (buffer->allocator == NULL) {
|
||||
free(buffer->array);
|
||||
} else {
|
||||
buffer->allocator->free(buffer->allocator, buffer->array, buffer->capacity);
|
||||
}
|
||||
buffer->array = NULL;
|
||||
buffer->capacity = 0;
|
||||
buffer->used = 0;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue