This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
gnoemoe/gnoemoe/gm-options.c

213 lines
5.0 KiB
C

#include <glib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "gm-options.h"
#include "gm-string.h"
#include "gm-debug.h"
extern int errno;
#define GM_OPTIONS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GM_TYPE_OPTIONS, GmOptionsPrivate))
struct _GmOptionsPrivate {
GHashTable *options;
gchar *filepath;
};
/* Signals */
enum {
OPTION_CHANGED,
NUM_SIGNALS
};
static guint options_signals[NUM_SIGNALS] = {0};
G_DEFINE_TYPE(GmOptions, gm_options, G_TYPE_OBJECT)
static void
gm_options_finalize(GObject *object) {
GmOptions *options = GM_OPTIONS(object);
g_hash_table_destroy(options->priv->options);
g_free(options->priv->filepath);
G_OBJECT_CLASS(gm_options_parent_class)->finalize(object);
}
static void
gm_options_class_init(GmOptionsClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = gm_options_finalize;
options_signals[OPTION_CHANGED] =
g_signal_new("option_changed",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmOptionsClass, option_changed),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING);
g_type_class_add_private(object_class, sizeof(GmOptionsPrivate));
}
static void
gm_options_init(GmOptions *options) {
options->priv = GM_OPTIONS_GET_PRIVATE(options);
options->priv->options = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
options->priv->filepath = NULL;
}
GmOptions *
gm_options_new(void) {
GmOptions *options = GM_OPTIONS(g_object_new(GM_TYPE_OPTIONS, NULL));
return options;
}
void
gm_options_dup_option(gchar *key, gchar *value, GmOptions *copy) {
gm_options_set(copy, key, value);
}
GmOptions *
gm_options_dup(GmOptions *source) {
GmOptions *copy = gm_options_new();
g_hash_table_foreach(source->priv->options, (GHFunc)gm_options_dup_option,
copy);
return copy;
}
// Adds an option to opt, even if key already exists
void
gm_options_set(GmOptions * options, const gchar *key, const gchar *value) {
gchar *trimmed = gm_string_trim(key);
gchar *lookup = g_hash_table_lookup(options->priv->options, trimmed);
gboolean changed = lookup != NULL && lookup != value;
if (lookup != value) {
g_hash_table_insert(options->priv->options, g_strdup(trimmed),
g_strdup(value));
}
if (changed) {
g_signal_emit(options, options_signals[OPTION_CHANGED], 0, trimmed);
}
g_free(trimmed);
}
const gchar *
gm_options_get(GmOptions *options, const gchar *key) {
return g_hash_table_lookup(options->priv->options, key);
}
void
gm_options_set_int(GmOptions *options, const gchar *key, int value) {
gchar val[15];
g_snprintf((gchar *) &val, 15, "%d", value);
gm_options_set(options, key, (const gchar *)val);
}
int
gm_options_get_int(GmOptions *options, const gchar *key) {
const gchar *val = gm_options_get(options, key);
int ret;
if (val && gm_string_to_int(val, &ret)) {
return ret;
} else {
return 0;
}
}
void
gm_options_save_value(gchar *key, gchar *value, FILE *f) {
gm_debug_msg(DEBUG_DEFAULT, "GmOptions.SaveValue: saving %s, %s", key, value);
fprintf(f, "%s=%s\n", key, value);
}
void
gm_options_save(GmOptions *options) {
FILE *f;
if (options->priv->filepath == NULL) {
return;
}
f = fopen(options->priv->filepath, "w");
gm_debug_msg(DEBUG_DEFAULT, "GmOptions.save: saving options (%s)!", options->priv->filepath);
if (f) {
g_hash_table_foreach(options->priv->options,
(GHFunc)gm_options_save_value, f);
fclose(f);
chmod(options->priv->filepath, 0660);
} else {
gm_debug_msg(DEBUG_DEFAULT, "GmOptions.save: couldn't open option file for saving: %s",
strerror(errno));
}
}
void
gm_options_save_as(GmOptions *options, const gchar *filename) {
g_free(options->priv->filepath);
options->priv->filepath = g_strdup(filename);
gm_options_save(options);
}
void
gm_options_load(GmOptions *options, const char *filename) {
FILE *f;
gchar **keyvalue, line[1024];
int i;
gm_debug_msg(DEBUG_DEFAULT, "GmOptions.load: loading options (%s)!", filename);
if ((f = fopen(filename, "r")) != NULL) {
i = 0;
while (fgets((char *) &line, 1024 - 1, f) != NULL) {
line[strlen((char *) &line) - 1] = '\0';
i++;
if (strlen(line) != 0) { // Empty lines, we don't need to process those
keyvalue = g_strsplit(line, "=", 2);
// This will return at least 1 element, at most 2, we need 2
if (strncmp(keyvalue[0], "#", 1) != 0) { // Commented lines, well ignore them too
if (keyvalue[1] != NULL) {
gm_debug_msg(DEBUG_DEFAULT, "GmOptions.load: adding %s, %s", keyvalue[0], keyvalue[1]);
gm_options_set(options, keyvalue[0], keyvalue[1]);
} else {
gm_debug_msg(DEBUG_DEFAULT, "GmOptions.load: wrong syntax of options "
"line in %s line %d", filename, i);
}
}
g_strfreev(keyvalue);
}
}
fclose(f);
} else {
gm_debug_msg(DEBUG_DEFAULT, "GmOptions.load: could not retrieve contents of file "
"%s (%s)", filename, strerror(errno));
}
g_free(options->priv->filepath);
options->priv->filepath = g_strdup(filename);
}