Merge pull request #822 from carlosmn/asp-pc
[mono.git] / eglib / src / giconv.c
index 9fe0edd3324fc1857cde28612bcc90b01aec8bfa..61db988909bdcb399dabe675754e09113eecc5ef 100644 (file)
@@ -174,14 +174,34 @@ gsize
 g_iconv (GIConv cd, gchar **inbytes, gsize *inbytesleft,
         gchar **outbytes, gsize *outbytesleft)
 {
-       size_t inleft, outleft;
+       gsize inleft, outleft;
        char *inptr, *outptr;
        gunichar c;
        int rc = 0;
        
 #ifdef HAVE_ICONV
-       if (cd->cd != (iconv_t) -1)
-               return iconv (cd->cd, inbytes, inbytesleft, outbytes, outbytesleft);
+       if (cd->cd != (iconv_t) -1) {
+               /* Note: gsize may have a different size than size_t, so we need to
+                  remap inbytesleft and outbytesleft to size_t's. */
+               size_t *outleftptr, *inleftptr;
+               size_t n_outleft, n_inleft;
+               
+               if (inbytesleft) {
+                       n_inleft = *inbytesleft;
+                       inleftptr = &n_inleft;
+               } else {
+                       inleftptr = NULL;
+               }
+               
+               if (outbytesleft) {
+                       n_outleft = *outbytesleft;
+                       outleftptr = &n_outleft;
+               } else {
+                       outleftptr = NULL;
+               }
+               
+               return iconv (cd->cd, inbytes, inleftptr, outbytes, outleftptr);
+       }
 #endif
        
        if (outbytes == NULL || outbytesleft == NULL) {
@@ -640,7 +660,7 @@ gchar *
 g_convert (const gchar *str, gssize len, const gchar *to_charset, const gchar *from_charset,
           gsize *bytes_read, gsize *bytes_written, GError **err)
 {
-       size_t outsize, outused, outleft, inleft, grow, rc;
+       gsize outsize, outused, outleft, inleft, grow, rc;
        char *result, *outbuf, *inbuf;
        gboolean flush = FALSE;
        gboolean done = FALSE;
@@ -676,7 +696,7 @@ g_convert (const gchar *str, gssize len, const gchar *to_charset, const gchar *f
                else
                        rc = g_iconv (cd, NULL, NULL, &outbuf, &outleft);
                
-               if (rc == (size_t) -1) {
+               if (rc == (gsize) -1) {
                        switch (errno) {
                        case E2BIG:
                                /* grow our result buffer */
@@ -901,7 +921,7 @@ eg_utf8_to_utf16_general (const gchar *str, glong len, glong *items_read, glong
        size_t inleft;
        char *inptr;
        gunichar c;
-       int n;
+       int u, n;
        
        g_return_val_if_fail (str != NULL, NULL);
        
@@ -910,6 +930,7 @@ eg_utf8_to_utf16_general (const gchar *str, glong len, glong *items_read, glong
                        g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, "Conversions with embedded nulls must pass the string length");
                        return NULL;
                }
+               
                len = strlen (str);
        }
        
@@ -917,29 +938,18 @@ eg_utf8_to_utf16_general (const gchar *str, glong len, glong *items_read, glong
        inleft = len;
        
        while (inleft > 0) {
-               if ((n = decode_utf8 (inptr, inleft, &c)) < 0) {
-                       if (errno == EILSEQ) {
-                               g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
-                                            "Illegal byte sequence encounted in the input.");
-                       } else if (items_read) {
-                               /* partial input is ok if we can let our caller know... */
-                               break;
-                       } else {
-                               g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
-                                            "Partial byte sequence encountered in the input.");
-                       }
-                       
-                       if (items_read)
-                               *items_read = inptr - str;
-                       
-                       if (items_written)
-                               *items_written = 0;
-                       
-                       return NULL;
-               } else if (c == 0 && !include_nuls)
+               if ((n = decode_utf8 (inptr, inleft, &c)) < 0)
+                       goto error;
+               
+               if (c == 0 && !include_nuls)
                        break;
                
-               outlen += g_unichar_to_utf16 (c, NULL);
+               if ((u = g_unichar_to_utf16 (c, NULL)) < 0) {
+                       errno = EILSEQ;
+                       goto error;
+               }
+               
+               outlen += u;
                inleft -= n;
                inptr += n;
        }
@@ -957,7 +967,8 @@ eg_utf8_to_utf16_general (const gchar *str, glong len, glong *items_read, glong
        while (inleft > 0) {
                if ((n = decode_utf8 (inptr, inleft, &c)) < 0)
                        break;
-               else if (c == 0 && !include_nuls)
+               
+               if (c == 0 && !include_nuls)
                        break;
                
                outptr += g_unichar_to_utf16 (c, outptr);
@@ -968,6 +979,25 @@ eg_utf8_to_utf16_general (const gchar *str, glong len, glong *items_read, glong
        *outptr = '\0';
        
        return outbuf;
+       
+ error:
+       if (errno == EILSEQ) {
+               g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+                            "Illegal byte sequence encounted in the input.");
+       } else if (items_read) {
+               /* partial input is ok if we can let our caller know... */
+       } else {
+               g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
+                            "Partial byte sequence encountered in the input.");
+       }
+       
+       if (items_read)
+               *items_read = inptr - str;
+       
+       if (items_written)
+               *items_written = 0;
+       
+       return NULL;
 }
 
 gunichar2 *