Files
Xmd/libXmd/src/Buffer.c
T

109 lines
2.5 KiB
C

#include <Xmd/Buffer.h>
#include <string.h>
#include <stdio.h>
#define XmdBUFFER_GROWTH_FACTOR 2
#define XmdBUFFER_INITIAL_CAPACITY 8
struct _XmdBuffer {
void * data;
Cardinal size;
Cardinal length;
Cardinal capacity;
};
static void XmdBufferResize (XmdBuffer *buffer, Cardinal length);
static void XmdBufferFit (XmdBuffer *buffer);
static void *XmdBufferOffset (XmdBuffer *buffer, Cardinal index);
XmdBuffer *_XmdBufferNew (Cardinal size) {
XmdBuffer *buffer = XtNew(XmdBuffer);
if (buffer == NULL) return NULL;
buffer->size = size;
buffer->length = 0;
buffer->capacity = XmdBUFFER_INITIAL_CAPACITY;
buffer->data = XtCalloc(buffer->capacity, buffer->size);
if (buffer->data == NULL) {
XmdBufferFree(buffer);
return NULL;
}
XmdBufferFit(buffer);
return buffer;
}
void XmdBufferResize (XmdBuffer *buffer, Cardinal length) {
buffer->length = length;
XmdBufferFit(buffer);
}
void XmdBufferFit (XmdBuffer *buffer) {
if (buffer->length > buffer->capacity) {
buffer->capacity *= XmdBUFFER_GROWTH_FACTOR;
void *data = XtRealloc (
buffer->data,
buffer->capacity *
buffer->size);
if (data == NULL) {
/* TODO return error */
}
buffer->data = data;
}
}
void *XmdBufferOffset (XmdBuffer *buffer, Cardinal index) {
char *data = buffer->data;
return (void *)(data + ((size_t)(index) * buffer->size));
}
void XmdBufferPush (XmdBuffer *buffer, void *element) {
Cardinal index = buffer->length;
XmdBufferResize(buffer, buffer->length + 1);
XmdBufferPoke(buffer, index, element);
}
void XmdBufferPop (XmdBuffer *buffer, void *element) {
Cardinal index = buffer->length - 1;
XmdBufferPeek(buffer, index, element);
XmdBufferResize(buffer, index);
}
void XmdBufferPoke (XmdBuffer *buffer, Cardinal index, void *element) {
if (index > buffer->length) return;
char *destination = XmdBufferOffset(buffer, index);
char *source = element;
if (source == NULL) {
memset(destination, 0, buffer->size);
} else {
memcpy(destination, source, buffer->size);
}
}
void XmdBufferPeek (XmdBuffer *buffer, Cardinal index, void *element) {
if (index > buffer->length) return;
if (element == NULL) return;
memcpy (
element,
XmdBufferOffset(buffer, index),
buffer->size);
}
void *XmdBufferBreak (XmdBuffer *buffer) {
void *data = buffer->data;
XtFree((char *)(buffer));
return data;
}
Cardinal XmdBufferLength (XmdBuffer *buffer) {
return buffer->length;
}
void XmdBufferFree (XmdBuffer *buffer) {
if (buffer->data != NULL) {
XtFree(buffer->data);
}
XtFree((char *)(buffer));
}