Files
c-string-test/tstring.c
T

215 lines
5.1 KiB
C

#include "tstring.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int GetGlyphByteWidth(const char* glyph);
void TStringCopyGlyph(const char* glyph, int length, TString* string);
int ResizeTStringCapacity(int newTextLength, TString* string);
struct __tstring {
char* Characters;
int Length;
int ByteCount;
int Capacity;
};
TString* TStringCreate(void) {
TString* string = malloc(sizeof(TString));
if (!string) {
fprintf(stderr, "Failed to malloc space for TString. %s.\n", strerror(errno));
return NULL;
}
string->Characters = calloc(DEFAULT_TSTRING_BYTE_BUFFER, sizeof(char));
if (!string->Characters) {
fprintf(stderr, "Failed to malloc space for TString character array. %s.\n", strerror(errno));
free(string);
return NULL;
}
string->Capacity = DEFAULT_TSTRING_BYTE_BUFFER;
string->ByteCount = 0;
string->Length = 0;
return string;
}
int TStringLength(const TString* string) {
if (!string) return -1;
return string->Length;
}
int ResizeTStringCapacity(int newTextLength, TString* string) {
if (!string) return 0;
if (string->ByteCount + newTextLength < string->Capacity) return 1;
//TODO: This is a bad assumption considering the additional length could overflow without a check.
char* buffer = realloc(string->Characters, string->Capacity * 2);
if (!buffer) {
fprintf(stderr, "Failed to realloc space for text insertion. %s.\n", strerror(errno));
return 0;
}
string->Characters = buffer;
string->Capacity *= 2;
return 1;
}
void TStringRemove(int index, TString* string) {
}
void TStringInsertText(const char* text, int index, TString* string) {
if (!text || !string) return;
int textLength = strlen(text);
int glyphCount = 0;
int startByte = 0;
if (!ResizeTStringCapacity(textLength, string)) return;
while(startByte < string->ByteCount) {
if (glyphCount == index) break;
startByte += GetGlyphByteWidth(&string->Characters[startByte]);
glyphCount++;
}
}
void TStringMemSwap(const char* text, int startIndex, int length, TString* string) {
if (!text || !string) return;
char buffer[256] = { 0 };
char intermediate[sizeof buffer] = { 0 };
const char* inputTextStart = text;
const char* characterListStart = &string->Characters[startIndex];
int blockCount = length / sizeof buffer;
int remainder = length % sizeof buffer;
for(; blockCount > 0; blockCount--) {
}
}
void TStringAppendText(const char* text, TString* string) {
if (!text || !string) return;
int totalLength = strlen(text);
int glyphLength = GetGlyphByteWidth(text);
//If the two lengths are the same then that means we have a single character.
//Simply append it to the list and return.
if (totalLength == glyphLength) {
TStringCopyGlyph(text, glyphLength, string);
return;
}
//If we've made it here, than that means we have a full on string of characters.
for(int i = 0; i < totalLength;) {
TStringCopyGlyph(&text[i], glyphLength, string);
i += glyphLength;
glyphLength = GetGlyphByteWidth(&text[i]);
}
}
char* TStringGetString(const TString* string) {
if (!string) return NULL;
char* text = calloc(string->ByteCount + 1, sizeof(char));
if (!text) {
fprintf(stderr, "Failed to calloc memory for TString text. %s.\n", strerror(errno));
return NULL;
}
memcpy(text, string->Characters, string->ByteCount);
return text;
}
void TStringGetGlyph(int index, char buffer[8], const TString* string) {
if (!buffer || !string) return;
memset(buffer, '\0', sizeof *buffer);
int glyphCount = 0;
for(int i = 0; i < string->ByteCount;) {
int glyphWidth = GetGlyphByteWidth(&string->Characters[i]);
if (glyphCount == index) {
memcpy(buffer, &string->Characters[i], glyphWidth);
return;
}
glyphCount++;
i += glyphWidth;
}
}
void TStringFree(TString* string) {
if (!string) return;
if (string->Characters) free(string->Characters);
free(string);
}
int GetGlyphByteWidth(const char* glyph) {
if (!glyph) return -1;
if ((*glyph & 0x80) == 0) {
return 1;
}
else if ((*glyph & 0xE0) == 0xC0) {
return 2;
}
else if ((*glyph & 0xF0) == 0xE0) {
return 3;
}
else if ((*glyph & 0xF8) == 0xF0) {
return 4;
}
return -1;
}
void TStringCopyGlyph(const char* glyph, int length, TString* string) {
if (!glyph || !string) return;
if (length < 1) return;
if (!ResizeTStringCapacity(length, string)) return;
memcpy(&string->Characters[string->ByteCount], glyph, length);
string->ByteCount += length;
string->Length++;
}
void TStringPrintDetails(const TString* string) {
if (!string) return;
printf("Length: %d Size: %d byte(s) Capacity: %d bytes\n", string->Length, string->ByteCount, string->Capacity);
if (string->Characters) {
char* text = TStringGetString(string);
printf("%s\n", text);
free(text);
}
}