mirror of
https://github.com/FunkyFr3sh/cnc-ddraw.git
synced 2025-03-15 06:04:49 +01:00
improve ini reader performance
This commit is contained in:
parent
488d4ea567
commit
d7ed6bd7bc
@ -1,8 +1,8 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include "ini.h"
|
||||
|
||||
#define FILE_EXISTS(a) (GetFileAttributes(a) != INVALID_FILE_ATTRIBUTES)
|
||||
|
||||
@ -15,6 +15,7 @@ typedef struct CNCDDRAWCONFIG
|
||||
char game_path[MAX_PATH];
|
||||
char process_file_name[MAX_PATH];
|
||||
char process_file_ext[MAX_PATH];
|
||||
INIFILE ini;
|
||||
|
||||
/* Optional settings */
|
||||
|
||||
|
16
inc/ini.h
16
inc/ini.h
@ -1,6 +1,20 @@
|
||||
#ifndef INI_H
|
||||
#define INI_H
|
||||
|
||||
BOOL ini_section_exists(char* section);
|
||||
typedef struct
|
||||
{
|
||||
char filename[MAX_PATH];
|
||||
|
||||
struct {
|
||||
unsigned long hash;
|
||||
char* data;
|
||||
}*sections;
|
||||
} INIFILE;
|
||||
|
||||
void ini_create(INIFILE* ini, char* filename);
|
||||
DWORD ini_get_string(INIFILE* ini, LPCSTR section, LPCSTR key, LPCSTR def, LPSTR buf, DWORD size);
|
||||
BOOL ini_get_bool(INIFILE* ini, LPCSTR section, LPCSTR key, BOOL def);
|
||||
int ini_get_int(INIFILE* ini, LPCSTR section, LPCSTR key, int def);
|
||||
void ini_free(INIFILE* ini);
|
||||
|
||||
#endif
|
||||
|
43
src/config.c
43
src/config.c
@ -106,6 +106,8 @@ void cfg_load()
|
||||
GET_BOOL(g_config.mgs_hack, "mgs_hack", FALSE);
|
||||
|
||||
GameHandlesClose = GameHandlesClose || g_config.infantryhack;
|
||||
|
||||
ini_free(&g_config.ini);
|
||||
}
|
||||
|
||||
void cfg_save()
|
||||
@ -1098,31 +1100,25 @@ static void cfg_init()
|
||||
{
|
||||
cfg_create_ini();
|
||||
}
|
||||
|
||||
ini_create(&g_config.ini, g_config.ini_path);
|
||||
}
|
||||
|
||||
static DWORD cfg_get_string(LPCSTR key, LPCSTR default_value, LPSTR out_string, DWORD out_size)
|
||||
{
|
||||
if (!g_config.ini_path[0])
|
||||
cfg_init();
|
||||
|
||||
char buf[MAX_PATH] = { 0 };
|
||||
|
||||
if (ini_section_exists(g_config.process_file_name))
|
||||
{
|
||||
DWORD s = GetPrivateProfileStringA(
|
||||
g_config.process_file_name, key, "", out_string, out_size, g_config.ini_path);
|
||||
DWORD s = ini_get_string(&g_config.ini, g_config.process_file_name, key, "", out_string, out_size);
|
||||
|
||||
if (s > 0)
|
||||
if (s > 0)
|
||||
{
|
||||
if (ini_get_string(&g_config.ini, g_config.process_file_name, "checkfile", "", buf, sizeof(buf)) > 0)
|
||||
{
|
||||
if (GetPrivateProfileStringA(
|
||||
g_config.process_file_name, "checkfile", "", buf, sizeof(buf), g_config.ini_path) > 0)
|
||||
{
|
||||
if (FILE_EXISTS(buf))
|
||||
return s;
|
||||
}
|
||||
else
|
||||
if (FILE_EXISTS(buf))
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
for (int i = 2; i < 10; i++)
|
||||
@ -1130,22 +1126,19 @@ static DWORD cfg_get_string(LPCSTR key, LPCSTR default_value, LPSTR out_string,
|
||||
char section[MAX_PATH] = { 0 };
|
||||
_snprintf(section, sizeof(section) - 1, "%s/%d", g_config.process_file_name, i);
|
||||
|
||||
if (ini_section_exists(section))
|
||||
{
|
||||
DWORD s = GetPrivateProfileStringA(section, key, "", out_string, out_size, g_config.ini_path);
|
||||
DWORD s = ini_get_string(&g_config.ini, section, key, "", out_string, out_size);
|
||||
|
||||
if (s > 0)
|
||||
if (s > 0)
|
||||
{
|
||||
if (ini_get_string(&g_config.ini, section, "checkfile", "", buf, sizeof(buf)) > 0)
|
||||
{
|
||||
if (GetPrivateProfileStringA(section, "checkfile", "", buf, sizeof(buf), g_config.ini_path) > 0)
|
||||
{
|
||||
if (FILE_EXISTS(buf))
|
||||
return s;
|
||||
}
|
||||
if (FILE_EXISTS(buf))
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GetPrivateProfileStringA("ddraw", key, default_value, out_string, out_size, g_config.ini_path);
|
||||
return ini_get_string(&g_config.ini, "ddraw", key, default_value, out_string, out_size);
|
||||
}
|
||||
|
||||
static BOOL cfg_get_bool(LPCSTR key, BOOL default_value)
|
||||
|
170
src/ini.c
170
src/ini.c
@ -1,49 +1,173 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "debug.h"
|
||||
#include "config.h"
|
||||
#include "crc32.h"
|
||||
#include "ini.h"
|
||||
|
||||
static unsigned long g_ini_section_hashes[1024];
|
||||
// Microsoft: The maximum profile section size is 32,767 characters.
|
||||
#define BUF_SIZE (8192)
|
||||
|
||||
BOOL ini_section_exists(char* section)
|
||||
void ini_create(INIFILE* ini, char* filename)
|
||||
{
|
||||
if (!g_ini_section_hashes[0])
|
||||
{
|
||||
char* buf = calloc(8192, 1);
|
||||
if (buf)
|
||||
{
|
||||
if (GetPrivateProfileSectionNamesA(buf, 8192, g_config.ini_path) > 0)
|
||||
{
|
||||
for (int i = 0; *buf && i < sizeof(g_ini_section_hashes) / sizeof(g_ini_section_hashes[0]); i++)
|
||||
{
|
||||
size_t len = strlen(buf);
|
||||
if (!ini || !filename || !filename[0])
|
||||
return;
|
||||
|
||||
for (char* p = buf; *p; ++p)
|
||||
ini->sections = calloc(sizeof(ini->sections[0]), 1);
|
||||
if (ini->sections)
|
||||
{
|
||||
strncpy(ini->filename, filename, sizeof(ini->filename) - 1);
|
||||
|
||||
char* names = calloc(BUF_SIZE, 1);
|
||||
if (names)
|
||||
{
|
||||
if (GetPrivateProfileSectionNamesA(names, BUF_SIZE, filename) > 0)
|
||||
{
|
||||
char* name = names;
|
||||
|
||||
for (int i = 0; *name; i++)
|
||||
{
|
||||
ini->sections = realloc(ini->sections, sizeof(ini->sections[0]) * (i + 2));
|
||||
|
||||
if (!ini->sections)
|
||||
return;
|
||||
|
||||
memset(&ini->sections[i + 1], 0, sizeof(ini->sections[0]));
|
||||
|
||||
char* buf = malloc(BUF_SIZE);
|
||||
if (buf)
|
||||
{
|
||||
DWORD size = GetPrivateProfileSectionA(name, buf, BUF_SIZE, ini->filename);
|
||||
if (size > 0)
|
||||
{
|
||||
ini->sections[i].data = malloc(size + 2);
|
||||
if (ini->sections[i].data)
|
||||
{
|
||||
memcpy(ini->sections[i].data, buf, size + 2);
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
size_t len = strlen(name);
|
||||
|
||||
for (char* p = name; *p; ++p)
|
||||
*p = tolower(*p);
|
||||
|
||||
g_ini_section_hashes[i] = Crc32_ComputeBuf(0, buf, len);
|
||||
ini->sections[i].hash = Crc32_ComputeBuf(0, name, len);
|
||||
|
||||
buf += len + 1;
|
||||
name += len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
free(names);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DWORD ini_get_string(INIFILE* ini, LPCSTR section, LPCSTR key, LPCSTR def, LPSTR buf, DWORD size)
|
||||
{
|
||||
if (!buf || size == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ini || !ini->sections || !section || !key)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
size_t key_len = strlen(key);
|
||||
|
||||
if (key_len == 0 || strlen(section) == 0)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
char s[MAX_PATH];
|
||||
strncpy(s, section, sizeof(s) - 1);
|
||||
buf[sizeof(s) - 1] = 0;
|
||||
|
||||
for (char* p = s; *p; ++p)
|
||||
*p = tolower(*p);
|
||||
|
||||
|
||||
unsigned long hash = Crc32_ComputeBuf(0, s, strlen(s));
|
||||
|
||||
for (int i = 0; i < sizeof(g_ini_section_hashes) / sizeof(g_ini_section_hashes[0]) && g_ini_section_hashes[i]; i++)
|
||||
|
||||
for (int i = 0; ini->sections[i].hash; i++)
|
||||
{
|
||||
if (g_ini_section_hashes[i] == hash)
|
||||
return TRUE;
|
||||
if (ini->sections[i].hash == hash)
|
||||
{
|
||||
if (!ini->sections[i].data)
|
||||
break;
|
||||
|
||||
for (char* p = ini->sections[i].data; *p; p += strlen(p) + 1)
|
||||
{
|
||||
if (_strnicmp(key, p, key_len) == 0 && p[key_len] == '=')
|
||||
{
|
||||
strncpy(buf, &p[key_len + 1], size - 1);
|
||||
buf[size - 1] = 0;
|
||||
return strlen(buf);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
end:
|
||||
if (def)
|
||||
{
|
||||
strncpy(buf, def, size - 1);
|
||||
buf[size - 1] = 0;
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL ini_get_bool(INIFILE* ini, LPCSTR section, LPCSTR key, BOOL def)
|
||||
{
|
||||
char value[8];
|
||||
ini_get_string(ini, section, key, def ? "Yes" : "No", value, sizeof(value));
|
||||
|
||||
return (_stricmp(value, "yes") == 0 || _stricmp(value, "true") == 0 || _stricmp(value, "1") == 0);
|
||||
}
|
||||
|
||||
int ini_get_int(INIFILE* ini, LPCSTR section, LPCSTR key, int def)
|
||||
{
|
||||
char def_str[32];
|
||||
_snprintf(def_str, sizeof(def_str) - 1, "%d", def);
|
||||
|
||||
char value[32];
|
||||
ini_get_string(ini, section, key, def_str, value, sizeof(value));
|
||||
|
||||
if (strstr(value, "0x"))
|
||||
{
|
||||
return strtol(value, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return atoi(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ini_free(INIFILE* ini)
|
||||
{
|
||||
if (ini->sections)
|
||||
{
|
||||
for (int i = 0; ini->sections[i].hash; i++)
|
||||
{
|
||||
if (ini->sections[i].data)
|
||||
{
|
||||
free(ini->sections[i].data);
|
||||
ini->sections[i].data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(ini->sections);
|
||||
ini->sections = NULL;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user