summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2016-01-26 19:37:14 +0000
committerRichard Hughes <richard@hughsie.com>2016-01-26 19:37:14 +0000
commitc795d33aa1906df4af80336e3f6df39344d7632f (patch)
tree202b3beae8539c41a2869a00fbb57ad18df92267
parente740ab00457cd7bbbf5a940d79a356ed0b918d1b (diff)
downloadappstream-glib-c795d33aa1906df4af80336e3f6df39344d7632f.tar.gz
Parse the sections in the QM file format
Many thanks to Thiago Macieira for the extra help.
-rw-r--r--libappstream-glib/as-app-builder.c140
1 files changed, 72 insertions, 68 deletions
diff --git a/libappstream-glib/as-app-builder.c b/libappstream-glib/as-app-builder.c
index 8e0cea3..799e862 100644
--- a/libappstream-glib/as-app-builder.c
+++ b/libappstream-glib/as-app-builder.c
@@ -217,18 +217,27 @@ as_app_builder_search_locale_gettext (AsAppBuilderContext *ctx,
}
typedef enum {
- AS_APP_TRANSLATION_QM_TAG_END = 1,
+ AS_APP_TRANSLATION_QM_TAG_END = 0x1,
/* SourceText16 */
- AS_APP_TRANSLATION_QM_TAG_TRANSLATION = 3,
+ AS_APP_TRANSLATION_QM_TAG_TRANSLATION = 0x3,
/* Context16 */
- AS_APP_TRANSLATION_QM_TAG_OBSOLETE1 = 5,
- AS_APP_TRANSLATION_QM_TAG_SOURCE_TEXT = 6,
- AS_APP_TRANSLATION_QM_TAG_CONTEXT = 7,
- AS_APP_TRANSLATION_QM_TAG_COMMENT = 8,
+ AS_APP_TRANSLATION_QM_TAG_OBSOLETE1 = 0x5,
+ AS_APP_TRANSLATION_QM_TAG_SOURCE_TEXT = 0x6,
+ AS_APP_TRANSLATION_QM_TAG_CONTEXT = 0x7,
+ AS_APP_TRANSLATION_QM_TAG_COMMENT = 0x8,
/* Obsolete2 */
AS_APP_TRANSLATION_QM_TAG_LAST
} AsAppBuilderQmTag;
+typedef enum {
+ AS_APP_TRANSLATION_QM_SECTION_CONTEXTS = 0x2f,
+ AS_APP_TRANSLATION_QM_SECTION_HASHES = 0x42,
+ AS_APP_TRANSLATION_QM_SECTION_MESSAGES = 0x69,
+ AS_APP_TRANSLATION_QM_SECTION_NUMERUS = 0x88,
+ AS_APP_TRANSLATION_QM_SECTION_DEPS = 0x96,
+ AS_APP_TRANSLATION_QM_SECTION_LAST
+} AsAppBuilderQmSection;
+
static guint8
_read_uint8 (const guint8 *data, guint32 *offset)
{
@@ -248,96 +257,44 @@ _read_uint32 (const guint8 *data, guint32 *offset)
}
/**
- * as_app_builder_parse_file_qt:
+ * as_app_builder_parse_data_qt:
**/
-static gboolean
-as_app_builder_parse_file_qt (AsAppBuilderContext *ctx,
+static void
+as_app_builder_parse_data_qt (AsAppBuilderContext *ctx,
const gchar *locale,
- const gchar *filename,
- GError **error)
+ const guint8 *data,
+ guint32 len)
{
AsAppBuilderEntry *entry;
- guint32 addr = 0;
- guint32 len;
guint32 m = 0;
guint nstrings = 0;
- g_autofree guint8 *data = NULL;
- const guint8 qm_magic[] = {
- 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
- 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
- };
-
- /* load file */
- if (!g_file_get_contents (filename, (gchar **) &data, (gsize *) &len, error))
- return FALSE;
-
- /* check header */
- if (len < sizeof(qm_magic) ||
- memcmp (data, qm_magic, sizeof(qm_magic)) != 0) {
- g_set_error_literal (error,
- AS_APP_ERROR,
- AS_APP_ERROR_FAILED,
- "file is invalid");
- return FALSE;
- }
- m += sizeof(qm_magic);
-
- /* unknown value 0x42? */
- _read_uint8 (data, &m);
-
- /* find offset to data table */
- addr = _read_uint32 (data, &m);
- m += addr;
-
- /* unknown! */
- _read_uint8 (data, &m);
- _read_uint32 (data, &m);
- //g_debug ("seeking to QM @ %x\n", m);
/* read data */
while (m < len) {
- guint8 tag;
guint32 tag_len;
- //g_debug ("QM @%x", m);
- tag = _read_uint8(data, &m);
+ AsAppBuilderQmTag tag = _read_uint8(data, &m);
switch (tag) {
case AS_APP_TRANSLATION_QM_TAG_END:
- //g_debug ("QM{END}");
break;
case AS_APP_TRANSLATION_QM_TAG_OBSOLETE1:
m += 4;
break;
case AS_APP_TRANSLATION_QM_TAG_TRANSLATION:
- tag_len = _read_uint32 (data, &m);
- if (tag_len < 0xffffffff)
- m += tag_len;
- //g_debug ("QM{TRANSLATION} len %i", tag_len);
- nstrings++;
- break;
case AS_APP_TRANSLATION_QM_TAG_SOURCE_TEXT:
- tag_len = _read_uint32 (data, &m);
- m += tag_len;
- //g_debug ("QM{SOURCE_TEXT} len %i", tag_len);
- break;
case AS_APP_TRANSLATION_QM_TAG_CONTEXT:
- tag_len = _read_uint32 (data, &m);
- m += tag_len;
- //g_debug ("QM{CONTEXT} len %i", tag_len);
- break;
case AS_APP_TRANSLATION_QM_TAG_COMMENT:
tag_len = _read_uint32 (data, &m);
- m += tag_len;
- //g_debug ("QM{COMMENT} len %i", tag_len);
+ if (tag_len < 0xffffffff)
+ m += tag_len;
+ if (tag == AS_APP_TRANSLATION_QM_TAG_TRANSLATION)
+ nstrings++;
break;
default:
- //g_debug ("QM{unknown} tag kind %i", tag);
m = G_MAXUINT32;
break;
}
}
-// g_debug ("for QT locale %s, nstrings=%i", locale, nstrings);
-
/* add new entry */
entry = as_app_builder_entry_new ();
entry->locale = g_strdup (locale);
@@ -345,6 +302,53 @@ as_app_builder_parse_file_qt (AsAppBuilderContext *ctx,
if (entry->nstrings > ctx->max_nstrings)
ctx->max_nstrings = entry->nstrings;
ctx->data = g_list_prepend (ctx->data, entry);
+}
+
+/**
+ * as_app_builder_parse_file_qt:
+ **/
+static gboolean
+as_app_builder_parse_file_qt (AsAppBuilderContext *ctx,
+ const gchar *locale,
+ const gchar *filename,
+ GError **error)
+{
+ guint32 len;
+ guint32 m = 0;
+ g_autofree guint8 *data = NULL;
+ const guint8 qm_magic[] = {
+ 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
+ 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
+ };
+
+ /* load file */
+ if (!g_file_get_contents (filename, (gchar **) &data, (gsize *) &len, error))
+ return FALSE;
+
+ /* check header */
+ if (len < sizeof(qm_magic) ||
+ memcmp (data, qm_magic, sizeof(qm_magic)) != 0) {
+ g_set_error_literal (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "file is invalid");
+ return FALSE;
+ }
+ m += sizeof(qm_magic);
+
+ /* parse each section */
+ while (m < len) {
+ AsAppBuilderQmSection section = _read_uint8(data, &m);
+ guint32 section_len = _read_uint32 (data, &m);
+ if (section == AS_APP_TRANSLATION_QM_SECTION_MESSAGES) {
+ as_app_builder_parse_data_qt (ctx,
+ locale,
+ data + m,
+ section_len);
+ }
+ m += section_len;
+ }
+
return TRUE;
}