Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / gst-libs / gst / tag / mklangtables.c
1 /* GStreamer Language Tag Utility Functions
2  * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /* mklangtables.c:
21  * little program that reads iso_639.xml and outputs tables for us as fallback
22  * for when iso-codes are not available or we fail to read the file for some
23  * reason, and so we don't have to parse the xml file just to map codes.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <glib.h>
31 #include <string.h>
32
33 #define ISO_639_XML_PATH ISO_CODES_PREFIX "/share/xml/iso-codes/iso_639.xml"
34
35 typedef struct
36 {
37   gchar code_1[3];              /* de     */
38   gchar code_2t[4];             /* deu    */
39   gchar code_2b[4];             /* ger    */
40   const gchar *name;            /* German */
41   guint name_offset;            /* offset into string table */
42 } IsoLang;
43
44 static GArray *languages = NULL;
45
46 static void
47 dump_languages (void)
48 {
49   GString *names;
50   const char *s;
51   int i, num_escaped;
52
53   g_assert (languages != NULL);
54
55   names = g_string_new ("");
56
57   g_print ("/* generated by " __FILE__ " iso-codes " ISO_CODES_VERSION " */\n");
58   g_print ("\n");
59   g_print ("#include <glib.h>\n");
60   g_print ("\n");
61   g_print ("#define ISO_639_FLAG_2T  (1 << 0)\n");
62   g_print ("#define ISO_639_FLAG_2B  (1 << 1)\n");
63   g_print ("\n");
64   g_print ("/* *INDENT-OFF* */\n");
65   g_print ("\n");
66   g_print ("static const struct\n");
67   g_print ("{\n");
68   g_print ("  const gchar iso_639_1[3];\n");
69   g_print ("  const gchar iso_639_2[4];\n");
70   g_print ("  guint8 flags;\n");
71   g_print ("  guint16 name_offset;\n");
72   g_print ("} iso_639_codes[] = {\n");
73
74   for (i = 0, num_escaped = 0; i < languages->len; ++i) {
75     IsoLang *lang = &g_array_index (languages, IsoLang, i);
76
77     /* For now just print those where there's both a ISO-639-1 and -2 code */
78     if (lang->code_1[0] == '\0')
79       continue;
80
81     /* save current offset */
82     lang->name_offset = names->len;
83
84     /* adjust for fact that \000 is 4 chars now but will take up only 1 later */
85     lang->name_offset -= num_escaped * 3;
86
87     /* append one char at a time, making sure to escape UTF-8 characters */
88     for (s = lang->name; s != NULL && *s != '\0'; ++s) {
89       if (g_ascii_isprint (*s) && *s != '"' && *s != '\\') {
90         g_string_append_c (names, *s);
91       } else {
92         g_string_append_printf (names, "\\%03o", (unsigned char) *s);
93         ++num_escaped;
94       }
95     }
96     g_string_append (names, "\\000");
97     ++num_escaped;
98
99     g_print ("    /* %s */\n", lang->name);
100     if (strcmp (lang->code_2b, lang->code_2t) == 0) {
101       g_print ("  { \"%s\", \"%s\", ISO_639_FLAG_2T | ISO_639_FLAG_2B, %u },\n",
102           lang->code_1, lang->code_2t, lang->name_offset);
103     } else {
104       /* if 639-2T and 639-2B differ, put 639-2T first */
105       g_print ("  { \"%s\", \"%s\", ISO_639_FLAG_2T, %u },\n",
106           lang->code_1, lang->code_2t, lang->name_offset);
107       g_print ("  { \"%s\", \"%s\", ISO_639_FLAG_2B, %u },\n",
108           lang->code_1, lang->code_2b, lang->name_offset);
109     }
110   }
111
112   g_print ("};\n");
113   g_print ("\n");
114   g_print ("static const gchar iso_639_names[] =\n");
115   s = names->str;
116   while (s != NULL && *s != '\0') {
117     gchar line[74], *lastesc;
118     guint left;
119
120     left = strlen (s);
121     g_strlcpy (line, s, MIN (left, sizeof (line)));
122     s += sizeof (line) - 1;
123     /* avoid partial escaped codes at the end of a line */
124     if ((lastesc = strrchr (line, '\\')) && strlen (lastesc) < 4) {
125       s -= strlen (lastesc);
126       *lastesc = '\0';
127     }
128     g_print ("  \"%s\"", line);
129     if (left < 74)
130       break;
131     g_print ("\n");
132   }
133   g_print (";\n");
134   g_print ("\n");
135   g_print ("/* *INDENT-ON* */\n");
136
137   g_string_free (names, TRUE);
138 }
139
140 static gboolean
141 copy_attribute (gchar * dest, guint dest_len, const gchar ** attr_names,
142     const gchar ** attr_vals, const gchar * needle)
143 {
144   while (attr_names != NULL && *attr_names != NULL) {
145     if (strcmp (*attr_names, needle) == 0) {
146       g_strlcpy (dest, *attr_vals, dest_len);
147       return TRUE;
148     }
149     ++attr_names;
150     ++attr_vals;
151   }
152   dest[0] = '\0';
153   return FALSE;
154 }
155
156 static void
157 xml_start_element (GMarkupParseContext * ctx, const gchar * element_name,
158     const gchar ** attr_names, const gchar ** attr_vals,
159     gpointer user_data, GError ** error)
160 {
161   gchar name[256];
162   IsoLang lang;
163
164   if (strcmp (element_name, "iso_639_entry") != 0)
165     return;
166
167   copy_attribute (lang.code_1, 3, attr_names, attr_vals, "iso_639_1_code");
168   copy_attribute (lang.code_2t, 4, attr_names, attr_vals, "iso_639_2T_code");
169   copy_attribute (lang.code_2b, 4, attr_names, attr_vals, "iso_639_2B_code");
170
171   copy_attribute (name, sizeof (name), attr_names, attr_vals, "name");
172   lang.name = g_intern_string (name);
173
174   g_array_append_val (languages, lang);
175 }
176
177 static void
178 parse_iso_639_xml (const gchar * data, gsize len)
179 {
180   GMarkupParser xml_parser = { xml_start_element, NULL, NULL, NULL, NULL };
181   GMarkupParseContext *ctx;
182   GError *err = NULL;
183
184   g_return_if_fail (g_utf8_validate (data, len, NULL));
185
186   ctx = g_markup_parse_context_new (&xml_parser, 0, NULL, NULL);
187   if (!g_markup_parse_context_parse (ctx, data, len, &err))
188     g_error ("Parsing failed: %s", err->message);
189
190   g_markup_parse_context_free (ctx);
191 }
192
193 static gint
194 languages_sort_func (IsoLang * l1, IsoLang * l2)
195 {
196   if (l1 == l2)
197     return 0;
198
199   if (l1->code_1[0] == '\0' && l2->code_1[0] != '\0')
200     return -1;
201
202   return strcmp (l1->code_1, l2->code_1);
203 }
204
205 int
206 main (int argc, char **argv)
207 {
208   GMappedFile *f;
209   gchar *xml_data;
210   gsize xml_len;
211
212   f = g_mapped_file_new (ISO_639_XML_PATH, FALSE, NULL);
213   if (f != NULL) {
214     xml_data = (gchar *) g_mapped_file_get_contents (f);
215     xml_len = g_mapped_file_get_length (f);
216   } else {
217     GError *err = NULL;
218
219     if (!g_file_get_contents (ISO_639_XML_PATH, &xml_data, &xml_len, &err))
220       g_error ("Could not read %s: %s", ISO_639_XML_PATH, err->message);
221   }
222
223   languages = g_array_new (FALSE, TRUE, sizeof (IsoLang));
224
225   parse_iso_639_xml (xml_data, xml_len);
226
227   g_array_sort (languages, (GCompareFunc) languages_sort_func);
228
229   dump_languages ();
230
231   g_array_free (languages, TRUE);
232
233   if (f != NULL)
234     g_mapped_file_unref (f);
235   else
236     g_free (xml_data);
237
238   return 0;
239 }