mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 12:05:14 -04:00
Rewrite C options to use StringsBuffer instead
This commit is contained in:
parent
b2ba84fb6a
commit
128920589b
@ -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;
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user