6 #include <glib/gstdio.h>
7 #include "icon_tools.h"
27 static tag_map_t tag_map[] =
29 {"resources", R_RESOURCES},
30 {"section", R_SECTION},
35 #define TAG_MAP_SZ (sizeof(tag_map)/sizeof(tag_map_t))
47 GList *inc_list = NULL;
50 find_file(GList *list, const gchar *name)
59 inc = (gchar*)link->data;
60 str = g_strdup_printf("%s/%s", inc, name);
61 if (g_file_test(str, G_FILE_TEST_IS_REGULAR))
66 link = g_list_next(link);
68 if (g_file_test(name, G_FILE_TEST_IS_REGULAR))
70 return g_strdup(name);
78 const gchar **attr_names,
79 const gchar **attr_values)
83 if (attr_names == NULL) return NULL;
84 for (ii = 0; attr_names[ii] != NULL; ii++)
86 if (strcmp(name, attr_names[ii]) == 0)
87 return attr_values[ii];
93 read_string_from_file(const gchar *filename)
100 fd = g_fopen(filename, "r");
103 fseek(fd, 0, SEEK_END);
105 fseek(fd, 0, SEEK_SET);
106 buffer = g_malloc(size+1);
107 size = fread(buffer, 1, size, fd);
109 gval = ghb_value_new(G_TYPE_STRING);
110 g_value_take_string(gval, buffer);
117 GMarkupParseContext *ctx,
119 const gchar **attr_names,
120 const gchar **attr_values,
124 parse_data_t *pd = (parse_data_t*)ud;
132 // Check to see if the first element found has been closed
133 // If so, ignore any junk following it.
137 for (ii = 0; ii < TAG_MAP_SZ; ii++)
139 if (strcmp(tag, tag_map[ii].tag) == 0)
141 id.id = tag_map[ii].id;
145 if (ii == TAG_MAP_SZ)
147 g_warning("Unrecognized start tag (%s)", tag);
150 g_queue_push_head(pd->tag_stack, id.pid);
153 GValue *current = g_queue_peek_head(pd->stack);
160 name = lookup_attr_value("name", attr_names, attr_values);
161 if (name && strcmp(name, "icons") == 0)
163 gval = ghb_dict_value_new();
164 if (pd->key) g_free(pd->key);
165 pd->key = g_strdup(name);
166 g_queue_push_head(pd->stack, gval);
174 name = lookup_attr_value("file", attr_names, attr_values);
175 filename = find_file(inc_list, name);
176 name = lookup_attr_value("name", attr_names, attr_values);
177 if (filename && name)
182 rd = g_malloc(sizeof(ghb_rawdata_t));
183 rd->data = icon_file_serialize(filename, &size);
185 gval = ghb_rawdata_value_new(rd);
186 if (pd->key) g_free(pd->key);
187 pd->key = g_strdup(name);
192 g_warning("%s:missing a requried attribute", name);
201 name = lookup_attr_value("file", attr_names, attr_values);
202 filename = find_file(inc_list, name);
203 name = lookup_attr_value("name", attr_names, attr_values);
204 if (filename && name)
206 gval = ghb_plist_parse_file(filename);
207 if (pd->key) g_free(pd->key);
208 pd->key = g_strdup(name);
213 g_warning("%s:missing a requried attribute", name);
222 name = lookup_attr_value("file", attr_names, attr_values);
223 filename = find_file(inc_list, name);
224 name = lookup_attr_value("name", attr_names, attr_values);
225 if (filename && name)
227 gval = read_string_from_file(filename);
228 if (pd->key) g_free(pd->key);
229 pd->key = g_strdup(name);
234 g_warning("%s:missing a requried attribute", name);
239 // Add the element to the current container
241 { // There's an element to add
247 gtype = G_VALUE_TYPE(current);
248 if (gtype == ghb_array_get_type())
250 ghb_array_append(current, gval);
252 else if (gtype == ghb_dict_get_type())
256 g_warning("No key for dictionary item");
257 ghb_value_free(gval);
261 ghb_dict_insert(current, g_strdup(pd->key), gval);
266 g_error("Invalid container type. This shouldn't happen");
273 GMarkupParseContext *ctx,
278 parse_data_t *pd = (parse_data_t*)ud;
287 // Check to see if the first element found has been closed
288 // If so, ignore any junk following it.
292 for (ii = 0; ii < TAG_MAP_SZ; ii++)
294 if (strcmp(name, tag_map[ii].tag) == 0)
300 if (ii == TAG_MAP_SZ)
302 g_warning("Unrecognized start tag (%s)", name);
305 start_id.pid = g_queue_pop_head(pd->tag_stack);
306 if (start_id.id != id)
307 g_warning("start tag != end tag: (%s %d) %d", name, id, id);
310 GValue *current = g_queue_peek_head(pd->stack);
316 g_queue_pop_head(pd->stack);
321 // Get the top of the data structure stack and if it's an array
322 // or dict, add the current element
326 pd->closed_top = TRUE;
329 gtype = G_VALUE_TYPE(current);
330 if (gtype == ghb_array_get_type())
332 ghb_array_append(current, gval);
334 else if (gtype == ghb_dict_get_type())
338 g_warning("No key for dictionary item");
339 ghb_value_free(gval);
343 ghb_dict_insert(current, g_strdup(pd->key), gval);
348 g_error("Invalid container type. This shouldn't happen");
351 if (g_queue_is_empty(pd->tag_stack))
352 pd->closed_top = TRUE;
357 GMarkupParseContext *ctx,
363 parse_data_t *pd = (parse_data_t*)ud;
364 if (pd->value) g_free(pd->value);
365 pd->value = g_strdup(text);
370 GMarkupParseContext *ctx,
376 //parse_data_t *pd = (parse_data_t*)ud;
378 //g_debug("passthrough %s", text);
382 parse_error(GMarkupParseContext *ctx, GError *error, gpointer ud)
384 g_warning("Resource parse error: %s", error->message);
387 // This is required or the parser crashes
389 destroy_notify(gpointer data)
391 //g_debug("destroy parser");
395 ghb_resource_parse(const gchar *buf, gssize len)
397 GMarkupParseContext *ctx;
398 GMarkupParser parser;
402 pd.stack = g_queue_new();
403 pd.tag_stack = g_queue_new();
406 pd.plist = ghb_dict_value_new();
407 g_queue_push_head(pd.stack, pd.plist);
408 pd.closed_top = FALSE;
410 parser.start_element = start_element;
411 parser.end_element = end_element;
412 parser.text = text_data;
413 parser.passthrough = passthrough;
414 parser.error = parse_error;
415 ctx = g_markup_parse_context_new(&parser, 0, &pd, destroy_notify);
417 g_markup_parse_context_parse(ctx, buf, len, &err);
418 g_markup_parse_context_end_parse(ctx, &err);
419 g_markup_parse_context_free(ctx);
420 g_queue_free(pd.stack);
421 g_queue_free(pd.tag_stack);
426 ghb_resource_parse_file(FILE *fd)
434 fseek(fd, 0, SEEK_END);
436 fseek(fd, 0, SEEK_SET);
437 buffer = g_malloc(size+1);
438 size = fread(buffer, 1, size, fd);
440 gval = ghb_resource_parse(buffer, (gssize)size);
449 "Usage: %s [-I <inc path>] <in resource list> <out resource plist>\n"
451 " Creates a resource plist from a resource list\n"
453 " I - Include path to search for files\n"
454 " <in resource list> Input resources file\n"
455 " <out resource plist> Output resources plist file\n"
464 main(gint argc, gchar *argv[])
469 const gchar *src, *dst;
473 opt = getopt(argc, argv, OPTS);
479 inc_list = g_list_prepend(inc_list, g_strdup(optarg));
484 if (optind != argc - 2)
489 src = argv[optind++];
490 dst = argv[optind++];
493 file = g_fopen(src, "r");
496 fprintf(stderr, "Error: failed to open %s\n", src);
500 gval = ghb_resource_parse_file(file);
501 ghb_plist_write_file(dst, gval);