save key values based on their value, but we dont know what values they have yet

This commit is contained in:
Dana Jansens 2010-03-25 19:31:57 -04:00
parent a1fa5dca08
commit 749d6f0938

View file

@ -25,34 +25,52 @@
#include <stdio.h> #include <stdio.h>
#endif #endif
typedef void (*ObtDDParseGroupFunc)(const gchar *group, typedef struct _ObtDDParse ObtDDParse;
GHashTable *key_hash); typedef struct _ObtDDParseGroup ObtDDParseGroup;
typedef struct _ObtDDParseGroup { typedef void (*ObtDDParseGroupFunc)(gchar *key, const gchar *val,
ObtDDParse *parse, gboolean *error);
struct _ObtDDParseGroup {
gchar *name; gchar *name;
gboolean seen; gboolean seen;
ObtDDParseGroupFunc func; ObtDDParseGroupFunc key_func;
/* the key is a string (a key in the .desktop). /* the key is a string (a key inside the group in the .desktop).
the value is a strings (a value in the .desktop) */ the value is an ObtDDParseValue */
GHashTable *key_hash; GHashTable *key_hash;
} ObtDDParseGroup; };
typedef struct _ObtDDParse { struct _ObtDDParse {
gchar *filename; gchar *filename;
gulong lineno; gulong lineno;
ObtDDParseGroup *group; ObtDDParseGroup *group;
/* the key is a group name, the value is a ObtDDParseGroup */ /* the key is a group name, the value is a ObtDDParseGroup */
GHashTable *group_hash; GHashTable *group_hash;
} ObtDDParse; };
typedef enum { typedef enum {
DATA_STRING, DATA_STRING,
DATA_LOCALESTRING, DATA_LOCALESTRING,
DATA_STRINGS,
DATA_LOCALESTRINGS,
DATA_BOOLEAN, DATA_BOOLEAN,
DATA_NUMERIC, DATA_NUMERIC,
NUM_DATA_TYPES NUM_DATA_TYPES
} ObtDDDataType; } ObtDDDataType;
typedef struct _ObtDDParseValue {
ObtDDDataType type;
union _ObtDDParseValueValue {
gchar *string;
struct _ObtDDParseValueStrings {
gchar *s;
gulong n;
} strings;
gboolean boolean;
gfloat numeric;
} value;
} ObtDDParseValue;
struct _ObtDDFile { struct _ObtDDFile {
guint ref; guint ref;
@ -63,7 +81,7 @@ struct _ObtDDFile {
gchar *icon; /*!< Name/path for an icon for the object */ gchar *icon; /*!< Name/path for an icon for the object */
union _ObtDDFileData { union _ObtDDFileData {
struct { struct _ObtDDFileApp {
gchar *exec; /*!< Executable to run for the app */ gchar *exec; /*!< Executable to run for the app */
gchar *wdir; /*!< Working dir to run the app in */ gchar *wdir; /*!< Working dir to run the app in */
gboolean term; /*!< Run the app in a terminal or not */ gboolean term; /*!< Run the app in a terminal or not */
@ -76,22 +94,43 @@ struct _ObtDDFile {
ObtDDFileAppStartup startup; ObtDDFileAppStartup startup;
gchar *startup_wmclass; gchar *startup_wmclass;
} app; } app;
struct { struct _ObtDDFileLink {
gchar *url; gchar *url;
} link; } link;
struct { struct _ObtDDFileDir {
} dir; } dir;
} d; } d;
}; };
static void value_free(ObtDDParseValue *v)
{
switch (v->type) {
case DATA_STRING:
case DATA_LOCALESTRING:
g_free(v->value.string); break;
case DATA_STRINGS:
case DATA_LOCALESTRINGS:
g_free(v->value.strings.s);
v->value.strings.n = 0;
break;
case DATA_BOOLEAN:
break;
case DATA_NUMERIC:
break;
default:
g_assert_not_reached();
}
g_slice_free(ObtDDParseValue, v);
}
static ObtDDParseGroup* group_new(gchar *name, ObtDDParseGroupFunc f) static ObtDDParseGroup* group_new(gchar *name, ObtDDParseGroupFunc f)
{ {
ObtDDParseGroup *g = g_slice_new(ObtDDParseGroup); ObtDDParseGroup *g = g_slice_new(ObtDDParseGroup);
g->name = name; g->name = name;
g->func = f; g->key_func = f;
g->seen = FALSE; g->seen = FALSE;
g->key_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g->key_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free); g_free, (GDestroyNotify)value_free);
return g; return g;
} }
@ -117,8 +156,14 @@ static void parse_error(const gchar *m, const ObtDDParse *const parse,
} }
/* reads an input string, strips out invalid stuff, and parses /* reads an input string, strips out invalid stuff, and parses
backslash-stuff */ backslash-stuff
static gchar* parse_string(const gchar *in, gboolean locale, if @nstrings is not NULL, then it splits the output string at ';'
characters. they are all returned in the same string with null zeros
between them, @nstrings is set to the number of such strings.
*/
static gchar* parse_string(const gchar *in,
gboolean locale,
gulong *nstrings,
const ObtDDParse *const parse, const ObtDDParse *const parse,
gboolean *error) gboolean *error)
{ {
@ -143,6 +188,8 @@ static gchar* parse_string(const gchar *in, gboolean locale,
else if (!g_utf8_validate(in, bytes, &end)) else if (!g_utf8_validate(in, bytes, &end))
parse_error("Invalid bytes in localestring", parse, error); parse_error("Invalid bytes in localestring", parse, error);
if (nstrings) *nstrings = 1;
out = g_new(char, bytes + 1); out = g_new(char, bytes + 1);
i = in; o = out; i = in; o = out;
backslash = FALSE; backslash = FALSE;
@ -154,6 +201,7 @@ static gchar* parse_string(const gchar *in, gboolean locale,
case 'n': *o++ = '\n'; break; case 'n': *o++ = '\n'; break;
case 't': *o++ = '\t'; break; case 't': *o++ = '\t'; break;
case 'r': *o++ = '\r'; break; case 'r': *o++ = '\r'; break;
case ';': *o++ = ';'; break;
case '\\': *o++ = '\\'; break; case '\\': *o++ = '\\'; break;
default: default:
parse_error((locale ? parse_error((locale ?
@ -165,6 +213,10 @@ static gchar* parse_string(const gchar *in, gboolean locale,
} }
else if (*i == '\\') else if (*i == '\\')
backslash = TRUE; backslash = TRUE;
else if (*i == ';' && nstrings) {
++nstrings;
*o = '\0';
}
else if ((guchar)*i >= 127 || (guchar)*i < 32) { else if ((guchar)*i >= 127 || (guchar)*i < 32) {
/* avoid ascii control characters */ /* avoid ascii control characters */
parse_error("Found control character in string", parse, error); parse_error("Found control character in string", parse, error);
@ -190,17 +242,64 @@ static gboolean parse_bool(const gchar *in, const ObtDDParse *const parse,
return FALSE; return FALSE;
} }
static float parse_numeric(const gchar *in, const ObtDDParse *const parse, static gfloat parse_numeric(const gchar *in, const ObtDDParse *const parse,
gboolean *error) gboolean *error)
{ {
float out = 0; gfloat out = 0;
if (sscanf(in, "%f", &out) == 0) if (sscanf(in, "%f", &out) == 0)
parse_error("Invalid numeric value", parse, error); parse_error("Invalid numeric value", parse, error);
return out; return out;
} }
gboolean parse_file_line(FILE *f, gchar **buf, gulong *size, gulong *read, static void parse_group_desktop_entry(gchar *key, const gchar *val,
ObtDDParse *parse, gboolean *error) ObtDDParse *parse, gboolean *error)
{
ObtDDParseValue v, *pv;
/* figure out value type */
v.type = NUM_DATA_TYPES;
/* parse the value */
switch (v.type) {
case DATA_STRING:
v.value.string = parse_string(val, FALSE, NULL, parse, error);
g_assert(v.value.string);
break;
case DATA_LOCALESTRING:
v.value.string = parse_string(val, TRUE, NULL, parse, error);
g_assert(v.value.string);
break;
case DATA_STRINGS:
v.value.strings.s = parse_string(val, FALSE, &v.value.strings.n,
parse, error);
g_assert(v.value.strings.s);
g_assert(v.value.strings.n);
break;
case DATA_LOCALESTRINGS:
v.value.strings.s = parse_string(val, TRUE, &v.value.strings.n,
parse, error);
g_assert(v.value.strings.s);
g_assert(v.value.strings.n);
break;
case DATA_BOOLEAN:
v.value.boolean = parse_bool(val, parse, error);
break;
case DATA_NUMERIC:
v.value.numeric = parse_numeric(val, parse, error);
break;
default:
g_assert_not_reached();
}
pv = g_slice_new(ObtDDParseValue);
*pv = v;
g_hash_table_insert(parse->group->key_hash, key, pv);
}
static gboolean parse_file_line(FILE *f, gchar **buf,
gulong *size, gulong *read,
ObtDDParse *parse, gboolean *error)
{ {
const gulong BUFMUL = 80; const gulong BUFMUL = 80;
size_t ret; size_t ret;
@ -334,7 +433,7 @@ static void parse_key_value(const gchar *buf, gulong len,
ObtDDParse *parse, gboolean *error) ObtDDParse *parse, gboolean *error)
{ {
gulong i, keyend, valstart, eq; gulong i, keyend, valstart, eq;
char *key, *val; char *key;
/* find the end of the key */ /* find the end of the key */
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
@ -377,22 +476,14 @@ static void parse_key_value(const gchar *buf, gulong len,
} }
key = g_strndup(buf, keyend); key = g_strndup(buf, keyend);
val = g_strndup(buf+valstart, len-valstart);
if (g_hash_table_lookup(parse->group->key_hash, key)) { if (g_hash_table_lookup(parse->group->key_hash, key)) {
parse_error("Duplicate key found", parse, error); parse_error("Duplicate key found", parse, error);
g_free(key); g_free(key);
g_free(val);
return; return;
} }
g_hash_table_insert(parse->group->key_hash, key, val); g_print("Found key/value %s=%s.\n", key, buf+valstart);
g_print("Found key/value %s=%s.\n", key, val); if (parse->group->key_func)
} parse->group->key_func(key, buf+valstart, parse, error);
void foreach_group(gpointer pkey, gpointer pvalue, gpointer user_data)
{
gchar *name = pkey;
ObtDDParseGroup *g = pvalue;
if (g->func) g->func(name, g->key_hash);
} }
static gboolean parse_file(ObtDDFile *dd, FILE *f, ObtDDParse *parse) static gboolean parse_file(ObtDDFile *dd, FILE *f, ObtDDParse *parse)
@ -417,18 +508,10 @@ static gboolean parse_file(ObtDDFile *dd, FILE *f, ObtDDParse *parse)
++parse->lineno; ++parse->lineno;
} }
g_hash_table_foreach(parse->group_hash, foreach_group, NULL);
if (buf) g_free(buf); if (buf) g_free(buf);
return !error; return !error;
} }
static void parse_group_desktop_entry(const gchar *group,
GHashTable *keys)
{
g_print("Parsing group %s\n", group);
}
ObtDDFile* obt_ddfile_new_from_file(const gchar *name, GSList *paths) ObtDDFile* obt_ddfile_new_from_file(const gchar *name, GSList *paths)
{ {
ObtDDFile *dd; ObtDDFile *dd;