QuelSolaar/i_settings.c

413 lines
10 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "forge.h"
typedef enum{
IMAGINE_ST_UNDEFINED,
IMAGINE_ST_BOOLEAN,
IMAGINE_ST_INTEGER,
IMAGINE_ST_DOUBLE,
IMAGINE_ST_TEXT,
IMAGINE_ST_COUNT
}ImagineSettingType;
typedef struct{
char name[32];
ImagineSettingType type;
const char *comment;
union{
boolean toggle;
char *text;
double real;
int integer;
}data;
}ImagineSetting;
struct{
ImagineSetting *array;
uint count;
uint version;
}ImagineGlobalSettings;
#ifdef __APPLE_CC__
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
void imagine_set_working_directory() /* FUCK APPLE!!!! */
{
uint i, j;
CFURLRef url;
char path[PATH_MAX], *dot_app = ".app";
url = CFBundleCopyExecutableURL(CFBundleGetMainBundle());
if(CFURLGetFileSystemRepresentation(url, true, (UInt8*)path, sizeof(path)))
{
for(i = 0; path[i] != 0; i++)
{
for(j = 0; path[i + j] == dot_app[j] && dot_app[j] != 0; j++);
if(dot_app[j] == 0)
{
for(;i > 0 && path[i] != '/'; i--);
path[++i] = 0;
printf("Set operating directory = %s\n", path);
chdir(path);
break;
}
}
}
CFRelease(url);
}
#endif
static void init_setting(void)
{
static boolean init = FALSE;
if(init)
return;
init = TRUE;
#ifdef __APPLE_CC__
imagine_set_working_directory();
#endif
ImagineGlobalSettings.array = malloc((sizeof *ImagineGlobalSettings.array) * 128);
ImagineGlobalSettings.count = 0;
ImagineGlobalSettings.version = 345;
}
static ImagineSetting * imagine_add_setting(const char *name, const char *comment)
{
ImagineSetting *s = NULL;
uint i, j;
init_setting();
for(i = 0; i < ImagineGlobalSettings.count; i++)
{
for(j = 0; ImagineGlobalSettings.array[i].name[j] == name[j] && name[j] != 0; j++);
if(ImagineGlobalSettings.array[i].name[j] == name[j])
{
s = &ImagineGlobalSettings.array[i];
if(s->type == IMAGINE_ST_UNDEFINED || s->type == IMAGINE_ST_TEXT)
free(s->data.text);
break;
}
}
if(s == NULL)
{
if(ImagineGlobalSettings.count % 64 == 0)
ImagineGlobalSettings.array = realloc(ImagineGlobalSettings.array, (sizeof *ImagineGlobalSettings.array) * (ImagineGlobalSettings.count + 64));
s = &ImagineGlobalSettings.array[ImagineGlobalSettings.count++];
for(i = 0; i < 31 && name[i] != 0; i++)
s->name[i] = name[i];
s->name[i] = 0;
}
s->comment = comment;
s->type = IMAGINE_ST_UNDEFINED;
s->data.integer = 1;
return s;
}
static ImagineSetting * imagine_setting_get(const char *name)
{
uint i;
init_setting();
for(i = 0; i < ImagineGlobalSettings.count; i++)
if(strcmp(ImagineGlobalSettings.array[i].name, name) == 0)
return &ImagineGlobalSettings.array[i];
return NULL;
}
boolean imagine_setting_boolean_get(const char *setting, boolean default_value, const char *comment)
{
ImagineSetting *s;
char *text;
uint i;
init_setting();
s = imagine_setting_get(setting);
if(s == NULL)
{
s = imagine_add_setting(setting, comment);
s->data.toggle = default_value;
s->type = IMAGINE_ST_BOOLEAN;
}else if(s->type != IMAGINE_ST_BOOLEAN)
{
text = s->data.text;
s->data.toggle = default_value;
for(i = 0; text[i] != 0 && text[i] <= 32; i++);
if(text[i] != 0)
{
if(text[i] == 'T' || text[i] == 't')
s->data.toggle = TRUE;
if(text[i] == 'F' || text[i] == 'f' || (text[i] > '0' && text[i] <= '9'))
s->data.toggle = FALSE;
}
free(text);
s->type = IMAGINE_ST_BOOLEAN;
}
if(comment != NULL)
s->comment = comment;
return s->data.toggle;
}
void imagine_setting_boolean_set(const char *setting, boolean value, const char *comment)
{
ImagineSetting *s;
init_setting();
s = imagine_setting_get(setting);
if(s == NULL)
s = imagine_add_setting(setting, comment);
s->data.toggle = value;
if(comment != NULL)
s->comment = comment;
s->type = IMAGINE_ST_BOOLEAN;
}
int imagine_setting_integer_get(const char *setting, int default_value, const char *comment)
{
ImagineSetting *s;
char *text;
init_setting();
s = imagine_setting_get(setting);
if(s == NULL)
{
s = imagine_add_setting(setting, comment);
s->data.integer = default_value;
s->type = IMAGINE_ST_INTEGER;
}else if(s->type != IMAGINE_ST_INTEGER)
{
text = s->data.text;
s->data.integer = default_value;
if(sscanf(text, "%u", &s->data.integer) == 1)
free(text);
s->type = IMAGINE_ST_INTEGER;
}
if(comment != NULL)
s->comment = comment;
return s->data.integer;
}
void imagine_setting_integer_set(const char *setting, int value, const char *comment)
{
ImagineSetting *s;
char *text;
init_setting();
s = imagine_setting_get(setting);
if(s == NULL)
s = imagine_add_setting(setting, comment);
s->data.integer = value;
s->type = IMAGINE_ST_INTEGER;
if(comment != NULL)
s->comment = comment;
}
double imagine_setting_double_get(const char *setting, double default_value, const char *comment)
{
ImagineSetting *s;
char *text;
init_setting();
s = imagine_setting_get(setting);
if(s == NULL)
{
s = imagine_add_setting(setting, comment);
s->data.real = default_value;
s->type = IMAGINE_ST_DOUBLE;
}else if(s->type != IMAGINE_ST_DOUBLE)
{
float f;
text = s->data.text;
s->data.real = default_value;
if(sscanf(text, "%f", &f) == 1)
{
s->data.real = f;
free(text);
}
s->type = IMAGINE_ST_DOUBLE;
}
if(comment != NULL)
s->comment = comment;
return s->data.real;
}
void imagine_setting_double_set(const char *setting, double value, const char *comment)
{
ImagineSetting *s;
char *text;
init_setting();
s = imagine_setting_get(setting);
if(s == NULL)
s = imagine_add_setting(setting, comment);
s->data.real = value;
s->type = IMAGINE_ST_DOUBLE;
if(comment != NULL)
s->comment = comment;
}
char *imagine_setting_text_get(const char *setting, char *default_text, const char *comment)
{
ImagineSetting *s;
char *text;
uint i;
init_setting();
s = imagine_setting_get(setting);
if(s == NULL)
{
s = imagine_add_setting(setting, comment);
for(i = 0; default_text[i] != 0; i++);
text = malloc((sizeof *text) * (i + 1));
for(i = 0; default_text[i] != 0; i++)
text[i] = default_text[i];
text[i] = 0;
s->data.text = text;
s->type = IMAGINE_ST_TEXT;
}
if(comment != NULL)
s->comment = comment;
return s->data.text;
}
void imagine_setting_text_set(const char *setting, char *text, const char *comment)
{
ImagineSetting *s;
char *t;
uint i;
init_setting();
s = imagine_setting_get(setting);
if(s == NULL)
s = imagine_add_setting(setting, comment);
for(i = 0; text[i] != 0; i++);
t = malloc((sizeof *t) * (i + 1));
for(i = 0; text[i] != 0; i++)
t[i] = text[i];
t[i] = 0;
s->data.text = t;
s->type = IMAGINE_ST_TEXT;
if(comment != NULL)
s->comment = comment;
}
boolean imagine_setting_test(const char *setting)
{
return NULL != imagine_setting_get(setting);
}
void imagine_settings_save(const char *file_name)
{
uint i;
FILE *settings;
init_setting();
#ifdef __APPLE_CC__
imagine_set_working_directory(); /* FUCK APPLE!!!! */
#endif
settings = fopen(file_name, "w");
if(settings == NULL)
return;
fprintf(settings, "<?xml version=\"1.0\"?>\n<ROOT>\n");
for(i = 0; i < ImagineGlobalSettings.count; i++)
{
switch(ImagineGlobalSettings.array[i].type)
{
case IMAGINE_ST_UNDEFINED :
fprintf(settings, "\t<%s>%s</%s>", ImagineGlobalSettings.array[i].name, ImagineGlobalSettings.array[i].data.text, ImagineGlobalSettings.array[i].name);
break;
case IMAGINE_ST_BOOLEAN :
if(ImagineGlobalSettings.array[i].data.toggle)
fprintf(settings, "\t<%s>TRUE</%s>", ImagineGlobalSettings.array[i].name, ImagineGlobalSettings.array[i].name);
else
fprintf(settings, "\t<%s>FALSE</%s>", ImagineGlobalSettings.array[i].name, ImagineGlobalSettings.array[i].name);
break;
case IMAGINE_ST_INTEGER :
fprintf(settings, "\t<%s>%i</%s>", ImagineGlobalSettings.array[i].name, ImagineGlobalSettings.array[i].data.integer, ImagineGlobalSettings.array[i].name);
break;
case IMAGINE_ST_DOUBLE :
fprintf(settings, "\t<%s>%f</%s>", ImagineGlobalSettings.array[i].name, ImagineGlobalSettings.array[i].data.real, ImagineGlobalSettings.array[i].name);
break;
case IMAGINE_ST_TEXT :
fprintf(settings, "\t<%s>%s</%s>", ImagineGlobalSettings.array[i].name, ImagineGlobalSettings.array[i].data.text, ImagineGlobalSettings.array[i].name);
break;
}
if(ImagineGlobalSettings.array[i].comment == NULL)
fprintf(settings, "\n");
else
fprintf(settings, " <!-- %s -->\n", ImagineGlobalSettings.array[i].comment);
}
fprintf(settings, "</ROOT>\n");
fclose(settings);
}
boolean imagine_settings_load(const char *file_name)
{
char *buffer, type[256], *text;
uint i, j, size;
FILE *settings;
ImagineSetting *s;
init_setting();
if((settings = fopen(file_name, "r")) != NULL)
{
fseek(settings , 0, SEEK_END);
size = ftell(settings) + 1;
fseek(settings , 0, SEEK_SET);
buffer = malloc(size + 1);
fread(buffer, sizeof(char), size, settings);
buffer[size] = 0;
for(i = 0; buffer[i] != 0; i++)
{
if(buffer[i] == '<')
{
i++;
if(buffer[i] != '/' && buffer[i] != '!')
{
for(j = 0; buffer[i] != 0 && buffer[i] != '>'; i++)
type[j++] = buffer[i];
type[j] = 0;
i++;
for(j = 0; buffer[i + j] != 0 && buffer[i + j] != '<'; j++);
if(buffer[i + j] != 0 && j != 0)
{
j++;
if(buffer[i + j] == '/')
{
text = malloc(sizeof(char) * j);
for(j = 0; buffer[i + j] != 0 && buffer[i + j] != '<'; j++)
text[j] = buffer[i + j];
text[j] = 0;
s = imagine_add_setting(type, NULL);
s->data.text = text;
}
}
}
}
}
fclose(settings);
free(buffer);
return TRUE;
}
return FALSE;
}
void imagine_settings_test()
{
/* sui_setting_boolean("BOOLEAN", TRUE, "This is a switch.");
sui_setting_integer("IINTEGER", 1138, "This is an integer number.");
sui_setting_double("DOUBLE", 3.14, "This is a double precision floating point value.");
sui_setting_text("TEXT","hello world", "This is some text.");*/
imagine_settings_load("setings.xml");
imagine_settings_save("setings2.xml");
}