<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
    <title></title>
  </head>
  <body text="#000000" bgcolor="#ffffff">
    On 04/20/2011 12:00 AM, Rodrigo Kumpera wrote:
    <blockquote
      cite="mid:BANLkTimQG0dqkk0LJ_k6YhoPUeCmw1JrhQ@mail.gmail.com"
      type="cite">
      <p>Jeff, shouldn't this be part of eglib as a build time option?</p>
    </blockquote>
    <br>
    I suppose it could be, but I think the plan right now is to simply
    remove g_iconv() from eglib since eglib is supposed to remain a
    minimalist version of glib as per discussion with Miguel.<br>
    <br>
    It's also probably not very useful for most people who want to use
    g_iconv() to *just* have UTF-16/32BE/LE to UTF-8 conversion.<br>
    <br>
    Jeff<br>
    <br>
    <br>
    <blockquote
      cite="mid:BANLkTimQG0dqkk0LJ_k6YhoPUeCmw1JrhQ@mail.gmail.com"
      type="cite">
      <div class="gmail_quote">On Apr 19, 2011 10:06 PM, "Jeffrey
        Stedfast (<a moz-do-not-send="true" href="mailto:fejj@gnome.org">fejj@gnome.org</a>)"
        &lt;<a moz-do-not-send="true"
          href="mailto:mono-patches@lists.ximian.com">mono-patches@lists.ximian.com</a>&gt;
        wrote:<br type="attribution">
        &gt; <br>
        &gt; Branch: refs/heads/master<br>
        &gt; Home: <a moz-do-not-send="true"
          href="https://github.com/mono/moon">https://github.com/mono/moon</a><br>
        &gt; <br>
        &gt; Commit: caef081dc43c17327c37932f65264deec19d8022<br>
        &gt; Author: Jeffrey Stedfast &lt;<a moz-do-not-send="true"
          href="mailto:fejj@gnome.org">fejj@gnome.org</a>&gt;<br>
        &gt; Date: 04/19/2011 21:05:59<br>
        &gt; URL: <a moz-do-not-send="true"
