mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-06 12:46:53 +08:00
c58159b63d
* fixed typos in src/ * fixed typos in docs/ * fixed typos in README and tests/ * rename INITALIZE to INITIALIZE * rename PRIMITE to PRIMITIVE * rename moudle to module Co-authored-by: Alexander Patel <acpatel@andrew.cmu.edu>
89 lines
5.8 KiB
C
89 lines
5.8 KiB
C
/*
|
|
* Copyright (c) 2020-2021 Thakee Nathees
|
|
* Distributed Under The MIT License
|
|
*/
|
|
|
|
#ifndef BUFFERS_TEMPLATE_H
|
|
#define BUFFERS_TEMPLATE_H
|
|
|
|
#include "pk_common.h"
|
|
|
|
// 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.
|
|
|
|
#define DECLARE_BUFFER(m_name, m_type) \
|
|
typedef struct { \
|
|
m_type* data; \
|
|
uint32_t count; \
|
|
uint32_t capacity; \
|
|
} pk##m_name##Buffer; \
|
|
\
|
|
/* Initialize a new buffer int instance. */ \
|
|
void pk##m_name##BufferInit(pk##m_name##Buffer* self); \
|
|
\
|
|
/* Clears the allocated elements from the VM's realloc function. */ \
|
|
void pk##m_name##BufferClear(pk##m_name##Buffer* self, PKVM* vm); \
|
|
\
|
|
/* Ensure the capacity is greater than [size], if not resize. */ \
|
|
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 */ \
|
|
/* 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.*/ \
|
|
void pk##m_name##BufferWrite(pk##m_name##Buffer* self, \
|
|
PKVM* vm, m_type data); \
|
|
|
|
// The buffer "template" implementation of diferent types.
|
|
#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; \
|
|
} \
|
|
\
|
|
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; \
|
|
} \
|
|
\
|
|
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; \
|
|
} \
|
|
} \
|
|
\
|
|
void pk##m_name##BufferFill(pk##m_name##Buffer* self, PKVM* vm, \
|
|
m_type data, int count) { \
|
|
\
|
|
pk##m_name##BufferReserve(self, vm, self->count + count); \
|
|
\
|
|
for (int i = 0; i < count; i++) { \
|
|
self->data[self->count++] = data; \
|
|
} \
|
|
} \
|
|
\
|
|
void pk##m_name##BufferWrite(pk##m_name##Buffer* self, \
|
|
PKVM* vm, m_type data) { \
|
|
pk##m_name##BufferFill(self, vm, data, 1); \
|
|
} \
|
|
|
|
#endif // BUFFERS_TEMPLATE_H
|