#include "tstring.h" #include #include #include #include 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); } }