href="https://github.com/mono/moon/commit/caef081dc43c17327c37932f65264deec19d8022">https://github.com/mono/moon/commit/caef081dc43c17327c37932f65264deec19d8022</a><br>
        &gt; <br>
        &gt; Implemented an iconv-like API for unicode conversion<br>
        &gt; <br>
        &gt; Changed paths:<br>
        &gt; M src/Makefile.am<br>
        &gt; Added paths:<br>
        &gt; A src/miconv.cpp<br>
        &gt; A src/miconv.h<br>
        &gt; <br>
        &gt; Modified: src/Makefile.am<br>
        &gt;
        ===================================================================<br>
        &gt; --- a/src/Makefile.am<br>
        &gt; +++ b/src/Makefile.am<br>
        &gt; @@ -78,6 +78,7 @@ libmoon_include_headers = \<br>
        &gt; medialog.h \<br>
        &gt; mediaplayer.h \<br>
        &gt; messaging.h \<br>
        &gt; + miconv.h \<br>
        &gt; moon-curves.h \<br>
        &gt; moonlightconfiguration.h\<br>
        &gt; moon-path.h \<br>
        &gt; @@ -234,6 +235,7 @@ dist_libmoon_la_SOURCES = \<br>
        &gt; medialog.cpp \<br>
        &gt; mediaplayer.cpp \<br>
        &gt; messaging.cpp \<br>
        &gt; + miconv.cpp \<br>
        &gt; moon-curves.c \<br>
        &gt; moonlightconfiguration.cpp \<br>
        &gt; moon-path.c \<br>
        &gt; <br>
        &gt; Added: src/miconv.cpp<br>
        &gt;
        ===================================================================<br>
        &gt; --- /dev/null<br>
        &gt; +++ b/src/miconv.cpp<br>
        &gt; @@ -0,0 +1,344 @@<br>
        &gt; +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t;
        c-basic-offset: 8 -*- */<br>
        &gt; +/*<br>
        &gt; + * miconv.cpp: <br>
        &gt; + *<br>
        &gt; + * Contact:<br>
        &gt; + * Moonlight List (<a moz-do-not-send="true"
          href="mailto:moonlight-list@lists.ximian.com">moonlight-list@lists.ximian.com</a>)<br>
        &gt; + *<br>
        &gt; + * Copyright 2011 Novell, Inc. (<a moz-do-not-send="true"
          href="http://www.novell.com">http://www.novell.com</a>)<br>
        &gt; + *<br>
        &gt; + * See the LICENSE file included with the distribution for
        details.<br>
        &gt; + */<br>
        &gt; +<br>
        &gt; +#include &lt;config.h&gt;<br>
        &gt; +<br>
        &gt; +#include &lt;glib.h&gt;<br>
        &gt; +#include &lt;string.h&gt;<br>
        &gt; +#include &lt;errno.h&gt;<br>
        &gt; +<br>
        &gt; +#include "miconv.h"<br>
        &gt; +<br>
        &gt; +namespace Moonlight {<br>
        &gt; +<br>
        &gt; +enum Endian {<br>
        &gt; + LittleEndian,<br>
        &gt; + BigEndian<br>
        &gt; +};<br>
        &gt; +<br>
        &gt; +typedef int (* Decoder) (Endian endian, char **inbytes,
        size_t *inbytesleft, gunichar *outchar);<br>
        &gt; +typedef int (* Encoder) (gunichar c, char **outbytes,
        size_t *outbytesleft);<br>
        &gt; +<br>
        &gt; +static int decode_utf32 (Endian endian, char **inbytes,
        size_t *inbytesleft, gunichar *outchar);<br>
        &gt; +//static int encode_utf32 (gunichar c, char **outbytes,
        size_t *outbytesleft);<br>
        &gt; +<br>
        &gt; +static int decode_utf16 (Endian endian, char **inbytes,
        size_t *inbytesleft, gunichar *outchar);<br>
        &gt; +//static int encode_utf16 (gunichar c, char **outbytes,
        size_t *outbytesleft);<br>
        &gt; +<br>
        &gt; +static int decode_utf8 (Endian endian, char **inbytes,
        size_t *inbytesleft, gunichar *outchar);<br>
        &gt; +static int encode_utf8 (gunichar c, char **outbytes,
        size_t *outbytesleft);<br>
        &gt; +<br>
        &gt; +static struct {<br>
        &gt; + const char *name;<br>
        &gt; + Decoder decoder;<br>
        &gt; + Encoder encoder;<br>
        &gt; + Endian endian;<br>
        &gt; +} charsets[] = {<br>
        &gt; + { "UTF-32BE", decode_utf32, NULL, BigEndian },<br>
        &gt; + { "UTF-32LE", decode_utf32, NULL, LittleEndian },<br>
        &gt; + { "UTF-16BE", decode_utf16, NULL, BigEndian },<br>
        &gt; + { "UTF-16LE", decode_utf16, NULL, LittleEndian },<br>
        &gt; + { "UTF-8", decode_utf8, encode_utf8, LittleEndian },<br>
        &gt; +};<br>
        &gt; +<br>
        &gt; +struct _miconv_t {<br>
        &gt; + Decoder decode;<br>
        &gt; + Encoder encode;<br>
        &gt; + Endian endian;<br>
        &gt; + gunichar c;<br>
        &gt; +};<br>
        &gt; +<br>
        &gt; +<br>
        &gt; +miconv_t<br>
        &gt; +miconv_open (const char *to, const char *from)<br>
        &gt; +{<br>
        &gt; + Decoder decoder = NULL;<br>
        &gt; + Encoder encoder = NULL;<br>
        &gt; + Endian endian;<br>
        &gt; + miconv_t cd;<br>
        &gt; + guint i;<br>
        &gt; + <br>
        &gt; + if (!to || !from)<br>
        &gt; + return (miconv_t) -1;<br>
        &gt; + <br>
        &gt; + for (i = 0; i &lt; G_N_ELEMENTS (charsets); i++) {<br>
        &gt; + if (!strcmp (charsets[i].name, from)) {<br>
        &gt; + decoder = charsets[i].decoder;<br>
        &gt; + endian = charsets[i].endian;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (!strcmp (charsets[i].name, to))<br>
        &gt; + encoder = charsets[i].encoder;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (encoder == NULL || decoder == NULL)<br>
        &gt; + return (miconv_t) -1;<br>
        &gt; + <br>
        &gt; + cd = (miconv_t) g_malloc (sizeof (*cd));<br>
        &gt; + cd-&gt;decode = decoder;<br>
        &gt; + cd-&gt;encode = encoder;<br>
        &gt; + cd-&gt;endian = endian;<br>
        &gt; + cd-&gt;c = -1;<br>
        &gt; + <br>
        &gt; + return cd;<br>
        &gt; +}<br>
        &gt; +<br>
        &gt; +int<br>
        &gt; +miconv_close (miconv_t cd)<br>
        &gt; +{<br>
        &gt; + g_free (cd);<br>
        &gt; + return 0;<br>
        &gt; +}<br>
        &gt; +<br>
        &gt; +int<br>
        &gt; +miconv (miconv_t cd, char **inbytes, size_t *inbytesleft,<br>
        &gt; + char **outbytes, size_t *outbytesleft)<br>
        &gt; +{<br>
        &gt; + size_t inleft, outleft;<br>
        &gt; + char *inptr, *outptr;<br>
        &gt; + gunichar c;<br>
        &gt; + int rc = 0;<br>
        &gt; + <br>
        &gt; + if (outbytes == NULL || outbytesleft == NULL) {<br>
        &gt; + /* reset converter */<br>
        &gt; + cd-&gt;c = -1;<br>
        &gt; + return 0;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + inleft = inbytesleft ? *inbytesleft : 0;<br>
        &gt; + inptr = inbytes ? *inbytes : NULL;<br>
        &gt; + outleft = *outbytesleft;<br>
        &gt; + outptr = *outbytes;<br>
        &gt; + c = cd-&gt;c;<br>
        &gt; + <br>
        &gt; + while (inleft &gt;= 0 &amp;&amp; outleft &gt; 0) {<br>
        &gt; + if (c == (gunichar) -1 &amp;&amp; cd-&gt;decode
        (cd-&gt;endian, &amp;inptr, &amp;inleft, &amp;c) == -1) {<br>
        &gt; + rc = -1;<br>
        &gt; + break;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (cd-&gt;encode (c, &amp;outptr, &amp;outleft) == -1) {<br>
        &gt; + rc = -1;<br>
        &gt; + break;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + c = -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (inbytesleft)<br>
        &gt; + *inbytesleft = inleft;<br>
        &gt; + <br>
        &gt; + if (inbytes)<br>
        &gt; + *inbytes = inptr;<br>
        &gt; + <br>
        &gt; + *outbytesleft = outleft;<br>
        &gt; + *outbytes = outptr;<br>
        &gt; + cd-&gt;c = c;<br>
        &gt; + <br>
        &gt; + return rc;<br>
        &gt; +}<br>
        &gt; +<br>
        &gt; +<br>
        &gt; +static int<br>
        &gt; +decode_utf32 (Endian endian, char **inbytes, size_t
        *inbytesleft, gunichar *outchar)<br>
        &gt; +{<br>
        &gt; + gunichar *inptr = (gunichar *) *inbytes;<br>
        &gt; + size_t inleft = *inbytesleft;<br>
        &gt; + gunichar c;<br>
        &gt; + <br>
        &gt; + if (inleft &lt; 4) {<br>
        &gt; + errno = EINVAL;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (endian == BigEndian)<br>
        &gt; + c = GUINT32_FROM_BE (*inptr);<br>
        &gt; + else<br>
        &gt; + c = GUINT32_FROM_LE (*inptr);<br>
        &gt; + <br>
        &gt; + inleft -= 4;<br>
        &gt; + inptr++;<br>
        &gt; + <br>
        &gt; + if (c &gt;= 2147483648UL) {<br>
        &gt; + errno = EILSEQ;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + *inbytes = (char *) inptr;<br>
        &gt; + *inbytesleft = inleft;<br>
        &gt; + *outchar = c;<br>
        &gt; + <br>
        &gt; + return 0;<br>
        &gt; +}<br>
        &gt; +<br>
        &gt; +//static int encode_utf32 (gunichar c, char **outbytes,
        size_t *outbytesleft);<br>
        &gt; +<br>
        &gt; +static int<br>
        &gt; +decode_utf16 (Endian endian, char **inbytes, size_t
        *inbytesleft, gunichar *outchar)<br>
        &gt; +{<br>
        &gt; + gunichar2 *inptr = (gunichar2 *) *inbytes;<br>
        &gt; + size_t inleft = *inbytesleft;<br>
        &gt; + gunichar2 c;<br>
        &gt; + gunichar u;<br>
        &gt; + <br>
        &gt; + if (inleft &lt; 2) {<br>
        &gt; + errno = EINVAL;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (endian == BigEndian)<br>
        &gt; + u = GUINT16_FROM_BE (*inptr);<br>
        &gt; + else<br>
        &gt; + u = GUINT16_FROM_LE (*inptr);<br>
        &gt; + <br>
        &gt; + inleft -= 2;<br>
        &gt; + inptr++;<br>
        &gt; + <br>
        &gt; + if (u &gt;= 0xdc00 &amp;&amp; u &lt;= 0xdfff) {<br>
        &gt; + errno = EILSEQ;<br>
        &gt; + return -1;<br>
        &gt; + } else if (u &gt;= 0xd800 &amp;&amp; u &lt;= 0xdbff) {<br>
        &gt; + if (inleft &lt; 2) {<br>
        &gt; + errno = EINVAL;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (endian == BigEndian)<br>
        &gt; + c = GUINT16_FROM_BE (*inptr);<br>
        &gt; + else<br>
        &gt; + c = GUINT16_FROM_LE (*inptr);<br>
        &gt; + <br>
        &gt; + inleft -= 2;<br>
        &gt; + inptr++;<br>
        &gt; + <br>
        &gt; + if (c &lt; 0xdc00 || c &gt; 0xdfff) {<br>
        &gt; + errno = EILSEQ;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + u = ((u - 0xd800) &lt;&lt; 10) + (c - 0xdc00) +
        0x0010000UL;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + *inbytes = (char *) inptr;<br>
        &gt; + *inbytesleft = inleft;<br>
        &gt; + *outchar = u;<br>
        &gt; + <br>
        &gt; + return 0;<br>
        &gt; +}<br>
        &gt; +<br>
        &gt; +//static int encode_utf16 (gunichar c, char **outbytes,
        size_t *outbytesleft);<br>
        &gt; +<br>
        &gt; +static int<br>
        &gt; +decode_utf8 (Endian endian, char **inbytes, size_t
        *inbytesleft, gunichar *outchar)<br>
        &gt; +{<br>
        &gt; + size_t inleft = *inbytesleft;<br>
        &gt; + char *inptr = *inbytes;<br>
        &gt; + size_t i, len = 0;<br>
        &gt; + unsigned char c;<br>
        &gt; + gunichar u;<br>
        &gt; + <br>
        &gt; + c = *inptr++;<br>
        &gt; + <br>
        &gt; + if (c &lt; 0x80) {<br>
        &gt; + /* simple ascii case */<br>
        &gt; + len = 1;<br>
        &gt; + } else if ((c &amp; 0xe0) == 0xc0) {<br>
        &gt; + c &amp;= 0x1f;<br>
        &gt; + len = 2;<br>
        &gt; + } else if ((c &amp; 0xf0) == 0xe0) {<br>
        &gt; + c &amp;= 0x0f;<br>
        &gt; + len = 3;<br>
        &gt; + } else if ((c &amp; 0xf8) == 0xf0) {<br>
        &gt; + c &amp;= 0x07;<br>
        &gt; + len = 4;<br>
        &gt; + } else if ((c &amp; 0xfc) == 0xf8) {<br>
        &gt; + c &amp;= 0x03;<br>
        &gt; + len = 5;<br>
        &gt; + } else if ((c &amp; 0xfe) == 0xfc) {<br>
        &gt; + c &amp;= 0x01;<br>
        &gt; + len = 6;<br>
        &gt; + } else {<br>
        &gt; + errno = EILSEQ;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (len &gt; inleft) {<br>
        &gt; + errno = EINVAL;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + u = c;<br>
        &gt; + for (i = 1; i &lt; len; i++) {<br>
        &gt; + u &lt;&lt;= 6 | ((*inptr) &amp; 0x3f);<br>
        &gt; + inptr++;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + *inbytesleft = inleft - len;<br>
        &gt; + *inbytes = inptr;<br>
        &gt; + *outchar = u;<br>
        &gt; + <br>
        &gt; + return 0;<br>
        &gt; +}<br>
        &gt; +<br>
        &gt; +static int<br>
        &gt; +encode_utf8 (gunichar c, char **outbytes, size_t
        *outbytesleft)<br>
        &gt; +{<br>
        &gt; + size_t outleft = *outbytesleft;<br>
        &gt; + char *outptr = *outbytes;<br>
        &gt; + size_t len, i;<br>
        &gt; + char base;<br>
        &gt; + <br>
        &gt; + if (c &lt; 128UL) {<br>
        &gt; + base = 0;<br>
        &gt; + len = 1;<br>
        &gt; + } else if (c &lt; 2048UL) {<br>
        &gt; + base = 192;<br>
        &gt; + len = 2;<br>
        &gt; + } else if (c &lt; 65536UL) {<br>
        &gt; + base = 224;<br>
        &gt; + len = 3;<br>
        &gt; + } else if (c &lt; 2097152UL) {<br>
        &gt; + base = 240;<br>
        &gt; + len = 4;<br>
        &gt; + } else if (c &lt; 67108864UL) {<br>
        &gt; + base = 248; <br>
        &gt; + len = 5;<br>
        &gt; + } else if (c &lt; 2147483648UL) {<br>
        &gt; + base = 252;<br>
        &gt; + len = 6;<br>
        &gt; + } else {<br>
        &gt; + errno = EINVAL;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + if (outleft &lt; len) {<br>
        &gt; + errno = E2BIG;<br>
        &gt; + return -1;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + for (i = len - 1; i &gt; 0; i--) {<br>
        &gt; + /* mask off 6 bits worth and add 128 */<br>
        &gt; + outptr[i] = 128 + (c &amp; 0x3f);<br>
        &gt; + c &gt;&gt;= 6;<br>
        &gt; + }<br>
        &gt; + <br>
        &gt; + /* first character has a different base */<br>
        &gt; + outptr[0] = base + (c &amp; 0x3f);<br>
        &gt; + <br>
        &gt; + *outbytesleft = outleft - len;<br>
        &gt; + *outbytes = outptr + len;<br>
        &gt; + <br>
        &gt; + return 0;<br>
        &gt; +}<br>
        &gt; +<br>
        &gt; +};<br>
        &gt; +<br>
        &gt; <br>
        &gt; Added: src/miconv.h<br>
        &gt;
        ===================================================================<br>
        &gt; --- /dev/null<br>
        &gt; +++ b/src/miconv.h<br>
        &gt; @@ -0,0 +1,35 @@<br>
        &gt; +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t;
        c-basic-offset: 8 -*- */<br>
        &gt; +/*<br>
        &gt; + * miconv.h: <br>
        &gt; + *<br>
        &gt; + * Contact:<br>
        &gt; + * Moonlight List (<a moz-do-not-send="true"
          href="mailto:moonlight-list@lists.ximian.com">moonlight-list@lists.ximian.com</a>)<br>
        &gt; + *<br>
        &gt; + * Copyright 2011 Novell, Inc. (<a moz-do-not-send="true"
          href="http://www.novell.com">http://www.novell.com</a>)<br>
        &gt; + *<br>
        &gt; + * See the LICENSE file included with the distribution for
        details.<br>
        &gt; + */<br>
        &gt; +<br>
        &gt; +#ifndef __MICONV_H__<br>
        &gt; +#define __MICONV_H__<br>
        &gt; +<br>
        &gt; +#include &lt;glib.h&gt;<br>
        &gt; +#include &lt;sys/types.h&gt;<br>
        &gt; +<br>
        &gt; +namespace Moonlight {<br>
        &gt; +<br>
        &gt; +G_BEGIN_DECLS<br>
        &gt; +<br>
        &gt; +typedef struct _miconv_t *miconv_t;<br>
        &gt; +<br>
        &gt; +int miconv (miconv_t cd, char **inbytes, size_t
        *inbytesleft,<br>
        &gt; + char **outbytes, size_t *outbytesleft);<br>
        &gt; +miconv_t miconv_open (const char *to, const char *from);<br>
        &gt; +int miconv_close (miconv_t cd);<br>
        &gt; +<br>
        &gt; +G_END_DECLS<br>
        &gt; +<br>
        &gt; +};<br>
        &gt; +<br>
        &gt; +#endif /* __MICONV_H__ */<br>
        &gt; +<br>
        &gt; <br>
        &gt; <br>
        &gt; <br>
        &gt; <br>
        &gt; <br>
        &gt; _______________________________________________<br>
        &gt; Mono-patches maillist - <a moz-do-not-send="true"
          href="mailto:Mono-patches@lists.ximian.com">Mono-patches@lists.ximian.com</a><br>
        &gt; <a moz-do-not-send="true"
          href="http://lists.ximian.com/mailman/listinfo/mono-patches">http://lists.ximian.com/mailman/listinfo/mono-patches</a><br>
      </div>
    </blockquote>
    <br>
  </body>
</html>