iconv_t cd;
char *n;
- // fixme: add support big_endian
+ // fixme: don't enforce big endian, support old iconv
g_assert (name);
n = mono_string_to_utf8 (name);
+ /* force big endian before class libraries are fixed */
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ big_endian = 1;
+#endif
+
#ifdef HAVE_NEW_ICONV
- cd = iconv_open (n, "UTF-16le");
+ cd = iconv_open (n, big_endian ? "UTF-16be" : "UTF-16le");
#else
cd = iconv_open (n, "UTF-16");
#endif
iconv_t cd;
char *n;
- // fixme: add support big_endian
+ // fixme: don't enforce big endian, support old iconv
g_assert (name);
n = mono_string_to_utf8 (name);
+ /* force big endian before class libraries are fixed */
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ big_endian = 1;
+#endif
+
#ifdef HAVE_NEW_ICONV
- cd = iconv_open ("UTF-16le", n);
+ cd = iconv_open (big_endian ? "UTF-16be" : "UTF-16le", n);
#else
cd = iconv_open ("UTF-16", n);
#endif
}
static int
-iconv_get_length (iconv_t cd, guchar *src, int len)
+iconv_get_length (iconv_t cd, guchar *src, int len, gboolean encode)
{
guchar buf [512];
- int i, res;
+ int res;
guchar *outp;
guchar *p;
guint inbytes_remaining;
guint outbuf_size;
gboolean have_error = FALSE;
size_t err;
-
+
g_assert (cd);
g_assert (src);
#ifndef HAVE_NEW_ICONV
- if (G_BYTE_ORDER == G_LITTLE_ENDIAN) {
+ if (G_BYTE_ORDER == G_LITTLE_ENDIAN && encode) {
+ int i;
+
src = g_memdup (src, len);
for (i = 0; i < len; i += 2) {
char t = src [i];
}
#ifndef HAVE_NEW_ICONV
- if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ if (G_BYTE_ORDER == G_LITTLE_ENDIAN && encode)
g_free (src);
#endif
src = mono_array_addr (chars, guint16, index);
- return iconv_get_length (cd, src, len);
+ return iconv_get_length (cd, src, len, TRUE);
}
static int
-iconv_convert (iconv_t cd, guchar *src, int len, guchar *dest, int max_len)
+iconv_convert (iconv_t cd, guchar *src, int len, guchar *dest, int max_len, gboolean encode)
{
- int i;
guchar *p, *outp;
guint inbytes_remaining;
guint outbytes_remaining;
g_assert (dest);
#ifndef HAVE_NEW_ICONV
- if (G_BYTE_ORDER == G_LITTLE_ENDIAN) {
+ if (G_BYTE_ORDER == G_LITTLE_ENDIAN && encode) {
+ int i;
+
src = g_memdup (src, len);
for (i = 0; i < len; i += 2) {
char t = src [i];
}
#ifndef HAVE_NEW_ICONV
- if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
- g_free (src);
+ if (G_BYTE_ORDER == G_LITTLE_ENDIAN) {
+ if (encode) {
+ g_free (src);
+ } else {
+ int mb = max_len - outbytes_remaining;
+ int i;
+ for (i = 0; i < mb; i+=2) {
+ char t = dest [i];
+ dest [i] = dest [i + 1];
+ dest [i + 1] = t;
+ }
+ }
+}
#endif
if (have_error) {
g_assert_not_reached ();
guchar *src, *dest;
int len, max_len;
+ if (!charCount)
+ return 0;
+
g_assert (cd);
g_assert (chars);
g_assert (bytes);
max_len = mono_array_length (bytes) - byteIndex;
- return iconv_convert (cd, src, len, dest, max_len);
+ return iconv_convert (cd, src, len, dest, max_len, TRUE);
}
int
src = mono_array_addr (bytes, char, index);
- return iconv_get_length (cd, src, len);
+ return iconv_get_length (cd, src, len, FALSE);
}
int
max_len = (mono_array_length (chars) - charIndex) * 2;
/* iconv_convert () returns the number of bytes */
- return iconv_convert (cd, src, len, dest, max_len) / 2;
+ return iconv_convert (cd, src, len, dest, max_len, FALSE) / 2;
}