diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-07-13 11:36:11 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-07-13 11:36:11 +0200 |
commit | 6f87e17cd57bd735711349711ccf30b8746c2fcb (patch) | |
tree | 1868d26d335c5b1cc3b56be7c1c79ca3840dd15d | |
parent | 79bdd9f1e782c27858b9c32f300f4fb4e6b12558 (diff) | |
download | libmbim-aleksander/no-iconv.tar.gz |
libmbim-glib,message: avoid iconv()aleksander/no-iconv
There are systems out there that come with a fake iconv() implementation that
don't support translations to/from UTF-16LE. We can easily avoid that by using
the built-in translations to UTF-16HE provided by GLib itself, we just need to
take care of converting from HE to/from LE.
-rw-r--r-- | src/libmbim-glib/mbim-message.c | 74 |
1 files changed, 45 insertions, 29 deletions
diff --git a/src/libmbim-glib/mbim-message.c b/src/libmbim-glib/mbim-message.c index 4e2aca0..06b9eb8 100644 --- a/src/libmbim-glib/mbim-message.c +++ b/src/libmbim-glib/mbim-message.c @@ -193,6 +193,8 @@ _mbim_message_read_string (const MbimMessage *self, gchar *str; GError *error = NULL; guint32 information_buffer_offset; + gunichar2 *utf16d = NULL; + const gunichar2 *utf16 = NULL; information_buffer_offset = _mbim_message_get_information_buffer_offset (self); @@ -207,20 +209,29 @@ _mbim_message_read_string (const MbimMessage *self, if (!size) return NULL; - str = g_convert (G_STRUCT_MEMBER_P ( - self->data, - (information_buffer_offset + struct_start_offset + offset)), - size, - "utf-8", - "utf-16le", - NULL, - NULL, - &error); + utf16 = (const gunichar2 *) G_STRUCT_MEMBER_P (self->data, (information_buffer_offset + struct_start_offset + offset)); + + /* For BE systems, convert from LE to BE */ + if (G_BYTE_ORDER == G_BIG_ENDIAN) { + guint i; + + utf16d = (gunichar2 *) g_malloc (size); + for (i = 0; i < (size / 2); i++) + utf16d[i] = GUINT16_FROM_LE (utf16[i]); + } + + str = g_utf16_to_utf8 (utf16d ? utf16d : utf16, + size / 2, + NULL, + NULL, + &error); if (error) { g_warning ("Error converting string: %s", error->message); g_error_free (error); } + g_free (utf16d); + return str; } @@ -641,36 +652,34 @@ _mbim_struct_builder_append_string (MbimStructBuilder *builder, { guint32 offset; guint32 length; - gchar *utf16le = NULL; - guint32 utf16le_bytes = 0; + gunichar2 *utf16 = NULL; + guint32 utf16_bytes = 0; GError *error = NULL; /* A string consists of Offset+Size in the static buffer, plus the * string itself in the variable buffer */ - /* Convert the string from UTF-8 to UTF-16LE */ + /* Convert the string from UTF-8 to UTF-16HE */ if (value && value[0]) { - gsize out_bytes = 0; - - utf16le = g_convert (value, - -1, - "utf-16le", - "utf-8", - NULL, - &out_bytes, - &error); - if (error) { + glong items_written = 0; + + utf16 = g_utf8_to_utf16 (value, + -1, + NULL, /* bytes */ + &items_written, /* gunichar2 */ + &error); + if (!utf16) { g_warning ("Error converting string: %s", error->message); g_error_free (error); return; } - utf16le_bytes = out_bytes; + utf16_bytes = items_written * 2; } /* If string length is greater than 0, add the offset to fix, otherwise set * the offset to 0 and don't configure the update */ - if (utf16le_bytes == 0) { + if (utf16_bytes == 0) { offset = 0; g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); } else { @@ -688,15 +697,22 @@ _mbim_struct_builder_append_string (MbimStructBuilder *builder, } /* Add the length value */ - length = GUINT32_TO_LE (utf16le_bytes); + length = GUINT32_TO_LE (utf16_bytes); g_byte_array_append (builder->fixed_buffer, (guint8 *)&length, sizeof (length)); /* And finally, the string itself to the variable buffer */ - if (utf16le_bytes) { - g_byte_array_append (builder->variable_buffer, (const guint8 *)utf16le, (guint)utf16le_bytes); - bytearray_apply_padding (builder->variable_buffer, &utf16le_bytes); + if (utf16_bytes) { + /* For BE systems, convert from BE to LE */ + if (G_BYTE_ORDER == G_BIG_ENDIAN) { + guint i; + + for (i = 0; i < (utf16_bytes / 2); i++) + utf16[i] = GUINT16_TO_LE (utf16[i]); + } + g_byte_array_append (builder->variable_buffer, (const guint8 *)utf16, (guint)utf16_bytes); + bytearray_apply_padding (builder->variable_buffer, &utf16_bytes); } - g_free (utf16le); + g_free (utf16); } void |