diff --git a/src/Client/Platform.h b/src/Client/Platform.h index 18947378e..ec7be2a04 100644 --- a/src/Client/Platform.h +++ b/src/Client/Platform.h @@ -8,71 +8,44 @@ Copyright 2017 ClassicalSharp | Licensed under BSD-3 */ -/* Newline for text */ -extern UInt8* Platform_NewLine; +extern UInt8* Platform_NewLine; /* Newline for text */ extern UInt8 Platform_DirectorySeparator; extern ReturnCode ReturnCode_FileShareViolation; -/* Initalises required state for this platform. */ void Platform_Init(void); -/* Releases the resources allocated for the required state. */ void Platform_Free(void); -/* Allocates a block of memory, returning NULL on failure. */ void* Platform_MemAlloc(UInt32 numBytes); -/* Frees a previously allocated block of memory. */ +void* Platform_MemRealloc(void* mem, UInt32 numBytes); void Platform_MemFree(void* mem); -/* Sets a block of memory to the given byte value. */ void Platform_MemSet(void* dst, UInt8 value, UInt32 numBytes); -/* Copies a block of non-overlapping memory. */ void Platform_MemCpy(void* dst, void* src, UInt32 numBytes); -/* Logs a message to console (if attached). Implictly puts each entry on a newline. */ void Platform_Log(STRING_PURE String* message); -/* Gets the current time, in UTC timezone. */ DateTime Platform_CurrentUTCTime(void); -/* Gets the current time, in user's local timezone. */ DateTime Platform_CurrentLocalTime(void); -/* Returns whether a directory with the given name exists. */ bool Platform_DirectoryExists(STRING_PURE String* path); -/* Creates a new directory. */ ReturnCode Platform_DirectoryCreate(STRING_PURE String* path); -/* Returns whether a file with the given name exists. */ bool Platform_FileExists(STRING_PURE String* path); -/* Creates or overwrites an existing file. */ ReturnCode Platform_FileCreate(void** file, STRING_PURE String* path); -/* Opens an existing file. */ ReturnCode Platform_FileOpen(void** file, STRING_PURE String* path, bool readOnly); -/* Reads a block of bytes from the given file, returning a platform-specific return code. */ ReturnCode Platform_FileRead(void* file, UInt8* buffer, UInt32 count, UInt32* bytesRead); -/* Writes a block of bytes to the given file, returning a platform-specific return code. */ ReturnCode Platform_FileWrite(void* file, UInt8* buffer, UInt32 count, UInt32* bytesWritten); -/* Closes the given file. */ ReturnCode Platform_FileClose(void* file); -/* Seeks / adjusts position within the file. */ ReturnCode Platform_FileSeek(void* file, Int32 offset, Int32 seekType); -/* Returns current position/offset within the file. */ UInt32 Platform_FilePosition(void* file); -/* Returns the length of the given file. */ UInt32 Platform_FileLength(void* file); -/* Blocks the calling thread for given number of milliseconds. */ void Platform_ThreadSleep(UInt32 milliseconds); struct DrawTextArgs_; struct Bitmap_; -/* Allocates handle for the given font. */ void Platform_MakeFont(FontDesc* desc, STRING_PURE String* fontName); -/* Frees handle for the given font. */ void Platform_FreeFont(FontDesc* desc); -/* Measures size of given text.*/ Size2D Platform_MeasureText(struct DrawTextArgs_* args); -/* Draws text onto the actively selected bitmap. */ void Platform_DrawText(struct DrawTextArgs_* args, Int32 x, Int32 y); -/* Sets the bitmap used for text drawing. */ void Platform_SetBitmap(struct Bitmap_* bmp); -/* Releases the bitmap that was used for text drawing.*/ void Platform_ReleaseBitmap(void); #endif \ No newline at end of file diff --git a/src/Client/String.c b/src/Client/String.c index d864b6c7e..d88188b85 100644 --- a/src/Client/String.c +++ b/src/Client/String.c @@ -1,6 +1,7 @@ #include "String.h" #include "Funcs.h" #include "ErrorHandler.h" +#include "Platform.h" String String_Init(STRING_REF UInt8* buffer, UInt16 length, UInt16 capacity) { String str; @@ -384,6 +385,23 @@ bool Convert_TryParseBool(STRING_PURE String* str, bool* value) { #define STRINGSBUFFER_LEN_SHIFT 10 #define STRINGSBUFFER_LEN_MASK 0x3FFUL +void StringBuffers_Init(StringsBuffer* buffer) { + buffer->Count = 0; + buffer->TextBuffer = buffer->DefaultBuffer; + buffer->FlagsBuffer = buffer->DefaultFlags; + buffer->TextBufferSize = STRINGSBUFFER_DEF_BUFFER_SIZE; + buffer->FlagsBufferElems = STRINGSBUFFER_DEF_FLAGS_ELEMS; +} + +void StringsBuffer_Free(StringsBuffer* buffer) { + if (buffer->TextBufferSize > STRINGSBUFFER_DEF_BUFFER_SIZE) { + Platform_MemFree(buffer->TextBuffer); + } + if (buffer->FlagsBufferElems > STRINGSBUFFER_DEF_FLAGS_ELEMS) { + Platform_MemFree(buffer->FlagsBuffer); + } +} + void StringsBuffer_Get(StringsBuffer* buffer, UInt32 index, STRING_TRANSIENT String* text) { String raw = StringsBuffer_UNSAFE_Get(buffer, index); String_Clear(text); @@ -393,8 +411,32 @@ void StringsBuffer_Get(StringsBuffer* buffer, UInt32 index, STRING_TRANSIENT Str String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, UInt32 index) { if (index >= buffer->Count) ErrorHandler_Fail("Tried to get String past StringsBuffer end"); - UInt32 flags = buffer->FlagsBuffer[index]; + UInt32 flags = buffer->FlagsBuffer[index]; UInt32 offset = flags >> STRINGSBUFFER_LEN_SHIFT; UInt32 len = flags & STRINGSBUFFER_LEN_MASK; return String_Init(&buffer->TextBuffer[offset], (UInt16)len, (UInt16)len); +} + +void StringsBuffer_Remove(StringsBuffer* buffer, UInt32 index) { + if (index >= buffer->Count) ErrorHandler_Fail("Tried to remove String past StringsBuffer end"); + + UInt32 flags = buffer->FlagsBuffer[index]; + UInt32 offset = flags >> STRINGSBUFFER_LEN_SHIFT; + UInt32 len = flags & STRINGSBUFFER_LEN_MASK; + + UInt32 lastFlags = buffer->FlagsBuffer[buffer->Count - 1]; + UInt32 lastOffset = lastFlags >> STRINGSBUFFER_LEN_SHIFT; + UInt32 lastLen = lastFlags & STRINGSBUFFER_LEN_MASK; + + /* Imagine buffer is this: XXYYYYZZZ, and want to delete X */ + /* Start points to first character of Y */ + /* End points to last character of Z */ + UInt32 i, start = offset + len, end = lastOffset + lastLen; + for (i = start; i < end; i++) { + buffer->TextBuffer[i - len] = buffer->TextBuffer[i]; + } + for (i = index; i < buffer->Count; i++) { + buffer->FlagsBuffer[i] = buffer->FlagsBuffer[i + 1]; + } + buffer->Count--; } \ No newline at end of file diff --git a/src/Client/String.h b/src/Client/String.h index 1cf192d8c..bc6f825fe 100644 --- a/src/Client/String.h +++ b/src/Client/String.h @@ -72,14 +72,16 @@ bool Convert_TryParseUInt16(STRING_PURE String* str, UInt16* value); bool Convert_TryParseReal32(STRING_PURE String* str, Real32* value); bool Convert_TryParseBool(STRING_PURE String* str, bool* value); -/* todo use a single byte array for all strings, each 'string' is 22 bits offsrt, 10 bits length into this array. */ -/* means resizing is expensive tho*/ +#define STRINGSBUFFER_DEF_BUFFER_SIZE 4096 +#define STRINGSBUFFER_DEF_FLAGS_ELEMS 256 typedef struct StringsBuffer_ { UInt8* TextBuffer; UInt32 TextBufferSize; UInt32* FlagsBuffer; - UInt32 FlagsBufferSize; + UInt32 FlagsBufferElems; UInt32 Count; + UInt8 DefaultBuffer[STRINGSBUFFER_DEF_BUFFER_SIZE]; + UInt32 DefaultFlags[STRINGSBUFFER_DEF_FLAGS_ELEMS]; } StringsBuffer; void StringBuffers_Init(StringsBuffer* buffer); diff --git a/src/Client/WinPlatform.c b/src/Client/WinPlatform.c index a2120502c..bf9063b18 100644 --- a/src/Client/WinPlatform.c +++ b/src/Client/WinPlatform.c @@ -61,6 +61,10 @@ void* Platform_MemAlloc(UInt32 numBytes) { return HeapAlloc(heap, 0, numBytes); } +void* Platform_MemRealloc(void* mem, UInt32 numBytes) { + return HeapReAlloc(heap, 0, mem, numBytes); +} + void Platform_MemFree(void* mem) { HeapFree(heap, 0, mem); } @@ -188,13 +192,15 @@ void Platform_ThreadSleep(UInt32 milliseconds) { } -void Platform_MakeFont(FontDesc* desc) { +void Platform_MakeFont(FontDesc* desc, STRING_PURE String* fontName) { LOGFONTA font = { 0 }; font.lfHeight = -Math_Ceil(desc->Size * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0f); font.lfUnderline = desc->Style == FONT_STYLE_UNDERLINE; font.lfWeight = desc->Style == FONT_STYLE_BOLD ? FW_BOLD : FW_NORMAL; font.lfQuality = ANTIALIASED_QUALITY; + String dstName = String_Init(font.lfFaceName, 0, LF_FACESIZE); + String_AppendString(&dstName, fontName); desc->Handle = CreateFontIndirectA(&font); if (desc->Handle == NULL) ErrorHandler_Fail("Creating font handle failed"); } @@ -204,6 +210,7 @@ void Platform_FreeFont(FontDesc* desc) { desc->Handle = NULL; } +/* TODO: Associate Font with device */ Size2D Platform_MeasureText(struct DrawTextArgs_* args) { HDC hDC = GetDC(NULL); RECT r = { 0 };