mirror of
https://github.com/Alcaro/Flips.git
synced 2026-09-07 10:06:09 -05:00
Fill in this config system. Next up: Use it.
This commit is contained in:
@@ -845,6 +845,10 @@ int GUIShow(const char * filename)
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
canShowGUI=gtk_parse_args(&argc, &argv);
|
||||
if (canShowGUI)
|
||||
{
|
||||
cfg.load_file(get_cfgpath());
|
||||
}
|
||||
return flipsmain(argc, argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
133
flips.cpp
133
flips.cpp
@@ -76,7 +76,8 @@ struct mem file::read()
|
||||
{
|
||||
struct mem out;
|
||||
out.len = len();
|
||||
out.ptr = (uint8_t*)malloc(out.len);
|
||||
out.ptr = (uint8_t*)malloc(out.len + sizeof(WCHAR));
|
||||
memset(out.ptr + out.len, 0, sizeof(WCHAR));
|
||||
if (!read(out.ptr, 0, out.len))
|
||||
{
|
||||
free(out.ptr);
|
||||
@@ -180,34 +181,146 @@ enum patchtype IdentifyPatch(file* patch)
|
||||
|
||||
|
||||
|
||||
|
||||
config::config(struct mem contents)
|
||||
//this is the most inefficient possible implementation. it works, that's all I care about
|
||||
void config::init_raw(LPWSTR contents)
|
||||
{
|
||||
LPCWSTR header = TEXT("[Flips]\n");
|
||||
|
||||
if (wcsncmp(contents, header, wcslen(header)) != 0) return;
|
||||
contents += wcslen(header);
|
||||
|
||||
//I need to somehow ensure that stepping backwards across whitespace doesn't go before the original string.
|
||||
//This can be done with while (iswspace(*contents)) contents++;, but demanding the header above works just as well.
|
||||
|
||||
while (true)
|
||||
{
|
||||
LPWSTR key;
|
||||
LPWSTR keyend;
|
||||
LPWSTR val;
|
||||
LPWSTR valend;
|
||||
|
||||
LPWSTR nextline = wcschr(contents, '\n');
|
||||
|
||||
if (nextline != NULL) valend = nextline;
|
||||
else valend = wcschr(contents, '\0');
|
||||
//do not move inside the conditional, it screws up the strchr
|
||||
while (iswspace(valend[-1])) valend--;
|
||||
*valend = '\0';
|
||||
|
||||
LPWSTR sep = wcschr(contents, '=');
|
||||
if (sep != NULL)
|
||||
{
|
||||
key = contents;
|
||||
keyend = sep;
|
||||
val = sep+1;
|
||||
|
||||
while (iswspace(key[0])) key++;
|
||||
while (iswspace(keyend[-1])) keyend--;
|
||||
*keyend = '\0';
|
||||
while (iswspace(val[0])) val++;
|
||||
|
||||
if (valend>val && keyend>key)
|
||||
{
|
||||
set(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
if (!nextline) break;
|
||||
contents = nextline+1;
|
||||
while (contents && iswspace(*contents)) contents++;
|
||||
}
|
||||
}
|
||||
|
||||
config::config(LPCWSTR filename)
|
||||
void config::init_file(LPCWSTR filename)
|
||||
{
|
||||
struct mem data = file::read(filename);
|
||||
if (data.len > 0 && data.len%sizeof(WCHAR) == 0)
|
||||
{
|
||||
this->init_raw((LPWSTR)(data.ptr));
|
||||
}
|
||||
free(data.ptr);
|
||||
|
||||
this->filename = wcsdup(filename);
|
||||
}
|
||||
|
||||
void config::setbin(const char * name, struct mem value)
|
||||
void config::set(LPCWSTR name, LPCWSTR value)
|
||||
{
|
||||
//printf("(%s)(%s)\n",name,value);
|
||||
for (size_t i=0;i<this->numentries;i++)
|
||||
{
|
||||
if (!wcscmp(name, this->names[i]))
|
||||
{
|
||||
free(this->values[i]);
|
||||
this->values[i] = wcsdup(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->numentries++;
|
||||
this->names = (LPWSTR*)realloc(this->names, sizeof(LPWSTR)*this->numentries);
|
||||
this->values = (LPWSTR*)realloc(this->values, sizeof(LPWSTR)*this->numentries);
|
||||
|
||||
this->names[this->numentries-1] = wcsdup(name);
|
||||
this->values[this->numentries-1] = wcsdup(value);
|
||||
}
|
||||
|
||||
struct mem config::getbin(const char * name)
|
||||
LPCWSTR config::get(LPCWSTR name)
|
||||
{
|
||||
for (size_t i=0;i<this->numentries;i++)
|
||||
{
|
||||
if (!wcscmp(name, this->names[i]))
|
||||
{
|
||||
return this->values[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mem config::flatten()
|
||||
LPWSTR config::flatten()
|
||||
{
|
||||
LPCWSTR header = TEXT("[Flips]\n");
|
||||
|
||||
size_t len = wcslen(header);
|
||||
for (size_t i=0;i<this->numentries;i++)
|
||||
{
|
||||
len += wcslen(this->names[i]) + 1 + wcslen(this->values[i]) + 1;
|
||||
}
|
||||
|
||||
LPWSTR ret = (LPWSTR)malloc((len+1)*sizeof(WCHAR));
|
||||
|
||||
LPWSTR at = ret;
|
||||
at += wsprintf(at, "%s", header);
|
||||
for (size_t i=0;i<this->numentries;i++)
|
||||
{
|
||||
at += wsprintf(at, "%s=%s\n", this->names[i], this->values[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
config::~config()
|
||||
{
|
||||
if (this->filename) filewrite::write(this->filename, this->contents);
|
||||
free(this->filename);
|
||||
free(this->contents.ptr);
|
||||
if (this->filename)
|
||||
{
|
||||
LPWSTR data = this->flatten();
|
||||
//puts(data);
|
||||
filewrite::write(this->filename, (struct mem){ (uint8_t*)data, wcslen(data)*sizeof(WCHAR) });
|
||||
free(data);
|
||||
free(this->filename);
|
||||
}
|
||||
|
||||
for (size_t i=0;i<this->numentries;i++)
|
||||
{
|
||||
//printf("#(%s)(%s)\n",this->names[i],this->values[i]);
|
||||
free(this->names[i]);
|
||||
free(this->values[i]);
|
||||
}
|
||||
free(this->names);
|
||||
free(this->values);
|
||||
}
|
||||
|
||||
config cfg;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
70
flips.h
70
flips.h
@@ -34,7 +34,7 @@
|
||||
//#define EXTERN_C
|
||||
//#endif
|
||||
|
||||
#define flipsversion "Flips v1.32"
|
||||
#define flipsversion "Flips v1.40"
|
||||
|
||||
|
||||
#if defined(FLIPS_WINDOWS)
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
#include <commctrl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define wcsicmp _wcsicmp//wcsicmp deprecated? fuck that, I use what I want. I do not add underlines to a few randomly chosen functions.
|
||||
#define wcsdup _wcsdup
|
||||
@@ -65,15 +66,17 @@
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
//Flips uses Windows type names internally, since it's easier to #define them to Linux types than
|
||||
//defining "const char *" to anything else, and since I use char* at some places (mainly libips/etc)
|
||||
//and really don't want to try to split them. Inventing my own typedefs seems counterproductive as
|
||||
//defining "const char *" to anything else. Inventing my own typedefs seems counterproductive as
|
||||
//well; they would bring no advantage over Windows typenames except not being Windows typenames, and
|
||||
//I don't see that as a valid argument.
|
||||
|
||||
#define LPCWSTR const char *
|
||||
#define LPWSTR char *
|
||||
#define WCHAR char
|
||||
|
||||
#define wcscpy strcpy
|
||||
#define wcscat strcat
|
||||
#define wcschr strchr
|
||||
@@ -85,15 +88,32 @@
|
||||
#define wcsicmp strcasecmp
|
||||
//#define wcsnicmp strncasecmp
|
||||
#define wprintf printf
|
||||
#define wsprintf sprintf
|
||||
|
||||
#define iswalnum isalnum
|
||||
#define iswalpha isalpha
|
||||
#define iswascii isascii
|
||||
#define iswblank isblank
|
||||
#define iswcntrl iscntrl
|
||||
#define iswdigit isdigit
|
||||
#define iswgraph isgraph
|
||||
#define iswlower islower
|
||||
#define iswprint isprint
|
||||
#define iswpunct ispunct
|
||||
#define iswspace isspace
|
||||
#define iswupper isupper
|
||||
#define iswxdigit isxdigit
|
||||
|
||||
#define TEXT(text) text
|
||||
//EXTERN_C int strcasecmp(const char *s1, const char *s2);
|
||||
|
||||
//some platforms define strdup, some don't.
|
||||
#define strdup strdup_flips
|
||||
static inline char* strdup(const char * in)
|
||||
{
|
||||
size_t len=strlen(in);
|
||||
char * ret=(char*)malloc(len+1);
|
||||
strcpy(ret, in);
|
||||
memcpy(ret, in, len+1);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -157,29 +177,43 @@ bool shouldRemoveHeader(LPCWSTR romname, size_t romlen);
|
||||
class config
|
||||
{
|
||||
LPWSTR filename;
|
||||
struct mem contents;
|
||||
|
||||
size_t numentries;
|
||||
LPWSTR * names;
|
||||
LPWSTR * values;
|
||||
|
||||
//stupid c++, why is there no sane way to get the implementation out of the headers
|
||||
bool parse(LPCWSTR contents);
|
||||
|
||||
public:
|
||||
config(struct mem contents);
|
||||
config(LPCWSTR filename);
|
||||
|
||||
void set(const char * name, LPCWSTR value)
|
||||
config()
|
||||
{
|
||||
setbin(name, (struct mem){(uint8_t*)value, (wcslen(value)+1)*sizeof(WCHAR)});
|
||||
numentries = 0;
|
||||
names = NULL;
|
||||
values = NULL;
|
||||
}
|
||||
void setbin(const char * name, struct mem value);
|
||||
|
||||
// free() these three when you're done with them.
|
||||
LPWSTR get(const char * name)
|
||||
{
|
||||
return (LPWSTR)(getbin(name).ptr);
|
||||
}
|
||||
struct mem getbin(const char * name);
|
||||
//This ends up writing a really ugly format on Windows: UTF-16, no BOM, LF endings.
|
||||
// I can't do anything else without adding a #ifdef, and that would reward Microsoft for being
|
||||
// dickbutts and not supporting UTF-8 properly.
|
||||
//I could use CRLF instead, but I want the file broken in Notepad; if I use CRLF, it adds a BOM,
|
||||
// and there's no way to get rid of that without a ifdef. If I break the file, people won't try.
|
||||
//If the input is invalid, the object will ignore the invalid parts and remain valid.
|
||||
//In particular, failing to initialize from a file will update the file on destruction.
|
||||
//Only init once.
|
||||
void init_file(LPCWSTR filename);
|
||||
void init_raw(LPWSTR contents); // Modifies the contents.
|
||||
|
||||
struct mem flatten();
|
||||
//Neither of those may have leading or trailing whitespace, or contain a \n. \r isn't recommended either.
|
||||
//Additionally, the name may not contain =.
|
||||
void set(LPCWSTR name, LPCWSTR value);
|
||||
LPCWSTR get(LPCWSTR name);
|
||||
|
||||
~config();
|
||||
LPWSTR flatten(); // free() this when you're done.
|
||||
~config(); // If you used init_file, this saves automatically.
|
||||
};
|
||||
extern config cfg;
|
||||
|
||||
struct mem GetRomList();
|
||||
void SetRomList(struct mem data);
|
||||
|
||||
1
global.h
1
global.h
@@ -33,6 +33,7 @@ public:
|
||||
virtual size_t len() = 0;
|
||||
virtual bool read(uint8_t* target, size_t start, size_t len) = 0;
|
||||
|
||||
//these two add sizeof(WCHAR) 00s after the actual data, so you can cast it to LPCWSTR (assuming it's aligned)
|
||||
static struct mem read(LPCWSTR filename); // provided by Flips core
|
||||
struct mem read(); // provided by Flips core
|
||||
|
||||
|
||||
Reference in New Issue
Block a user