Revision: 2135
          http://gtkpod.svn.sourceforge.net/gtkpod/?rev=2135&view=rev
Author:   teuf
Date:     2008-10-07 18:56:51 +0000 (Tue, 07 Oct 2008)

Log Message:
-----------
Add array support to the plist parser

The SysInfoExtended file on the ipod used to contain the artwork formats in
<array> tags containing <key> tags as well as the value. This is not valid
according to the plist DTD, and this was fixed with the 4th generation Nanos
(but not with the 120GB ipod classic).
libgpod was written using invalid (wrt to the XML DTD) files, and thus handled
<array> elements as if they were <dict> elements (because of the <key> tags).
This was wrong, and prevented it from parsing the fixed SysInfoExtended file
on the new Nanos. This changeset implements support for <array> tags (ignoring
tags like <key> in the process so as not to fail with older SysInfoExtended
files)

Modified Paths:
--------------
    libgpod/trunk/ChangeLog
    libgpod/trunk/src/itdb_plist.c

Modified: libgpod/trunk/ChangeLog
===================================================================
--- libgpod/trunk/ChangeLog     2008-10-05 06:40:04 UTC (rev 2134)
+++ libgpod/trunk/ChangeLog     2008-10-07 18:56:51 UTC (rev 2135)
@@ -1,3 +1,9 @@
+2008-10-07  Christophe Fergeau  <[EMAIL PROTECTED]>
+
+       * src/itdb_plist.c: add support for <array> tags to the plist
+       parser, this is needed to support SysInfoExtended files as found on
+       on the 4g nanos
+
 2008-10-05  Christophe Fergeau  <[EMAIL PROTECTED]>
 
        * src/itdb_device.c: add serial number for the 8GB Silver Nano 4g

Modified: libgpod/trunk/src/itdb_plist.c
===================================================================
--- libgpod/trunk/src/itdb_plist.c      2008-10-05 06:40:04 UTC (rev 2134)
+++ libgpod/trunk/src/itdb_plist.c      2008-10-07 18:56:51 UTC (rev 2135)
@@ -32,8 +32,6 @@
  * 
  * This parser should handle most plist files, with those limitations :
  *      - no support for <date> tags
- *      - no support for <array> containing "unamed" elements (ie with no
- *      <key> tag)
  *
  * The plist file is parsed using libxml, and the parsed result is stored 
  * in GValue. The types are mapped in the following way:
@@ -42,7 +40,7 @@
  *      - <integer> => G_TYPE_INT (gint)
  *      - <true/>, <false/> => G_TYPE_BOOLEAN (gboolean)
  *      - <data> => G_TYPE_GSTRING (GString *)
- *      - <array> => G_TYPE_HASH_TABLE (GHashTable *)
+ *      - <array> => G_TYPE_VALUE_ARRAY (GValueArray *)
  *      - <dict> => G_TYPE_HASH_TABLE (GHashTable *)
  */
 #ifdef HAVE_CONFIG_H
@@ -248,6 +246,7 @@
         cur_node = parse_one_dict_entry (cur_node, dict, error);
     }
     if ((error != NULL) && (*error != NULL)) {
+        g_hash_table_destroy (dict);
         return NULL;
     }
     value = g_new0 (GValue, 1);
@@ -256,39 +255,92 @@
 
     return value;
 }
+       
+typedef GValue *(*ParseCallback) (xmlNode *, GError **);
+static ParseCallback get_parser_for_type (const xmlChar *type);
 
-typedef GValue *(*ParseCallback) (xmlNode *, GError **);
+static GValue * 
+parse_array (xmlNode *a_node, GError **error)
+{
+    xmlNode *cur_node = a_node->children;
+    GValue *value;
+    GValueArray *array;
+
+    array = g_value_array_new (4);
+
+    while (cur_node != NULL) {
+       if (get_parser_for_type (cur_node->name) != NULL) {
+           GValue *cur_value;
+           cur_value = parse_node (cur_node, error);
+           if (cur_value != NULL) {
+               array = g_value_array_append (array, cur_value);
+               g_value_unset (cur_value);
+               g_free (cur_value);
+           }
+       }
+       /* When an array contains an element enclosed in "unknown" tags (ie 
+        * non-type ones), we silently skip them since early
+        * SysInfoExtended files used to have <key> values enclosed within 
+        * <array> tags.
+        */
+       cur_node = cur_node->next;
+    }
+
+    if ((error != NULL) && (*error != NULL)) {
+       g_value_array_free (array);
+        return NULL;
+    }
+    value = g_new0 (GValue, 1);
+    value = g_value_init (value, G_TYPE_VALUE_ARRAY);
+    g_value_take_boxed (value, array);
+
+    return value;
+}
+
 struct Parser {
     const char * const type_name;
     ParseCallback parser;
 };
 
-static struct Parser parsers[] = { {"integer", parse_integer},
-                                   {"real",    parse_real},
-                                   {"string",  parse_string},
-                                   {"true",    parse_boolean},
-                                   {"false",   parse_boolean},
-                                   {"data",    parse_data},
-                                   {"dict",    parse_dict}, 
-                                   {"array",   parse_dict},
-                                   {NULL,      NULL} };
+static const struct Parser parsers[] = { {"integer", parse_integer},
+                                        {"real",    parse_real},
+                                        {"string",  parse_string},
+                                        {"true",    parse_boolean},
+                                        {"false",   parse_boolean},
+                                        {"data",    parse_data},
+                                        {"dict",    parse_dict}, 
+                                        {"array",   parse_array},
+                                        {NULL,      NULL} };
 
-static GValue *parse_node (xmlNode *a_node, GError **error)
+static ParseCallback get_parser_for_type (const xmlChar *type)
 {
     guint i = 0;
-    g_return_val_if_fail (a_node != NULL, FALSE);
+
     while (parsers[i].type_name != NULL) {        
-        if (xmlStrcmp (a_node->name, (xmlChar *)parsers[i].type_name) == 0) {
+        if (xmlStrcmp (type, (xmlChar *)parsers[i].type_name) == 0) {
             if (parsers[i].parser != NULL) {
-                return parsers[i].parser (a_node, error);
+                return parsers[i].parser;
             }
         }
         i++;
     }
-    DEBUG ("no parser for <%s>\n", a_node->name);
     return NULL;
 }
 
+static GValue *parse_node (xmlNode *a_node, GError **error)
+{
+    ParseCallback parser;
+
+    g_return_val_if_fail (a_node != NULL, NULL);
+    parser = get_parser_for_type (a_node->name);
+    if (parser != NULL) {
+       return parser (a_node, error);
+    } else {
+       DEBUG ("no parser for <%s>\n", a_node->name);
+       return NULL;
+    }
+}
+
 static GValue *
 itdb_plist_parse (xmlNode * a_node, GError **error)
 {


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to