add some functions for parsing a value in a .desktop file
authorDana Jansens <danakj@orodu.net>
Wed, 24 Mar 2010 00:12:16 +0000 (20:12 -0400)
committerDana Jansens <danakj@orodu.net>
Thu, 25 Mar 2010 22:11:13 +0000 (18:11 -0400)
obt/ddfile.c

index c9ec32d..9c651e6 100644 (file)
 
 #include "obt/ddfile.h"
 #include <glib.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+typedef struct _ObtDDParse {
+    gchar *filename;
+    gulong lineno;
+} ObtDDParse;
+
+typedef enum {
+    DATA_STRING,
+    DATA_LOCALESTRING,
+    DATA_BOOLEAN,
+    DATA_NUMERIC,
+    NUM_DATA_TYPES
+} ObtDDDataType;
 
 struct _ObtDDFile {
     ObtDDFileType type;
@@ -47,3 +66,91 @@ struct _ObtDDFile {
         } dir;
     } d;
 };
+
+static void parse_error(const gchar *m, const ObtDDParse *const parse,
+                        gboolean *error)
+{
+    if (!parse->filename)
+        g_warning("%s at line %lud of input\n", m, parse->lineno);
+    else
+        g_warning("%s at line %lud of file %s\n",
+                  m, parse->lineno, parse->filename);
+    if (error) *error = TRUE;
+}
+
+/* reads an input string, strips out invalid stuff, and parses
+   backslash-stuff */
+static gchar* parse_string(const gchar *in, gboolean locale,
+                           const ObtDDParse *const parse,
+                           gboolean *error)
+{
+    const gint bytes = strlen(in);
+    gboolean backslash;
+    gchar *out, *o;
+    const gchar *end, *i;
+
+    g_return_val_if_fail(in != NULL, NULL);
+
+    if (!locale) {
+        end = in + bytes;
+        for (i = in; i < end; ++i) {
+            if (*i > 127) {
+                end = i;
+                parse_error("Invalid bytes in string", parse, error);
+                break;
+            }
+        }
+    }
+    else if (!g_utf8_validate(in, bytes, &end))
+        parse_error("Invalid bytes in localestring", parse, error);
+
+    out = g_new(char, bytes + 1);
+    i = in; o = out;
+    backslash = FALSE;
+    while (i < end) {
+        const gchar *next = locale ? g_utf8_find_next_char(i, end) : i+1;
+        if (backslash) {
+            switch(*i) {
+            case 's': *o++ = ' '; break;
+            case 'n': *o++ = '\n'; break;
+            case 't': *o++ = '\t'; break;
+            case 'r': *o++ = '\r'; break;
+            case '\\': *o++ = '\\'; break;
+            default:
+                parse_error((locale ?
+                             "Invalid escape sequence in localestring" :
+                             "Invalid escape sequence in string"),
+                            parse, error);
+            }
+            backslash = FALSE;
+        }
+        else if (*i == '\\')
+            backslash = TRUE;
+        else {
+            memcpy(o, i, next-i);
+            o += next-i;
+        }
+        i = next;
+    }
+    *o = '\0';
+    return o;
+}
+
+static gboolean parse_bool(const gchar *in, const ObtDDParse *const parse,
+                           gboolean *error)
+{
+    if (strcmp(in, "true") == 0)
+        return TRUE;
+    else if (strcmp(in, "false") != 0)
+        parse_error("Invalid boolean value", parse, error);
+    return FALSE;
+}
+
+static float parse_numeric(const gchar *in, const ObtDDParse *const parse,
+    gboolean *error)
+{
+    float out = 0;
+    if (sscanf(in, "%f", &out) == 0)
+        parse_error("Invalid numeric value", parse, error);
+    return out;
+}