#include <mono/metadata/object.h>
#include <mono/metadata/unicode.h>
-#include <iconv.h>
+#if HAVE_ICONV_H
+#include <iconv.h>
+#elif HAVE_GICONV_H
+#include <giconv.h>
+#endif
static MonoUnicodeCategory catmap[] = {
/* G_UNICODE_CONTROL = */ Control,
gboolean
ves_icall_System_Char_IsNumber (gunichar2 c)
{
- return g_unichar_isdigit (c);
+ GUnicodeType t = g_unichar_type (c);
+ return t == G_UNICODE_DECIMAL_NUMBER ||
+ t == G_UNICODE_LETTER_NUMBER ||
+ t == G_UNICODE_OTHER_NUMBER;
}
gboolean
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
g_assert (cd != (iconv_t)-1);
+ g_free (n);
return (gpointer)cd;
}
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
g_assert (cd != (iconv_t)-1);
+ g_free (n);
return (gpointer)cd;
}
}
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];
outbytes_remaining = outbuf_size;
outp = buf;
- err = iconv (cd, (const char **)&p, &inbytes_remaining,
+ err = iconv (cd, (char **)&p, &inbytes_remaining,
(char **)&outp, &outbytes_remaining);
if(err == (size_t)-1) {
}
#ifndef HAVE_NEW_ICONV
- if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ if (G_BYTE_ORDER == G_LITTLE_ENDIAN && encode)
g_free (src);
#endif
}
int
-ves_icall_iconv_get_byte_count (gpointer converter, MonoArray *chars, gint32 index, gint32 count)
+ves_icall_iconv_get_byte_count (gpointer converter, MonoArray *chars, gint32 idx, gint32 count)
{
iconv_t cd = (iconv_t)converter;
guchar *src;
g_assert (cd);
g_assert (chars);
- g_assert (mono_array_length (chars) > index);
- g_assert (mono_array_length (chars) >= (index + count));
+ g_assert (mono_array_length (chars) > idx);
+ g_assert (mono_array_length (chars) >= (idx + count));
- if (!(len = (mono_array_length (chars) - index) * 2))
+ if (!(len = (mono_array_length (chars) - idx) * 2))
return 0;
- src = mono_array_addr (chars, guint16, index);
+ src = mono_array_addr (chars, guint16, idx);
- 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];
outbytes_remaining = outbuf_size;
outp = dest;
- err = iconv (cd, (const char **)&p, &inbytes_remaining, (char **)&outp, &outbytes_remaining);
+ err = iconv (cd, (char **)&p, &inbytes_remaining, (char **)&outp, &outbytes_remaining);
if(err == (size_t)-1) {
if (errno == EINVAL) {
}
#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 ();
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
-ves_icall_iconv_get_char_count (gpointer converter, MonoArray *bytes, gint32 index, gint32 count)
+ves_icall_iconv_get_char_count (gpointer converter, MonoArray *bytes, gint32 idx, gint32 count)
{
iconv_t cd = (iconv_t)converter;
guchar *src;
- int len;
g_assert (cd);
g_assert (bytes);
- g_assert (mono_array_length (bytes) > index);
- g_assert (mono_array_length (bytes) >= (index + count));
+ g_assert (mono_array_length (bytes) > idx);
+ g_assert (mono_array_length (bytes) >= (idx + count));
- if (!(len = (mono_array_length (bytes) - index)))
- return 0;
-
- src = mono_array_addr (bytes, char, index);
+ src = mono_array_addr (bytes, char, idx);
- return iconv_get_length (cd, src, len);
+ /* iconv_get_length () returns the number of bytes */
+ return iconv_get_length (cd, src, (int) count, FALSE) / 2;
}
int
{
iconv_t cd = (iconv_t)converter;
guchar *src, *dest;
- int len, max_len;
+ int max_len;
g_assert (cd);
g_assert (chars);
g_assert (mono_array_length (chars) >= (byteIndex + byteCount));
g_assert (mono_array_length (chars) > charIndex);
- if (!(len = (mono_array_length (bytes) - byteIndex)))
- return 0;
-
src = mono_array_addr (bytes, char, byteIndex);
dest = mono_array_addr (chars, guint16, charIndex);
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, (int) byteCount, dest, max_len, FALSE) / 2;
}