summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2007-01-21 20:13:06 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2007-01-21 20:13:06 +0000
commit49f7899a1bde827dff68a755977be4f0cb52f20e (patch)
tree34400f48cec53b394b2fb89ab0e47de888d639b8
parentcb3478520fc9ea7296c9b393721a47e6744801c8 (diff)
First go at somewhat functional g_key_file_* impementation
-rw-r--r--eglib/gmain.c133
-rw-r--r--eglib/gmain.h2
2 files changed, 122 insertions, 13 deletions
diff --git a/eglib/gmain.c b/eglib/gmain.c
index 381aece1..108df5f5 100644
--- a/eglib/gmain.c
+++ b/eglib/gmain.c
@@ -12,6 +12,9 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/file.h>
#include <gmain.h>
@@ -571,6 +574,24 @@ GError* g_error_new_literal(GQuark domain, gint code, const gchar *message)
return err;
}
+void g_set_error(GError **err, GQuark domain, gint code,
+ const gchar *format, ...)
+{
+ gchar msg[1024];
+ va_list ap;
+
+ if (!err)
+ return;
+
+ va_start(ap, format);
+
+ vsnprintf(msg, sizeof(msg) - 1, format, ap);
+
+ va_end(ap);
+
+ *err = g_error_new_literal(domain, code, msg);
+}
+
void g_error_free(GError *err)
{
g_free(err->message);
@@ -1180,11 +1201,6 @@ struct _GKeyFile {
gchar *filename;
};
-struct _GKeyFileKeyValuePair {
- gchar *key; /* NULL for comments */
- gchar *value;
-};
-
GKeyFile *g_key_file_new(void)
{
return g_new0(GKeyFile, 1);
@@ -1210,10 +1226,90 @@ gchar *g_key_file_get_string(GKeyFile *key_file,
const gchar *key,
GError **error)
{
- /* Not implemented */
- if (error)
- *error = g_error_new_literal(0, 0, "Not implemented");
- return NULL;
+ struct stat st;
+ char *map, *nl, *off, *group = NULL, *value = NULL, tmp[1024];
+ off_t size;
+ size_t key_len, to_copy, value_len;
+ int fd, err = 0;
+
+ fd = open(key_file->filename, O_RDONLY);
+ if (fd < 0) {
+ g_set_error(error, 0, 0, "%s: %s", key_file->filename,
+ strerror(errno));
+ return NULL;
+ }
+
+ if (flock(fd, LOCK_SH) < 0) {
+ err = errno;
+ goto close;
+ }
+
+ if (fstat(fd, &st) < 0) {
+ err = errno;
+ goto unlock;
+ }
+
+ size = st.st_size;
+
+ map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (!map || map == MAP_FAILED) {
+ err = errno;
+ goto unlock;
+ }
+
+ group = strstr(map, group_name);
+ if (!group)
+ goto unmap;
+
+ nl = strchr(group, '\n');
+ if (!nl)
+ goto unmap;
+
+ off = strstr(nl + 1, key);
+ if (!off)
+ goto unmap;
+
+ key_len = strlen(key);
+
+ if (off[key_len] != '=')
+ goto unmap;
+
+ off += key_len + 1;
+
+ nl = strchr(off, '\n');
+ if (!nl)
+ goto unmap;
+
+ value_len = nl - off;
+
+ to_copy = value_len > (sizeof(tmp) - 1) ? sizeof(tmp) - 1 : value_len;
+
+ memset(tmp, 0, sizeof(tmp));
+
+ strncpy(tmp, off, to_copy);
+
+ value = g_strdup(tmp);
+
+unmap:
+ munmap(map, size);
+
+unlock:
+ flock(fd, LOCK_UN);
+
+close:
+ close(fd);
+
+ if (err)
+ g_set_error(error, 0, 0, "%s: %s", key_file->filename,
+ strerror(err));
+ else if (!group)
+ g_set_error(error, 0, 0, "%s: group %s not found",
+ key_file->filename, group_name);
+ else if (!value)
+ g_set_error(error, 0, 0, "%s: key %s not found",
+ key_file->filename, key);
+
+ return value;
}
gboolean g_key_file_get_boolean(GKeyFile *key_file,
@@ -1221,9 +1317,20 @@ gboolean g_key_file_get_boolean(GKeyFile *key_file,
const gchar *key,
GError **error)
{
- /* Not implemented */
- if (error)
- *error = g_error_new_literal(0, 0, "Not implemented");
- return FALSE;
+ gboolean ret;
+ gchar *str;
+
+ str = g_key_file_get_string(key_file, group_name, key, error);
+ if (!str)
+ return FALSE;
+
+ if (strcmp(str, str) == 0)
+ ret = TRUE;
+ else
+ ret = FALSE;
+
+ g_free(str);
+
+ return ret;
}
diff --git a/eglib/gmain.h b/eglib/gmain.h
index cafc2353..175872d9 100644
--- a/eglib/gmain.h
+++ b/eglib/gmain.h
@@ -119,6 +119,8 @@ typedef struct {
gchar *message;
} GError;
+void g_set_error(GError **err, GQuark domain, gint code,
+ const gchar *format, ...);
GError* g_error_new_literal(GQuark domain, gint code, const gchar *message);
void g_error_free(GError *err);