Files
cAI/cKit/Foundation/c_StringBuffer.c
T

162 lines
5.2 KiB
C
Raw Normal View History

2026-08-10 01:21:15 +08:00
#include <c_StringBuffer.h>
#include <c_Memory.h>
#define DEFAULT_INIT_CAPACITY 16
C_STATIC_FORCE_INLINE
c_err_t c_StringBuffer_EnsureCapacity(c_StringBuffer_t* self, c_size_t required_len) {
c_size_t needed_capacity = self->size + required_len + 1; // +1 for trailing '\0'
if (needed_capacity <= self->capacity) {
return C_ERR_OK;
}
c_size_t new_capacity = self->capacity == 0 ? DEFAULT_INIT_CAPACITY : self->capacity;
while (new_capacity < needed_capacity) {
new_capacity *= 2; // Exponential doubling strategy
}
char* new_buffer = (char*)C_ALLOC(new_capacity);
if (!new_buffer) {
return C_ERR_NOMEM;
}
if (self->buffer && self->size > 0) {
memcpy(new_buffer, self->buffer, self->size);
}
new_buffer[self->size] = '\0';
C_FREE(self->buffer);
self->buffer = new_buffer;
self->capacity = new_capacity;
return C_ERR_OK;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
c_err_t c_StringBuffer_Init(c_StringBuffer_t* self, c_size_t capacity) {
if (!self) return C_ERR_PARAM;
self->size = 0;
self->capacity = capacity > 0 ? capacity : DEFAULT_INIT_CAPACITY; // Enforce minimum initial allocation
self->buffer = (char*)C_ALLOC(self->capacity);
if (!self->buffer) {
self->capacity = 0;
return C_ERR_NOMEM;
}
self->buffer[0] = '\0';
return C_ERR_OK;
}
void c_StringBuffer_Destroy(c_StringBuffer_t* self) {
if (!self) return;
if (self->buffer) {
C_FREE(self->buffer);
}
self->size = 0;
self->capacity = 0;
}
c_err_t c_StringBuffer_Append(c_StringBuffer_t* self, const char* string, c_size_t length) {
if (!self || !self->buffer || !string || length == 0) return C_ERR_PARAM;
c_err_t err = c_StringBuffer_EnsureCapacity(self, length);
if (err != C_ERR_OK) return err;
memcpy(self->buffer + self->size, string, length);
self->size += length;
self->buffer[self->size] = '\0';
return C_ERR_OK;
}
c_err_t c_StringBuffer_Prepend(c_StringBuffer_t* self, const char* string, c_size_t length) {
return c_StringBuffer_InsertAt(self, 0, string, length);
}
c_err_t c_StringBuffer_InsertAt(c_StringBuffer_t* self, c_size_t index, const char* string, c_size_t length) {
if (!self || !self->buffer || !string || length == 0 || index > self->size) return C_ERR_PARAM;
c_err_t err = c_StringBuffer_EnsureCapacity(self, length);
if (err != C_ERR_OK) return err;
// Shift memory to the right using memmove to prevent overlapping issues
memmove(self->buffer + index + length, self->buffer + index, self->size - index);
memcpy(self->buffer + index, string, length);
self->size += length;
self->buffer[self->size] = '\0';
return C_ERR_OK;
}
c_err_t c_StringBuffer_RemoveAt(c_StringBuffer_t* self, c_size_t index, c_size_t length) {
if (!self || !self->buffer || length == 0 || index >= self->size) return C_ERR_PARAM;
// Clamp length if it attempts to read past the end of the current buffer
if (index + length > self->size) {
length = self->size - index;
}
// Shift trailing memory to the left to close the character gap
memmove(self->buffer + index, self->buffer + index + length, self->size - (index + length));
self->size -= length;
self->buffer[self->size] = '\0';
return C_ERR_OK;
}
void c_StringBuffer_Clear(c_StringBuffer_t* self) {
if (!self || !self->buffer) return;
self->size = 0;
self->buffer[0] = '\0';
}
/* --- Explicit String-Wrapper Interfaces --- */
c_err_t c_StringBuffer_AppendStr(c_StringBuffer_t* self, const char* string) {
if (!string) return C_ERR_PARAM;
return c_StringBuffer_Append(self, string, strlen(string));
}
c_err_t c_StringBuffer_PrependStr(c_StringBuffer_t* self, const char* string) {
if (!string) return C_ERR_PARAM;
return c_StringBuffer_Prepend(self, string, strlen(string));
}
c_err_t c_StringBuffer_InsertStrAt(c_StringBuffer_t* self, const char* string, c_size_t index) {
if (!string) return C_ERR_PARAM;
return c_StringBuffer_InsertAt(self, index, string, strlen(string));
}
c_err_t c_StringBuffer_CopyTo(c_StringBuffer_t* self, c_size_t index, c_size_t length, char* buffer, c_size_t buffer_length) {
// 1. Guard against invalid pointers, empty destinations, or index out-of-bounds
if (!self || !self->buffer || !buffer || buffer_length == 0 || index > self->size) {
return C_ERR_PARAM;
}
// 2. Clamp requested copy length if it exceeds the remaining data payload bounds
if (index + length > self->size) {
length = self->size - index;
}
// 3. Enforce destination buffer capacity threshold checks
// The requested segment requires at least (length + 1) bytes for safe null-termination
if (length >= buffer_length) {
return C_ERR_PARAM; // Destination buffer is too small to store the segment safely
}
// 4. Perform the raw memory copy if there are valid characters to process
if (length > 0) {
memcpy(buffer, self->buffer + index, length);
}
// 5. Always apply a deterministic trailing null terminator
buffer[length] = '\0';
return C_ERR_OK;
}