Added Makefile.

This commit is contained in:
2022-07-08 13:26:04 +00:00
parent 26e18bb798
commit cc4e2b3ad0
7 changed files with 32 additions and 1 deletions
+56
View File
@@ -0,0 +1,56 @@
#include "futil.h"
int ReadAllString(const char* path, char** content_ptr, size_t* bytes_read) {
if (!path || !content_ptr || !bytes_read) return 0;
FILE *file = fopen(path, "rb"); //Always open the file in binary mode.
if (!file) {
fprintf(stderr, "Failed to open '%s'. %s.\n", path, strerror(errno));
return 0;
}
char *content = NULL, *temp;
size_t used = 0, capacity = 0, read = 0; //Allows initialize stack allocated values to zero!
while(1) {
if (used + FUTIL_READ_SIZE + 1 > capacity) {
capacity = used + FUTIL_READ_SIZE + 1;
temp = realloc(content, capacity);
if (!temp) {
fprintf(stderr, "Failed to realloc space for file contents. %s.\n", strerror(errno));
free(content);
fclose(file);
return 0;
}
content = temp;
}
read = fread(content + used, 1, FUTIL_READ_SIZE, file);
if (read == 0) break;
used += read;
}
fclose(file);
//Shrink the buffer to fit just the contents of the buffer.
temp = realloc(content, used + 1);
if (!temp) {
fprintf(stderr, "Failed to realloc to only hold the file contents. %s.\n", strerror(errno));
free(content);
return 0;
}
content = temp;
content[used] = '\0';
*content_ptr = content;
*bytes_read = used;
return 1;
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef FUTIL_H
#define FUTIL_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifndef FUTIL_READ_SIZE
#define FUTIL_READ_SIZE 2097152 //Default here is 2MiB
#endif
int ReadAllString(const char*, char**, size_t*);
#endif
+111
View File
@@ -0,0 +1,111 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tstring.h"
#include "futil.h"
int main(int argc, char** argv) {
char input[1024] = { 0 };
char glyph[8] = { 0 };
char* file;
size_t bytesRead;
TString* string = TStringCreate();
while(1) {
printf("> ");
fgets(input, sizeof input, stdin);
input[strlen(input) - 1] = '\0';
if (input[0] == 'q') break;
if (input[0] == 'p') {
if (input[1] == '\0') TStringPrintDetails(string, 0);
else TStringPrintDetails(string, 1);
continue;
}
if (input[0] == 'i') {
printf("Select index: ");
fgets(input, sizeof input, stdin);
int num = strtol(input, NULL, 10);
printf("Enter text to insert at index %d: ", num);
fgets(input, sizeof input, stdin);
input[strlen(input) - 1] = '\0';
TStringInsertText(input, num, string);
continue;
}
if (input[0] == 'f') {
printf("Enter file path to open: ");
fgets(input, sizeof input, stdin);
input[strlen(input) - 1] = '\0';
if (ReadAllString(input, &file, &bytesRead)) {
TStringAppendText(file, string);
printf("Read %ld byte(s)\n", bytesRead);
free(file);
}
continue;
}
if (input[0] == 'r') {
if (input[1] != '\0') {
printf("Select index: ");
fgets(input, sizeof input, stdin);
int num = strtol(input, NULL, 10);
printf("Enter count: ");
fgets(input, sizeof input, stdin);
int count = strtol(input, NULL, 10);
TStringRemoveRange(num, count, string);
continue;
}
TStringPop(glyph, string);
printf("Popped '%s'\n", glyph);
continue;
}
if (input[0] == 'g') {
if (input[1] != '\0') {
printf("Select index: ");
fgets(input, sizeof input, stdin);
int num = strtol(input, NULL, 10);
printf("Enter count: ");
fgets(input, sizeof input, stdin);
int count = strtol(input, NULL, 10);
char* text = TStringGetStringRange(num, count, string);
printf("Returned String:\n'%s'\n", text);
free(text);
continue;
}
}
TStringAppendText(input, string);
}
//fgets(glyph, 10, stdin);
//glyph[strlen(glyph) - 1] = 0;
//printf("Width %d byte(s).\n", GetGlyphByteWidth(glyph));
TStringFree(string);
}
+324
View File
@@ -0,0 +1,324 @@
#include "tstring.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
void TStringCopyGlyph(const char* glyph, int length, TString* string);
int ResizeTStringCapacity(int newTextLength, TString* string);
int GetGlyphByteWidth(char glyph);
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 additionalLength, TString* string) {
if (!string) return 0;
if (string->ByteCount + additionalLength < string->Capacity) return 1;
unsigned int newCapacity = string->Capacity;
while (additionalLength > newCapacity) newCapacity = string->Capacity * 2;
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 TStringPop(char buffer[8], TString* string) {
if (!string) return;
if (string->ByteCount == 0) return;
for (int i = string->ByteCount - 1; i >= 0; i--) {
unsigned int width = GetGlyphByteWidth(string->Characters[i]);
if (width > 0) {
//If we've been provided a buffer, then populate it with the glyph we're removing.
if (buffer) {
memset(buffer, '\0', 8);
memcpy(buffer, &string->Characters[i], width);
}
memset(&string->Characters[i], '\0', width);
string->Length--;
string->ByteCount -= width;
break;
}
}
}
void TStringRemoveRange(int startIndex, int count, TString* string) {
if (!string) return;
if (startIndex < 0 || startIndex > string->Length) return;
if (count <= 0 || count > string->Length - startIndex) return;
char buffer[4] = { 0 };
unsigned int startByte = 0;
unsigned int glyphCount = 0;
while(glyphCount != startIndex) {
startByte += GetGlyphByteWidth(string->Characters[startByte]);
glyphCount++;
}
unsigned int endByte = startByte;
for (glyphCount = 0; glyphCount < count; glyphCount++) endByte += GetGlyphByteWidth(string->Characters[endByte]);
if (endByte == string->ByteCount) {
memset(&string->Characters[startByte], '\0', endByte - startByte);
string->Length -= glyphCount;
string->ByteCount -= endByte - startByte;
return;
}
unsigned int fullBuffers = (string->ByteCount - endByte) / sizeof buffer;
unsigned int remainder = (string->ByteCount - endByte) - fullBuffers * sizeof buffer;
printf("Remainder: %d; full buffers: %d; endbyte : %d\n", remainder, fullBuffers, endByte);
for (int i = 0; i < fullBuffers; i++) {
memcpy(buffer, &string->Characters[endByte + i * sizeof buffer], sizeof buffer);
printf("Buffer: %s\n", buffer);
memcpy(&string->Characters[startByte + sizeof buffer * i], buffer, sizeof buffer);
}
if (remainder > 0) {
memcpy(buffer, &string->Characters[string->ByteCount - remainder], remainder);
printf("Buffer: %s\n", buffer);
memcpy(&string->Characters[startByte + fullBuffers * sizeof buffer], buffer, remainder);
}
memset(&string->Characters[string->ByteCount - endByte - startByte], '\0', endByte - startByte);
string->Length -= glyphCount;
string->ByteCount -= endByte - startByte;
}
void TStringInsertText(const char* text, int index, TString* string) {
if (!text || !string) return;
if (index < 0 || index > string->Length) index = string->Length;
unsigned int insertionTextLength = strlen(text);
unsigned int startByte = 0;
unsigned int endByte = string->ByteCount + insertionTextLength;
if (!ResizeTStringCapacity(insertionTextLength, string)) return;
char buffer[256] = { 0 };
for (int glyphCount = 0; glyphCount != index; glyphCount++) startByte += GetGlyphByteWidth(string->Characters[startByte]);
for (unsigned int offset = 0; offset < insertionTextLength; string->Length++) offset += GetGlyphByteWidth(text[offset]);
unsigned int fullBuffers = (string->ByteCount - startByte) / sizeof buffer;
unsigned int remainder = (string->ByteCount - startByte) - fullBuffers * sizeof buffer;
for (int i = fullBuffers; i > 0; i--) {
memcpy(buffer, &string->Characters[string->ByteCount - i * sizeof buffer], sizeof buffer);
memcpy(&string->Characters[endByte - sizeof buffer * i], buffer, sizeof buffer);
}
if (remainder > 0) {
memcpy(buffer, &string->Characters[startByte], remainder);
memcpy(&string->Characters[insertionTextLength + startByte], buffer, remainder);
}
memcpy(&string->Characters[startByte], text, insertionTextLength);
string->ByteCount += insertionTextLength;
}
void TStringAppendText(const char* text, TString* string) {
if (!text || !string) return;
int totalLength = strlen(text);
int glyphLength = GetGlyphByteWidth(text[0]);
//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;
}
char* TStringGetStringRange(int startIndex, int count, const TString* string) {
if (!string) return NULL;
if (startIndex < 0 || startIndex >= string->Length) return NULL;
if (count > string->Length) 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;
}
unsigned int startByte = 0;
unsigned int glyphCount = 0;
while(glyphCount != startIndex) {
startByte += GetGlyphByteWidth(string->Characters[startByte]);
glyphCount++;
}
unsigned int endByte = startByte;
for (glyphCount = 0; glyphCount < count && endByte <= string->ByteCount; glyphCount++) endByte += GetGlyphByteWidth(string->Characters[endByte]);
memcpy(text, &string->Characters[startByte], endByte - startByte);
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(char glyph) {
//ANDing 0x80 (1000 0000) should result in 0 if this code point is 1 byte long.
if ((glyph & 0x80) == 0) return 1;
//ANDing 0xE0 (1110 0000) will result in 0xC0 (1100 0000) if this code point is 2 bytes long.
if ((glyph & 0xE0) == 0xC0) return 2;
//ANDing 0xF0 (1111 0000) will result in 0xE0 (1110 0000) if this code point is 3 bytes long.
if ((glyph & 0xF0) == 0xE0) return 3;
//ANDing 0xE0 (1111 1000) will result in 0xF0 (1111 0000) if this code point is 4 bytes long.
if ((glyph & 0xF8) == 0xF0) return 4;
//Else we either have a continuation point (pattern: 10XX XXXX) or its just a junk value
//as far as we're concerned.
return 0;
}
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, int statsOnly) {
if (!string) return;
printf("Stats: Length %d; Size %d byte(s); Capacity: %d bytes\n", string->Length, string->ByteCount, string->Capacity);
if (statsOnly) return;
printf("Stored String:\n");
if (string->Characters) {
char* text = TStringGetString(string);
printf("%s\n", text);
free(text);
}
printf("\nBytes:\n");
for(int i = 0; i < string->Capacity; i++) {
if (i != 0 && i % 80 == 0) printf("\n");
printf("%02X ", string->Characters[i] & 0xFF);
}
printf("\n");
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef TSTRING_H
#define TSTRING_H
#ifndef DEFAULT_TSTRING_BYTE_BUFFER
#define DEFAULT_TSTRING_BYTE_BUFFER 32
#endif
typedef struct __tstring TString;
TString* TStringCreate(void);
void TStringAppendText(const char* text, TString* string);
void TStringGetGlyph(int index, char buffer[8], const TString* string);
void TStringFree(TString* string);
void TStringPrintDetails(const TString* string, int statsOnly);
void TStringInsertText(const char* text, int index, TString* string);
void TStringPop(char buffer[8], TString* string);
void TStringRemoveRange(int startIndex, int count, TString* string);
char* TStringGetString(const TString* string);
char* TStringGetStringRange(int startIndex, int count, const TString* string);
int TStringLength(const TString* string);
#endif