pocketlang/src/pk_buffers.h

103 lines
6.8 KiB
C
Raw Normal View History

/*
2021-06-09 18:42:26 +08:00
* Copyright (c) 2020-2021 Thakee Nathees
* Distributed Under The MIT License
*/
#ifndef BUFFERS_TEMPLATE_H
#define BUFFERS_TEMPLATE_H
#include "pk_internal.h"
2021-06-01 19:50:41 +08:00
// The macro 'DECLARE_BUFFER()' emulate the C++ template to declare and define
// different types of buffer objects.
// A buffer of type 'T' will contain a heap allocated array of 'T' with the
// capacity of 'Tbuffer.capacity' as 'T* Tbuffer.data'. When the capacity is
// filled with 'T' values (ie. Tbuffer.count == Tbuffer.capacity) the buffer's
// internal data array will be reallocate to a capacity of 'GROW_FACTOR' times
// it's last capacity.
2021-06-09 18:42:26 +08:00
#define DECLARE_BUFFER(m_name, m_type) \
typedef struct { \
m_type* data; \
uint32_t count; \
uint32_t capacity; \
2021-06-09 18:42:26 +08:00
} pk##m_name##Buffer; \
\
/* Initialize a new buffer int instance. */ \
2021-06-09 18:42:26 +08:00
void pk##m_name##BufferInit(pk##m_name##Buffer* self); \
\
/* Clears the allocated elements from the VM's realloc function. */ \
2021-06-09 18:42:26 +08:00
void pk##m_name##BufferClear(pk##m_name##Buffer* self, PKVM* vm); \
\
/* Ensure the capacity is greater than [size], if not resize. */ \
2021-06-09 18:42:26 +08:00
void pk##m_name##BufferReserve(pk##m_name##Buffer* self, PKVM* vm, \
size_t size); \
\
/* Fill the buffer at the end of it with provided data if the capacity */ \
2021-06-09 18:42:26 +08:00
/* isn't enough using VM's realloc function. */ \
void pk##m_name##BufferFill(pk##m_name##Buffer* self, PKVM* vm, \
m_type data, int count); \
\
/* Write to the buffer with provided data at the end of the buffer.*/ \
2021-06-09 18:42:26 +08:00
void pk##m_name##BufferWrite(pk##m_name##Buffer* self, \
PKVM* vm, m_type data); \
\
/* Concatenate the contents of another buffer at the end of this buffer.*/ \
void pk##m_name##BufferConcat(pk##m_name##Buffer* self, PKVM* vm, \
pk##m_name##Buffer* other); \
// The buffer "template" implementation of different types.
2021-06-09 18:42:26 +08:00
#define DEFINE_BUFFER(m_name, m_type) \
void pk##m_name##BufferInit(pk##m_name##Buffer* self) { \
self->data = NULL; \
self->count = 0; \
self->capacity = 0; \
} \
\
2021-06-09 18:42:26 +08:00
void pk##m_name##BufferClear(pk##m_name##Buffer* self, \
PKVM* vm) { \
vmRealloc(vm, self->data, self->capacity * sizeof(m_type), 0); \
self->data = NULL; \
self->count = 0; \
self->capacity = 0; \
} \
\
2021-06-09 18:42:26 +08:00
void pk##m_name##BufferReserve(pk##m_name##Buffer* self, PKVM* vm, \
size_t size) { \
if (self->capacity < size) { \
int capacity = utilPowerOf2Ceil((int)size); \
if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY; \
self->data = (m_type*)vmRealloc(vm, self->data, \
self->capacity * sizeof(m_type), capacity * sizeof(m_type)); \
self->capacity = capacity; \
} \
} \
\
2021-06-09 18:42:26 +08:00
void pk##m_name##BufferFill(pk##m_name##Buffer* self, PKVM* vm, \
m_type data, int count) { \
\
2021-06-09 18:42:26 +08:00
pk##m_name##BufferReserve(self, vm, self->count + count); \
\
for (int i = 0; i < count; i++) { \
self->data[self->count++] = data; \
} \
} \
\
2021-06-09 18:42:26 +08:00
void pk##m_name##BufferWrite(pk##m_name##Buffer* self, \
PKVM* vm, m_type data) { \
2021-06-09 18:42:26 +08:00
pk##m_name##BufferFill(self, vm, data, 1); \
} \
\
void pk##m_name##BufferConcat(pk##m_name##Buffer* self, PKVM* vm, \
pk##m_name##Buffer* other) { \
pk##m_name##BufferReserve(self, vm, self->count + other->count); \
\
memcpy(self->data + self->count, \
other->data, \
other->count * sizeof(m_type)); \
self->count += other->count; \
}
#endif // BUFFERS_TEMPLATE_H