#include #include #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; }