Use separator argument instead, eliminate need for separate EntryList struct

This commit is contained in:
UnknownShadow200 2020-07-01 23:06:17 +10:00
parent 669dac1738
commit 6a1235f6a9
10 changed files with 86 additions and 98 deletions

View File

@ -721,7 +721,7 @@ static void Font_SysTextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int
static FT_Library ft_lib; static FT_Library ft_lib;
static struct FT_MemoryRec_ ft_mem; static struct FT_MemoryRec_ ft_mem;
static struct EntryList font_list; static struct StringsBuffer font_list;
static cc_bool fonts_changed; static cc_bool fonts_changed;
struct SysFont { struct SysFont {
@ -849,8 +849,8 @@ static void SysFonts_Init(void) {
Window_ShowDialog("One time load", "Initialising font cache, this can take several seconds."); Window_ShowDialog("One time load", "Initialising font cache, this can take several seconds.");
} }
EntryList_Init(&font_list, FONT_CACHE_FILE, '='); EntryList_Load(&font_list, FONT_CACHE_FILE, '=', NULL);
if (!font_list.entries.count) SysFonts_Update(); if (!font_list.count) SysFonts_Update();
} }
static void SysFonts_Add(const String* path, FT_Face face, int index, char type, const char* defStyle) { static void SysFonts_Add(const String* path, FT_Face face, int index, char type, const char* defStyle) {
@ -876,7 +876,7 @@ static void SysFonts_Add(const String* path, FT_Face face, int index, char type,
String_Format2(&value, "%s,%i", path, &index); String_Format2(&value, "%s,%i", path, &index);
Platform_Log2("Face: %s = %s", &key, &value); Platform_Log2("Face: %s = %s", &key, &value);
EntryList_Set(&font_list, &key, &value); EntryList_Set(&font_list, &key, &value, '=');
fonts_changed = true; fonts_changed = true;
} }
@ -913,9 +913,9 @@ void SysFonts_Register(const String* path) {
int i, count; int i, count;
/* if font is already known, skip it */ /* if font is already known, skip it */
for (i = 0; i < font_list.entries.count; i++) { for (i = 0; i < font_list.count; i++) {
entry = StringsBuffer_UNSAFE_Get(&font_list.entries, i); entry = StringsBuffer_UNSAFE_Get(&font_list, i);
String_UNSAFE_Separate(&entry, font_list.separator, &name, &value); String_UNSAFE_Separate(&entry, '=', &name, &value);
String_UNSAFE_Separate(&value, ',', &fontPath, &index); String_UNSAFE_Separate(&value, ',', &fontPath, &index);
if (String_CaselessEquals(path, &fontPath)) return; if (String_CaselessEquals(path, &fontPath)) return;
@ -931,12 +931,12 @@ void SysFonts_Register(const String* path) {
void Font_GetNames(struct StringsBuffer* buffer) { void Font_GetNames(struct StringsBuffer* buffer) {
String entry, name, path; String entry, name, path;
int i; int i;
if (!font_list.entries.count) SysFonts_Init(); if (!font_list.count) SysFonts_Init();
SysFonts_Update(); SysFonts_Update();
for (i = 0; i < font_list.entries.count; i++) { for (i = 0; i < font_list.count; i++) {
entry = StringsBuffer_UNSAFE_Get(&font_list.entries, i); entry = StringsBuffer_UNSAFE_Get(&font_list, i);
String_UNSAFE_Separate(&entry, font_list.separator, &name, &path); String_UNSAFE_Separate(&entry, '=', &name, &path);
/* only want Regular fonts here */ /* only want Regular fonts here */
if (name.length < 2 || name.buffer[name.length - 1] != 'R') continue; if (name.length < 2 || name.buffer[name.length - 1] != 'R') continue;
@ -950,12 +950,12 @@ static String Font_LookupOf(const String* fontName, const char type) {
String_InitArray(name, nameBuffer); String_InitArray(name, nameBuffer);
String_Format2(&name, "%s %r", fontName, &type); String_Format2(&name, "%s %r", fontName, &type);
return EntryList_UNSAFE_Get(&font_list, &name); return EntryList_UNSAFE_Get(&font_list, &name, '=');
} }
static String Font_DoLookup(const String* fontName, int style) { static String Font_DoLookup(const String* fontName, int style) {
String path; String path;
if (!font_list.entries.count) SysFonts_Init(); if (!font_list.count) SysFonts_Init();
path = String_Empty; path = String_Empty;
if (style & FONT_STYLE_BOLD) path = Font_LookupOf(fontName, 'B'); if (style & FONT_STYLE_BOLD) path = Font_LookupOf(fontName, 'B');

View File

@ -105,7 +105,8 @@ static void Http_DownloadNextAsync(void);
#endif #endif
/* Adds a req to the list of pending requests, waking up worker thread if needed. */ /* Adds a req to the list of pending requests, waking up worker thread if needed. */
static void Http_Add(const String* url, cc_bool priority, const String* id, cc_uint8 type, const String* lastModified, const String* etag, const void* data, cc_uint32 size, struct EntryList* cookies) { static void Http_Add(const String* url, cc_bool priority, const String* id, cc_uint8 type, const String* lastModified,
const String* etag, const void* data, cc_uint32 size, struct StringsBuffer* cookies) {
struct HttpRequest req = { 0 }; struct HttpRequest req = { 0 };
String_CopyToRawArray(req.url, url); String_CopyToRawArray(req.url, url);
@ -252,8 +253,7 @@ static void Http_ParseCookie(struct HttpRequest* req, const String* value) {
dataEnd = String_IndexOf(&data, ';'); dataEnd = String_IndexOf(&data, ';');
if (dataEnd >= 0) data.length = dataEnd; if (dataEnd >= 0) data.length = dataEnd;
req->cookies->separator = '='; EntryList_Set(req->cookies, &name, &data, '=');
EntryList_Set(req->cookies, &name, &data);
} }
/* Parses a HTTP header */ /* Parses a HTTP header */
@ -300,12 +300,12 @@ static void Http_SetRequestHeaders(struct HttpRequest* req) {
} }
if (req->data) Http_AddHeader("Content-Type", &contentType); if (req->data) Http_AddHeader("Content-Type", &contentType);
if (!req->cookies || !req->cookies->entries.count) return; if (!req->cookies || !req->cookies->count) return;
String_InitArray(cookies, cookiesBuffer); String_InitArray(cookies, cookiesBuffer);
for (i = 0; i < req->cookies->entries.count; i++) { for (i = 0; i < req->cookies->count; i++) {
if (i) String_AppendConst(&cookies, "; "); if (i) String_AppendConst(&cookies, "; ");
str = StringsBuffer_UNSAFE_Get(&req->cookies->entries, i); str = StringsBuffer_UNSAFE_Get(req->cookies, i);
String_AppendString(&cookies, &str); String_AppendString(&cookies, &str);
} }
Http_AddHeader("Cookie", &cookies); Http_AddHeader("Cookie", &cookies);
@ -1030,10 +1030,10 @@ void Http_AsyncGetData(const String* url, cc_bool priority, const String* id) {
void Http_AsyncGetHeaders(const String* url, cc_bool priority, const String* id) { void Http_AsyncGetHeaders(const String* url, cc_bool priority, const String* id) {
Http_Add(url, priority, id, REQUEST_TYPE_HEAD, NULL, NULL, NULL, 0, NULL); Http_Add(url, priority, id, REQUEST_TYPE_HEAD, NULL, NULL, NULL, 0, NULL);
} }
void Http_AsyncPostData(const String* url, cc_bool priority, const String* id, const void* data, cc_uint32 size, struct EntryList* cookies) { void Http_AsyncPostData(const String* url, cc_bool priority, const String* id, const void* data, cc_uint32 size, struct StringsBuffer* cookies) {
Http_Add(url, priority, id, REQUEST_TYPE_POST, NULL, NULL, data, size, cookies); Http_Add(url, priority, id, REQUEST_TYPE_POST, NULL, NULL, data, size, cookies);
} }
void Http_AsyncGetDataEx(const String* url, cc_bool priority, const String* id, const String* lastModified, const String* etag, struct EntryList* cookies) { void Http_AsyncGetDataEx(const String* url, cc_bool priority, const String* id, const String* lastModified, const String* etag, struct StringsBuffer* cookies) {
Http_Add(url, priority, id, REQUEST_TYPE_GET, lastModified, etag, NULL, 0, cookies); Http_Add(url, priority, id, REQUEST_TYPE_GET, lastModified, etag, NULL, 0, cookies);
} }

View File

@ -35,7 +35,7 @@ struct HttpRequest {
char etag[STRING_SIZE]; /* ETag of cached item (if any) */ char etag[STRING_SIZE]; /* ETag of cached item (if any) */
cc_uint8 requestType; /* See the various REQUEST_TYPE_ */ cc_uint8 requestType; /* See the various REQUEST_TYPE_ */
cc_bool success; /* Whether Result is 0, status is 200, and data is not NULL */ cc_bool success; /* Whether Result is 0, status is 200, and data is not NULL */
struct EntryList* cookies; /* Cookie list sent in requests. May be modified by the response. */ struct StringsBuffer* cookies; /* Cookie list sent in requests. May be modified by the response. */
}; };
/* Frees data from a HTTP request. */ /* Frees data from a HTTP request. */
@ -51,10 +51,10 @@ void Http_AsyncGetData(const String* url, cc_bool priority, const String* id);
void Http_AsyncGetHeaders(const String* url, cc_bool priority, const String* id); void Http_AsyncGetHeaders(const String* url, cc_bool priority, const String* id);
/* Asynchronously performs a http POST request. (e.g. to submit data) */ /* Asynchronously performs a http POST request. (e.g. to submit data) */
/* NOTE: You don't have to persist data, a copy is made of it. */ /* NOTE: You don't have to persist data, a copy is made of it. */
void Http_AsyncPostData(const String* url, cc_bool priority, const String* id, const void* data, cc_uint32 size, struct EntryList* cookies); void Http_AsyncPostData(const String* url, cc_bool priority, const String* id, const void* data, cc_uint32 size, struct StringsBuffer* cookies);
/* Asynchronously performs a http GET request. (e.g. to download data) */ /* Asynchronously performs a http GET request. (e.g. to download data) */
/* Also sets the If-Modified-Since and If-None-Match headers. (if not NULL) */ /* Also sets the If-Modified-Since and If-None-Match headers. (if not NULL) */
void Http_AsyncGetDataEx(const String* url, cc_bool priority, const String* id, const String* lastModified, const String* etag, struct EntryList* cookies); void Http_AsyncGetDataEx(const String* url, cc_bool priority, const String* id, const String* lastModified, const String* etag, struct StringsBuffer* cookies);
/* Encodes data using % or URL encoding. */ /* Encodes data using % or URL encoding. */
void Http_UrlEncode(String* dst, const cc_uint8* data, int len); void Http_UrlEncode(String* dst, const cc_uint8* data, int len);

View File

@ -477,9 +477,9 @@ static void Hotkeys_Init(void) {
cc_uint8 modifiers; cc_uint8 modifiers;
cc_bool more; cc_bool more;
for (i = 0; i < Options.entries.count; i++) { for (i = 0; i < Options.count; i++) {
entry = StringsBuffer_UNSAFE_Get(&Options.entries, i); entry = StringsBuffer_UNSAFE_Get(&Options, i);
String_UNSAFE_Separate(&entry, Options.separator, &key, &value); String_UNSAFE_Separate(&entry, '=', &key, &value);
if (!String_CaselessStarts(&key, &prefix)) continue; if (!String_CaselessStarts(&key, &prefix)) continue;
/* Format is: key&modifiers = more-input&text */ /* Format is: key&modifiers = more-input&text */

View File

@ -235,7 +235,7 @@ void LWebTask_DisplayError(struct LWebTask* task, const char* action, String* ds
/*########################################################################################################################* /*########################################################################################################################*
*-------------------------------------------------------GetTokenTask------------------------------------------------------* *-------------------------------------------------------GetTokenTask------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static struct EntryList ccCookies; static struct StringsBuffer ccCookies;
struct GetTokenTaskData GetTokenTask; struct GetTokenTaskData GetTokenTask;
static void GetTokenTask_OnValue(struct JsonContext* ctx, const String* str) { static void GetTokenTask_OnValue(struct JsonContext* ctx, const String* str) {

View File

@ -7,13 +7,13 @@
#include "Utils.h" #include "Utils.h"
#include "Logger.h" #include "Logger.h"
struct EntryList Options; struct StringsBuffer Options;
static struct StringsBuffer changedOpts; static struct StringsBuffer changedOpts;
int Options_ChangedCount(void) { return changedOpts.count; } int Options_ChangedCount(void) { return changedOpts.count; }
void Options_Free(void) { void Options_Free(void) {
StringsBuffer_Clear(&Options.entries); StringsBuffer_Clear(&Options);
StringsBuffer_Clear(&changedOpts); StringsBuffer_Clear(&changedOpts);
} }
@ -32,7 +32,7 @@ cc_bool Options_UNSAFE_Get(const char* keyRaw, String* value) {
int idx; int idx;
String key = String_FromReadonly(keyRaw); String key = String_FromReadonly(keyRaw);
*value = EntryList_UNSAFE_Get(&Options, &key); *value = EntryList_UNSAFE_Get(&Options, &key, '=');
if (value->length) return true; if (value->length) return true;
/* Fallback to without '-' (e.g. "hacks-fly" to "fly") */ /* Fallback to without '-' (e.g. "hacks-fly" to "fly") */
@ -41,7 +41,7 @@ cc_bool Options_UNSAFE_Get(const char* keyRaw, String* value) {
if (idx == -1) return false; if (idx == -1) return false;
key = String_UNSAFE_SubstringAt(&key, idx + 1); key = String_UNSAFE_SubstringAt(&key, idx + 1);
*value = EntryList_UNSAFE_Get(&Options, &key); *value = EntryList_UNSAFE_Get(&Options, &key, '=');
return value->length > 0; return value->length > 0;
} }
@ -113,10 +113,10 @@ void Options_Set(const char* keyRaw, const String* value) {
void Options_SetString(const String* key, const String* value) { void Options_SetString(const String* key, const String* value) {
int i; int i;
if (!value || !value->length) { if (!value || !value->length) {
i = EntryList_Remove(&Options, key); i = EntryList_Remove(&Options, key, '=');
if (i == -1) return; if (i == -1) return;
} else { } else {
EntryList_Set(&Options, key, value); EntryList_Set(&Options, key, value, '=');
} }
#ifdef CC_BUILD_WEB #ifdef CC_BUILD_WEB
@ -134,26 +134,26 @@ static cc_bool Options_LoadFilter(const String* entry) {
} }
void Options_Load(void) { void Options_Load(void) {
static cc_bool loaded; static cc_bool inited;
String entry, key, value; String entry, key, value;
int i; int i;
if (!loaded) { if (!inited) {
EntryList_Init(&Options, "options-default.txt", '='); EntryList_Load(&Options, "options-default.txt", '=', NULL);
EntryList_Init(&Options, "options.txt", '='); EntryList_Load(&Options, "options.txt", '=', NULL);
loaded = true; inited = true;
} else { } else {
/* Reset all the unchanged options */ /* Reset all the unchanged options */
for (i = Options.entries.count - 1; i >= 0; i--) { for (i = Options.count - 1; i >= 0; i--) {
entry = StringsBuffer_UNSAFE_Get(&Options.entries, i); entry = StringsBuffer_UNSAFE_Get(&Options, i);
String_UNSAFE_Separate(&entry, '=', &key, &value); String_UNSAFE_Separate(&entry, '=', &key, &value);
if (Options_HasChanged(&key)) continue; if (Options_HasChanged(&key)) continue;
StringsBuffer_Remove(&Options.entries, i); StringsBuffer_Remove(&Options, i);
} }
/* Load only options which have not changed */ /* Load only options which have not changed */
EntryList_Load(&Options, "options.txt", Options_LoadFilter); EntryList_Load(&Options, "options.txt", '=', Options_LoadFilter);
} }
} }

View File

@ -68,7 +68,7 @@
#define OPT_MAX_CHUNK_UPDATES "gfx-maxchunkupdates" #define OPT_MAX_CHUNK_UPDATES "gfx-maxchunkupdates"
#define OPT_CAMERA_MASS "cameramass" #define OPT_CAMERA_MASS "cameramass"
extern struct EntryList Options; extern struct StringsBuffer Options;
/* Returns the number of options changed via Options_SetXYZ since last save. */ /* Returns the number of options changed via Options_SetXYZ since last save. */
int Options_ChangedCount(void); int Options_ChangedCount(void);
/* Frees any memory allocated in storing options. */ /* Frees any memory allocated in storing options. */

View File

@ -150,7 +150,7 @@ cc_bool Atlas_TryChange(Bitmap* atlas) {
/*########################################################################################################################* /*########################################################################################################################*
*------------------------------------------------------TextureCache-------------------------------------------------------* *------------------------------------------------------TextureCache-------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static struct EntryList acceptedList, deniedList, etagCache, lastModCache; static struct StringsBuffer acceptedList, deniedList, etagCache, lastModCache;
#define ACCEPTED_TXT "texturecache/acceptedurls.txt" #define ACCEPTED_TXT "texturecache/acceptedurls.txt"
#define DENIED_TXT "texturecache/deniedurls.txt" #define DENIED_TXT "texturecache/deniedurls.txt"
#define ETAGS_TXT "texturecache/etags.txt" #define ETAGS_TXT "texturecache/etags.txt"
@ -158,27 +158,27 @@ static struct EntryList acceptedList, deniedList, etagCache, lastModCache;
/* Initialises cache state (loading various lists) */ /* Initialises cache state (loading various lists) */
static void TextureCache_Init(void) { static void TextureCache_Init(void) {
EntryList_Init(&acceptedList, ACCEPTED_TXT, ' '); EntryList_Load(&acceptedList, ACCEPTED_TXT, '=', NULL);
EntryList_Init(&deniedList, DENIED_TXT, ' '); EntryList_Load(&deniedList, DENIED_TXT, '=', NULL);
EntryList_Init(&etagCache, ETAGS_TXT, ' '); EntryList_Load(&etagCache, ETAGS_TXT, '=', NULL);
EntryList_Init(&lastModCache, LASTMOD_TXT, ' '); EntryList_Load(&lastModCache, LASTMOD_TXT, '=', NULL);
} }
cc_bool TextureCache_HasAccepted(const String* url) { return EntryList_Find(&acceptedList, url) >= 0; } cc_bool TextureCache_HasAccepted(const String* url) { return EntryList_Find(&acceptedList, url, ' ') >= 0; }
cc_bool TextureCache_HasDenied(const String* url) { return EntryList_Find(&deniedList, url) >= 0; } cc_bool TextureCache_HasDenied(const String* url) { return EntryList_Find(&deniedList, url, ' ') >= 0; }
void TextureCache_Accept(const String* url) { void TextureCache_Accept(const String* url) {
EntryList_Set(&acceptedList, url, &String_Empty); EntryList_Set(&acceptedList, url, &String_Empty, ' ');
EntryList_Save(&acceptedList, ACCEPTED_TXT); EntryList_Save(&acceptedList, ACCEPTED_TXT);
} }
void TextureCache_Deny(const String* url) { void TextureCache_Deny(const String* url) {
EntryList_Set(&deniedList, url, &String_Empty); EntryList_Set(&deniedList, url, &String_Empty, ' ');
EntryList_Save(&deniedList, DENIED_TXT); EntryList_Save(&deniedList, DENIED_TXT);
} }
int TextureCache_ClearDenied(void) { int TextureCache_ClearDenied(void) {
int count = deniedList.entries.count; int count = deniedList.count;
StringsBuffer_Clear(&deniedList.entries); StringsBuffer_Clear(&deniedList);
EntryList_Save(&deniedList, DENIED_TXT); EntryList_Save(&deniedList, DENIED_TXT);
return count; return count;
} }
@ -218,12 +218,12 @@ static cc_bool OpenCachedData(const String* url, struct Stream* stream) {
return true; return true;
} }
CC_NOINLINE static String GetCachedTag(const String* url, struct EntryList* list) { CC_NOINLINE static String GetCachedTag(const String* url, struct StringsBuffer* list) {
String key; char keyBuffer[STRING_INT_CHARS]; String key; char keyBuffer[STRING_INT_CHARS];
String_InitArray(key, keyBuffer); String_InitArray(key, keyBuffer);
HashUrl(&key, url); HashUrl(&key, url);
return EntryList_UNSAFE_Get(list, &key); return EntryList_UNSAFE_Get(list, &key, ' ');
} }
static String GetCachedLastModified(const String* url) { static String GetCachedLastModified(const String* url) {
@ -243,14 +243,14 @@ static String GetCachedETag(const String* url) {
return GetCachedTag(url, &etagCache); return GetCachedTag(url, &etagCache);
} }
CC_NOINLINE static void SetCachedTag(const String* url, struct EntryList* list, CC_NOINLINE static void SetCachedTag(const String* url, struct StringsBuffer* list,
const String* data, const char* file) { const String* data, const char* file) {
String key; char keyBuffer[STRING_INT_CHARS]; String key; char keyBuffer[STRING_INT_CHARS];
if (!data->length) return; if (!data->length) return;
String_InitArray(key, keyBuffer); String_InitArray(key, keyBuffer);
HashUrl(&key, url); HashUrl(&key, url);
EntryList_Set(list, &key, data); EntryList_Set(list, &key, data, ' ');
EntryList_Save(list, file); EntryList_Save(list, file);
} }

View File

@ -220,7 +220,7 @@ int Convert_FromBase64(const char* src, int len, cc_uint8* dst) {
/*########################################################################################################################* /*########################################################################################################################*
*--------------------------------------------------------EntryList--------------------------------------------------------* *--------------------------------------------------------EntryList--------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
void EntryList_Load(struct EntryList* list, const char* file, EntryList_Filter filter) { void EntryList_Load(struct StringsBuffer* list, const char* file, char separator, EntryList_Filter filter) {
String entry; char entryBuffer[768]; String entry; char entryBuffer[768];
String path; char pathBuffer[FILENAME_SIZE]; String path; char pathBuffer[FILENAME_SIZE];
String key, value; String key, value;
@ -260,15 +260,15 @@ void EntryList_Load(struct EntryList* list, const char* file, EntryList_Filter f
Logger_WarnFunc(&entry); continue; Logger_WarnFunc(&entry); continue;
} }
String_UNSAFE_Separate(&entry, list->separator, &key, &value); String_UNSAFE_Separate(&entry, separator, &key, &value);
EntryList_Set(list, &key, &value); EntryList_Set(list, &key, &value, separator);
} }
res = stream.Close(&stream); res = stream.Close(&stream);
if (res) { Logger_Warn2(res, "closing", &path); } if (res) { Logger_Warn2(res, "closing", &path); }
} }
void EntryList_Save(struct EntryList* list, const char* file) { void EntryList_Save(struct StringsBuffer* list, const char* file) {
String path, entry; char pathBuffer[FILENAME_SIZE]; String path, entry; char pathBuffer[FILENAME_SIZE];
struct Stream stream; struct Stream stream;
int i; int i;
@ -280,8 +280,8 @@ void EntryList_Save(struct EntryList* list, const char* file) {
res = Stream_CreateFile(&stream, &path); res = Stream_CreateFile(&stream, &path);
if (res) { Logger_Warn2(res, "creating", &path); return; } if (res) { Logger_Warn2(res, "creating", &path); return; }
for (i = 0; i < list->entries.count; i++) { for (i = 0; i < list->count; i++) {
entry = StringsBuffer_UNSAFE_Get(&list->entries, i); entry = StringsBuffer_UNSAFE_Get(list, i);
res = Stream_WriteLine(&stream, &entry); res = Stream_WriteLine(&stream, &entry);
if (res) { Logger_Warn2(res, "writing to", &path); break; } if (res) { Logger_Warn2(res, "writing to", &path); break; }
} }
@ -290,53 +290,48 @@ void EntryList_Save(struct EntryList* list, const char* file) {
if (res) { Logger_Warn2(res, "closing", &path); } if (res) { Logger_Warn2(res, "closing", &path); }
} }
int EntryList_Remove(struct EntryList* list, const String* key) { int EntryList_Remove(struct StringsBuffer* list, const String* key, char separator) {
int i = EntryList_Find(list, key); int i = EntryList_Find(list, key, separator);
if (i >= 0) StringsBuffer_Remove(&list->entries, i); if (i >= 0) StringsBuffer_Remove(list, i);
return i; return i;
} }
void EntryList_Set(struct EntryList* list, const String* key, const String* value) { void EntryList_Set(struct StringsBuffer* list, const String* key, const String* value, char separator) {
String entry; char entryBuffer[1024]; String entry; char entryBuffer[1024];
String_InitArray(entry, entryBuffer); String_InitArray(entry, entryBuffer);
if (value->length) { if (value->length) {
String_Format3(&entry, "%s%r%s", key, &list->separator, value); String_Format3(&entry, "%s%r%s", key, &separator, value);
} else { } else {
String_Copy(&entry, key); String_Copy(&entry, key);
} }
EntryList_Remove(list, key); EntryList_Remove(list, key, separator);
StringsBuffer_Add(&list->entries, &entry); StringsBuffer_Add(list, &entry);
} }
String EntryList_UNSAFE_Get(struct EntryList* list, const String* key) { String EntryList_UNSAFE_Get(struct StringsBuffer* list, const String* key, char separator) {
String curEntry, curKey, curValue; String curEntry, curKey, curValue;
int i; int i;
for (i = 0; i < list->entries.count; i++) { for (i = 0; i < list->count; i++) {
curEntry = StringsBuffer_UNSAFE_Get(&list->entries, i); curEntry = StringsBuffer_UNSAFE_Get(list, i);
String_UNSAFE_Separate(&curEntry, list->separator, &curKey, &curValue); String_UNSAFE_Separate(&curEntry, separator, &curKey, &curValue);
if (String_CaselessEquals(key, &curKey)) return curValue; if (String_CaselessEquals(key, &curKey)) return curValue;
} }
return String_Empty; return String_Empty;
} }
int EntryList_Find(struct EntryList* list, const String* key) { int EntryList_Find(struct StringsBuffer* list, const String* key, char separator) {
String curEntry, curKey, curValue; String curEntry, curKey, curValue;
int i; int i;
for (i = 0; i < list->entries.count; i++) { for (i = 0; i < list->count; i++) {
curEntry = StringsBuffer_UNSAFE_Get(&list->entries, i); curEntry = StringsBuffer_UNSAFE_Get(list, i);
String_UNSAFE_Separate(&curEntry, list->separator, &curKey, &curValue); String_UNSAFE_Separate(&curEntry, separator, &curKey, &curValue);
if (String_CaselessEquals(key, &curKey)) return i; if (String_CaselessEquals(key, &curKey)) return i;
} }
return -1; return -1;
} }
void EntryList_Init(struct EntryList* list, const char* path, char separator) {
list->separator = separator;
EntryList_Load(list, path, NULL);
}

View File

@ -54,24 +54,17 @@ int Convert_ToBase64(const cc_uint8* src, int len, char* dst);
/* NOTE: You MUST ensure that dst is appropriately sized. */ /* NOTE: You MUST ensure that dst is appropriately sized. */
int Convert_FromBase64(const char* src, int len, cc_uint8* dst); int Convert_FromBase64(const char* src, int len, cc_uint8* dst);
struct EntryList {
char separator;
struct StringsBuffer entries;
};
typedef cc_bool (*EntryList_Filter)(const String* entry); typedef cc_bool (*EntryList_Filter)(const String* entry);
/* Loads the entries from disc. */ /* Loads the entries from disc. */
CC_NOINLINE void EntryList_Load(struct EntryList* list, const char* file, EntryList_Filter filter); CC_NOINLINE void EntryList_Load(struct StringsBuffer* list, const char* file, char seperator, EntryList_Filter filter);
/* Saves the entries to disc. */ /* Saves the entries to disc. */
CC_NOINLINE void EntryList_Save(struct EntryList* list, const char* file); CC_NOINLINE void EntryList_Save(struct StringsBuffer* list, const char* file);
/* Removes the entry whose key caselessly equals the given key. */ /* Removes the entry whose key caselessly equals the given key. */
CC_NOINLINE int EntryList_Remove(struct EntryList* list, const String* key); CC_NOINLINE int EntryList_Remove(struct StringsBuffer* list, const String* key, char seperator);
/* Replaces the entry whose key caselessly equals the given key, or adds a new entry. */ /* Replaces the entry whose key caselessly equals the given key, or adds a new entry. */
CC_NOINLINE void EntryList_Set(struct EntryList* list, const String* key, const String* value); CC_NOINLINE void EntryList_Set(struct StringsBuffer* list, const String* key, const String* value, char seperator);
/* Returns the value of the entry whose key caselessly equals the given key. */ /* Returns the value of the entry whose key caselessly equals the given key. */
CC_NOINLINE STRING_REF String EntryList_UNSAFE_Get(struct EntryList* list, const String* key); CC_NOINLINE STRING_REF String EntryList_UNSAFE_Get(struct StringsBuffer* list, const String* key, char seperator);
/* Finds the index of the entry whose key caselessly equals the given key. */ /* Finds the index of the entry whose key caselessly equals the given key. */
CC_NOINLINE int EntryList_Find(struct EntryList* list, const String* key); CC_NOINLINE int EntryList_Find(struct StringsBuffer* list, const String* key, char seperator);
/* Initialises the EntryList and loads the entries from disc. */
void EntryList_Init(struct EntryList* list, const char* file, char separator);
#endif #endif