Files
Main/support/arcade/buffer.cpp
2019-12-12 03:43:49 +08:00

195 lines
5.3 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include <limits.h>
#include "buffer.h"
////////////////////////////////////////////////////////////////////////////////
//
// Function buffer_init
//
// Purpose:
//
// This function will return a struct with the values it needs before it
// can be used with buffer_append. The default "expand_length" is
//
// Parameters:
//
// initial_size (IN) This parameter will preallocate the buffer with this
// size in bytes.
//
// Returns:
//
// returns a struct, or NULL on error
//
// Error Definitions:
//
// NULL = Couldn't create the structure
//
////////////////////////////////////////////////////////////////////////////////
buffer_data * buffer_init(unsigned int initial_size) {
buffer_data * buffer = NULL;
// only allow max initial size of SIZE_MAX
if (initial_size > 65535) {
return NULL;
}
// malloc the space for a pointer to a buffer_data
buffer = (buffer_data *)malloc(sizeof(buffer_data));
if (buffer == NULL) {
return NULL;
}
// fill the struct up
buffer->expand_length = initial_size;
buffer->capacity = initial_size;
buffer->length = 0;
// allocate the buffer space
buffer->content = (char *)malloc(sizeof(char) * initial_size);
buffer->content[0] = 0;
if (buffer->content == NULL) {
// can't allocate the buffer, therefore we need to clean everything up
free(buffer);
return NULL;
}
// return a pointer to our buffer_data structure
return buffer;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function buffer_append
//
// Purpose:
//
// This function will take data and append it into a buffer in the struct
// given. It will growing as required (or as allowed by realloc) by the
// length desired in the structure element "expand_length" plus the length
// of the data being appended. If additional expansion is not desired, you
// can set the struct element "expand_length" to zero.
//
// Parameters:
//
// buffer_data (IN/OUT) This parameter is a struct (mapped below) to
// keep track of the internal buffer and its working parameters.
//
// typedef struct {
// unsigned int length; // the current length of the content in bytes
// unsigned int capacity; // the total capacity of "content" in bytes
// unsigned int expand_length; // the amount to expand the buffer on resize
// char * content; // the target for appending data
// } buffer_data;
//
//
// append_data (IN) This parameter is a const char * that is the data
// to be appended.
//
// Returns:
//
// This function will return the amount of bytes appended. If the
// return value is <= 0 there was an error.
//
// Error Definitions:
//
// -1 = No data was given to append
// -2 = Additional space could not be allocated for the buffer.
//
////////////////////////////////////////////////////////////////////////////////
int buffer_append(buffer_data * buffer, const char * append_data) {
// ensure there IS something to append..
const unsigned int append_len = strlen(append_data);
if (append_len < 1) {
return -1;
}
// is there enough space, or should we reallocate memory?
if (buffer->length + append_len > buffer->capacity) {
const unsigned int realloc_size =
buffer->capacity + append_len + buffer->expand_length;
// allocate the new buffer
char *new_buffer = (char *)realloc(buffer->content, realloc_size);
// resize success..
if (new_buffer == NULL) {
return -2;
}
// copy the data to append into the new content buffer
strcat(new_buffer, append_data);
// update the struct with the new values
buffer->content = new_buffer; // new buffer content
buffer->capacity = realloc_size; // add the amount to expand beyond our initial needs
buffer->length = buffer->length + append_len;
}
else {
// append the string
strcat(buffer->content, append_data);
}
// update the buffer length
buffer->length += append_len;
// return the amount appended
return append_len;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function buffer_destroy
//
// Purpose:
//
// This function will destroy the inner buffer and reset all of the data
// if the struct was dynamically allocated, it is expected that you will
// take care of freeing the data.
//
// Parameters:
//
// buffer_data (IN) This parameter is a struct (mapped below) to
// keep track of the internal buffer and its working parameters.
//
// typedef struct {
// unsigned int length; // the current length of the content in bytes
// unsigned int capacity; // the total capacity of "content" in bytes
// unsigned int expand_length; // the amount to expand the buffer on resize
// char * content; // the target for appending data
// } buffer_data;
//
// Returns:
//
// returns nothing
//
////////////////////////////////////////////////////////////////////////////////
void buffer_destroy(buffer_data * buffer) {
// only work with valid data..
if (buffer != NULL) {
// if the content is not null, free it.
if (buffer->content != NULL) {
free(buffer->content);
}
// free the buffer
free(buffer);
}
}