diff --git a/src/Client/Options.c b/src/Client/Options.c index e4fcbe8e2..6a7b8732a 100644 --- a/src/Client/Options.c +++ b/src/Client/Options.c @@ -2,54 +2,47 @@ #include "ExtMath.h" #include "ErrorHandler.h" #include "Utils.h" - -UInt8 Options_KeysBuffer[String_BufferSize(26) * OPTIONS_COUNT]; -UInt8 Options_ValuesBuffer[ - String_BufferSize(8) * OPTIONS_TINYSTRS + - String_BufferSize(16) * OPTIONS_SMALLSTRS + - String_BufferSize(32) * OPTIONS_MEDSTRS + - String_BufferSize(512) * OPTIONS_LARGESTRS -]; - -#define Options_InitStrs(strArray, count, elemLen)\ -for (i = 0; i < count; i++, j++) {\ - strArray[j] = String_FromEmptyBuffer(buffer, elemLen);\ - buffer += String_BufferSize(elemLen);\ -} +#include "Funcs.h" +#define OPT_NOT_FOUND UInt32_MaxValue void Options_Init(void) { - Int32 i, j = 0; - UInt8* buffer = Options_KeysBuffer; - Options_InitStrs(Options_Keys, OPTIONS_COUNT, 24); - - j = 0; - buffer = Options_ValuesBuffer; - Options_InitStrs(Options_Values, OPTIONS_TINYSTRS, 8); - Options_InitStrs(Options_Values, OPTIONS_SMALLSTRS, 16); - Options_InitStrs(Options_Values, OPTIONS_MEDSTRS, 32); - Options_InitStrs(Options_Values, OPTIONS_LARGESTRS, 512); + StringBuffers_Init(&Options_Keys); + StringBuffers_Init(&Options_Values); } -Int32 Options_Find(String key) { - Int32 i; - for (i = 0; i < OPTIONS_COUNT; i++) { - if (String_CaselessEquals(&Options_Keys[i], &key)) return i; +void Options_Free(void) { + StringsBuffer_Free(&Options_Keys); + StringsBuffer_Free(&Options_Values); +} + +UInt32 Options_Find(String key) { + UInt32 i; + for (i = 0; i < Options_Keys.Count; i++) { + String curKey = StringsBuffer_UNSAFE_Get(&Options_Keys, i); + if (String_CaselessEquals(&curKey, &key)) return i; } - return -1; + return OPT_NOT_FOUND; } -bool Options_TryGetValue(const UInt8* keyRaw, String* value) { +bool Options_TryGetValue(const UInt8* keyRaw, STRING_TRANSIENT String* value) { String key = String_FromReadonly(keyRaw); *value = String_MakeNull(); - Int32 i = Options_Find(key); - if (i >= 0) { *value = Options_Values[i]; return true; } + + UInt32 i = Options_Find(key); + if (i != OPT_NOT_FOUND) { + *value = StringsBuffer_UNSAFE_Get(&Options_Values, i); + return true; + } Int32 sepIndex = String_IndexOf(&key, '-', 0); if (sepIndex == -1) return false; - key = String_UNSAFE_SubstringAt(&key, sepIndex + 1); + i = Options_Find(key); - if (i >= 0) { *value = Options_Values[i]; return true; } + if (i != OPT_NOT_FOUND) { + *value = StringsBuffer_UNSAFE_Get(&Options_Values, i); + return true; + } return false; } @@ -94,48 +87,41 @@ UInt32 Options_GetEnum(const UInt8* key, UInt32 defValue, const UInt8** names, U return Utils_ParseEnum(&str, defValue, names, namesCount); } -void Options_Remove(Int32 i) { - String_Clear(&Options_Keys[i]); - String_Clear(&Options_Values[i]); +void Options_Remove(UInt32 i) { + StringsBuffer_Remove(&Options_Keys, i); + StringsBuffer_Remove(&Options_Values, i); } Int32 Options_Insert(String key, String value) { - Int32 i = Options_Find(key); - /* The new value may not fit in the old slot, always insert into a new slot. */ - if (i >= 0) { + UInt32 i = Options_Find(key); + if (i != OPT_NOT_FOUND) { Options_Remove(i); - Options_Changed[i] = false; + /* Reset Changed state for this option */ + for (; i < Array_NumElements(Options_Changed) - 1; i++) { + Options_Changed[i] = Options_Changed[i + 1]; + } } - for (i = 0; i < OPTIONS_COUNT; i++) { - if (Options_Keys[i].length > 0) continue; - if (Options_Values[i].capacity < value.length) continue; - - String_AppendString(&Options_Keys[i], &key); - String_AppendString(&Options_Values[i], &value); - return i; - } - - ErrorHandler_Fail("No free slot left to save option"); - return -1; + StringsBuffer_Add(&Options_Keys, &key); + StringsBuffer_Add(&Options_Values, &value); + return Options_Keys.Count; } void Options_SetInt32(const UInt8* keyRaw, Int32 value) { UInt8 numBuffer[String_BufferSize(STRING_INT32CHARS)]; - UInt8* ptr = numBuffer; - String numStr = String_FromRawBuffer(ptr, STRING_INT32CHARS); + String numStr = String_FromRawBuffer(numBuffer, STRING_INT32CHARS); String_AppendInt32(&numStr, value); Options_Set(keyRaw, numStr); } void Options_Set(const UInt8* keyRaw, STRING_PURE String value) { String key = String_FromReadonly(keyRaw); - Int32 i; + UInt32 i; if (value.buffer == NULL) { i = Options_Find(key); - if (i >= 0) Options_Remove(i); + if (i != OPT_NOT_FOUND) Options_Remove(i); } else { i = Options_Insert(key, value); } - if (i >= 0) Options_Changed[i] = true; + if (i != OPT_NOT_FOUND) Options_Changed[i] = true; } \ No newline at end of file diff --git a/src/Client/Options.h b/src/Client/Options.h index 0057d7286..8f283e281 100644 --- a/src/Client/Options.h +++ b/src/Client/Options.h @@ -70,18 +70,14 @@ typedef UInt8 FpsLimitMethod; #define OptionsKey_AllowClassicHacks "nostalgia-hacks" #define OptionsKey_ClassicArmModel "nostalgia-classicarm" -#define OPTIONS_LARGESTRS 4 -#define OPTIONS_MEDSTRS 16 -#define OPTIONS_SMALLSTRS 32 -#define OPTIONS_TINYSTRS 64 -#define OPTIONS_COUNT (OPTIONS_LARGESTRS + OPTIONS_MEDSTRS + OPTIONS_SMALLSTRS + OPTIONS_TINYSTRS) - -String Options_Keys[OPTIONS_COUNT]; -String Options_Values[OPTIONS_COUNT]; -bool Options_Changed[OPTIONS_COUNT]; +StringsBuffer Options_Keys; +StringsBuffer Options_Values; +bool Options_Changed[256]; void Options_Init(void); +void Options_Free(void); +/* TODO: eliminate this and use STRING_TRANSIENT ARG */ String Options_Get(const UInt8* key); Int32 Options_GetInt(const UInt8* key, Int32 min, Int32 max, Int32 defValue); bool Options_GetBool(const UInt8* key, bool defValue); diff --git a/src/Client/String.c b/src/Client/String.c index 56480d04e..68bcb43ad 100644 --- a/src/Client/String.c +++ b/src/Client/String.c @@ -2,7 +2,7 @@ #include "Funcs.h" #include "ErrorHandler.h" -String String_FromEmptyBuffer(UInt8* buffer, UInt16 capacity) { +String String_FromEmptyBuffer(STRING_REF UInt8* buffer, UInt16 capacity) { String str; str.buffer = buffer; str.capacity = capacity; @@ -10,7 +10,7 @@ String String_FromEmptyBuffer(UInt8* buffer, UInt16 capacity) { return str; } -String String_FromRawBuffer(UInt8* buffer, UInt16 capacity) { +String String_FromRawBuffer(STRING_REF UInt8* buffer, UInt16 capacity) { String str = String_FromEmptyBuffer(buffer, capacity); Int32 i; @@ -19,7 +19,7 @@ String String_FromRawBuffer(UInt8* buffer, UInt16 capacity) { return str; } -String String_FromReadonly(const UInt8* buffer) { +String String_FromReadonly(STRING_REF const UInt8* buffer) { UInt16 length = 0; UInt8* cur = buffer; while ((*cur) != NULL) { cur++; length++; } @@ -385,14 +385,20 @@ bool Convert_TryParseBool(STRING_PURE String* str, bool* value) { #define STRINGSBUFFER_LEN_SHIFT 10 #define STRINGSBUFFER_LEN_MASK 0x3FFUL void StringsBuffer_Get(StringsBuffer* buffer, UInt32 index, STRING_TRANSIENT String* text) { - if (index >= buffer->Count) ErrorHandler_Fail("Tried to get String past StringsBuffer end"); + String raw = StringsBuffer_UNSAFE_Get(buffer, index); String_Clear(text); + String_AppendString(text, &raw); +} - UInt32 flags = buffer->FlagsBuffer[index]; +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 offset = flags >> STRINGSBUFFER_LEN_SHIFT; - UInt32 len = flags & STRINGSBUFFER_LEN_MASK; + UInt32 len = flags & STRINGSBUFFER_LEN_MASK; - UInt8* src = &buffer->FlagsBuffer[offset]; - UInt32 i; - for (i = 0; i < len; i++) { String_Append(text, src[i]); } + String raw; + raw.buffer = &buffer->TextBuffer[offset]; + raw.length = len; raw.capacity = len; + return raw; } \ No newline at end of file diff --git a/src/Client/String.h b/src/Client/String.h index 41736ad63..430bbc714 100644 --- a/src/Client/String.h +++ b/src/Client/String.h @@ -26,12 +26,12 @@ typedef struct String_ { } String; /* Constructs a new string, pointing a buffer consisting purely of NULL characters. */ -String String_FromEmptyBuffer(UInt8* buffer, UInt16 capacity); +String String_FromEmptyBuffer(STRING_REF UInt8* buffer, UInt16 capacity); /* Constructs a new string, pointing a buffer consisting of arbitary data. -NOTE: This method sets the bytes occupied by the string to NUL. */ -String String_FromRawBuffer(UInt8* buffer, UInt16 capacity); +NOTE: This method sets the bytes occupied by the string to NULL. */ +String String_FromRawBuffer(STRING_REF UInt8* buffer, UInt16 capacity); /* Constructs a new string from a constant readonly buffer. */ -String String_FromReadonly(const UInt8* buffer); +String String_FromReadonly(STRING_REF const UInt8* buffer); /* Makes an empty string that points to nowhere. */ String String_MakeNull(void); /* Constructs a new string from a compile time string constant. */ @@ -48,9 +48,7 @@ NOTE: THIS IS UNSAFE - IT MAINTAINS A REFERENCE TO THE ORIGINAL BUFFER, AND THE String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length); #define String_UNSAFE_SubstringAt(str, offset) (String_UNSAFE_Substring(str, offset, (str)->length - (offset))) -/* Returns whether two strings have same contents. */ bool String_Equals(STRING_PURE String* a, STRING_PURE String* b); -/* Returns whether two strings have same case-insensitive contents. */ bool String_CaselessEquals(STRING_PURE String* a, STRING_PURE String* b); /* Attempts to append a character to the end of a string. */ @@ -100,7 +98,10 @@ typedef struct StringsBuffer_ { UInt32 Count; } StringsBuffer; -void StringsBuffer_Get(StringsBuffer* buffer, UInt32 index, STRING_TRANSIENT String* text); -void StringsBuffer_Add(StringsBuffer* buffer, STRING_PURE String* text); +void StringBuffers_Init(StringsBuffer* buffer); void StringsBuffer_Free(StringsBuffer* buffer); +void StringsBuffer_Get(StringsBuffer* buffer, UInt32 index, STRING_TRANSIENT String* text); +STRING_REF String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, UInt32 index); +void StringsBuffer_Add(StringsBuffer* buffer, STRING_PURE String* text); +void StringsBuffer_Remove(StringsBuffer* buffer, UInt32 index); #endif \ No newline at end of file