summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2016-07-13 11:36:11 +0200
committerAleksander Morgado <aleksander@aleksander.es>2016-07-13 11:36:11 +0200
commit6f87e17cd57bd735711349711ccf30b8746c2fcb (patch)
tree1868d26d335c5b1cc3b56be7c1c79ca3840dd15d
parent79bdd9f1e782c27858b9c32f300f4fb4e6b12558 (diff)
downloadlibmbim-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.c74
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