Doc fixes.
[platform/upstream/glib.git] / glib / gutf8.c
1 /* gutf8.c - Operations on UTF-8 strings.
2  *
3  * Copyright (C) 1999 Tom Tromey
4  * Copyright (C) 2000 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <config.h>
23
24 #include <stdlib.h>
25 #ifdef HAVE_CODESET
26 #include <langinfo.h>
27 #endif
28 #include <string.h>
29
30 #include "glib.h"
31
32 #ifdef G_PLATFORM_WIN32
33 #include <stdio.h>
34 #define STRICT
35 #include <windows.h>
36 #undef STRICT
37 #endif
38
39 #include "glibintl.h"
40
41 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
42   if (Char < 128)                                                             \
43     {                                                                         \
44       Len = 1;                                                                \
45       Mask = 0x7f;                                                            \
46     }                                                                         \
47   else if ((Char & 0xe0) == 0xc0)                                             \
48     {                                                                         \
49       Len = 2;                                                                \
50       Mask = 0x1f;                                                            \
51     }                                                                         \
52   else if ((Char & 0xf0) == 0xe0)                                             \
53     {                                                                         \
54       Len = 3;                                                                \
55       Mask = 0x0f;                                                            \
56     }                                                                         \
57   else if ((Char & 0xf8) == 0xf0)                                             \
58     {                                                                         \
59       Len = 4;                                                                \
60       Mask = 0x07;                                                            \
61     }                                                                         \
62   else if ((Char & 0xfc) == 0xf8)                                             \
63     {                                                                         \
64       Len = 5;                                                                \
65       Mask = 0x03;                                                            \
66     }                                                                         \
67   else if ((Char & 0xfe) == 0xfc)                                             \
68     {                                                                         \
69       Len = 6;                                                                \
70       Mask = 0x01;                                                            \
71     }                                                                         \
72   else                                                                        \
73     Len = -1;
74
75 #define UTF8_LENGTH(Char)              \
76   ((Char) < 0x80 ? 1 :                 \
77    ((Char) < 0x800 ? 2 :               \
78     ((Char) < 0x10000 ? 3 :            \
79      ((Char) < 0x200000 ? 4 :          \
80       ((Char) < 0x4000000 ? 5 : 6)))))
81    
82
83 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
84   (Result) = (Chars)[0] & (Mask);                                             \
85   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
86     {                                                                         \
87       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
88         {                                                                     \
89           (Result) = -1;                                                      \
90           break;                                                              \
91         }                                                                     \
92       (Result) <<= 6;                                                         \
93       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
94     }
95
96 #define UNICODE_VALID(Char)                   \
97     ((Char) < 0x110000 &&                     \
98      ((Char) < 0xD800 || (Char) >= 0xE000) && \
99      (Char) != 0xFFFE && (Char) != 0xFFFF)
100    
101      
102 static const gchar utf8_skip_data[256] = {
103   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
104   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
105   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
106   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
107   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
108   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
109   2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
110   3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0
111 };
112
113 const gchar * const g_utf8_skip = utf8_skip_data;
114
115 /**
116  * g_utf8_find_prev_char:
117  * @str: pointer to the beginning of a UTF-8 string
118  * @p: pointer to some position within @str
119  * 
120  * Given a position @p with a UTF-8 encoded string @str, find the start
121  * of the previous UTF-8 character starting before @p. Returns %NULL if no
122  * UTF-8 characters are present in @p before @str.
123  *
124  * @p does not have to be at the beginning of a UTF-8 chracter. No check
125  * is made to see if the character found is actually valid other than
126  * it starts with an appropriate byte.
127  *
128  * Return value: a pointer to the found character or %NULL.
129  **/
130 gchar *
131 g_utf8_find_prev_char (const char *str,
132                        const char *p)
133 {
134   for (--p; p >= str; --p)
135     {
136       if ((*p & 0xc0) != 0x80)
137         return (gchar *)p;
138     }
139   return NULL;
140 }
141
142 /**
143  * g_utf8_find_next_char:
144  * @p: a pointer to a position within a UTF-8 encoded string
145  * @end: a pointer to the end of the string, or %NULL to indicate
146  *        that the string is NULL terminated, in which case
147  *        the returned value will be 
148  *
149  * Find the start of the next utf-8 character in the string after @p
150  *
151  * @p does not have to be at the beginning of a UTF-8 chracter. No check
152  * is made to see if the character found is actually valid other than
153  * it starts with an appropriate byte.
154  * 
155  * Return value: a pointer to the found character or %NULL
156  **/
157 gchar *
158 g_utf8_find_next_char (const gchar *p,
159                        const gchar *end)
160 {
161   if (*p)
162     {
163       if (end)
164         for (++p; p < end && (*p & 0xc0) == 0x80; ++p)
165           ;
166       else
167         for (++p; (*p & 0xc0) == 0x80; ++p)
168           ;
169     }
170   return (p == end) ? NULL : (gchar *)p;
171 }
172
173 /**
174  * g_utf8_prev_char:
175  * @p: a pointer to a position within a UTF-8 encoded string
176  *
177  * Find the previous UTF-8 character in the string before @p.
178  *
179  * @p does not have to be at the beginning of a UTF-8 character. No check
180  * is made to see if the character found is actually valid other than
181  * it starts with an appropriate byte. If @p might be the first
182  * character of the string, you must use g_utf8_find_prev_char instead.
183  * 
184  * Return value: a pointer to the found character.
185  **/
186 gchar *
187 g_utf8_prev_char (const gchar *p)
188 {
189   while (TRUE)
190     {
191       p--;
192       if ((*p & 0xc0) != 0x80)
193         return (gchar *)p;
194     }
195 }
196
197 /**
198  * g_utf8_strlen:
199  * @p: pointer to the start of a UTF-8 string.
200  * @max: the maximum number of bytes to examine. If @max
201  *       is less than 0, then the string is assumed to be
202  *       nul-terminated.
203  * 
204  * Return value: the length of the string in characters
205  **/
206 glong
207 g_utf8_strlen (const gchar *p,
208                gssize       max)
209 {
210   glong len = 0;
211   const gchar *start = p;
212
213   if (max < 0)
214     {
215       while (*p)
216         {
217           p = g_utf8_next_char (p);
218           ++len;
219         }
220     }
221   else
222     {
223       if (max == 0 || !*p)
224         return 0;
225       
226       p = g_utf8_next_char (p);          
227
228       while (p - start < max && *p)
229         {
230           ++len;
231           p = g_utf8_next_char (p);          
232         }
233
234       /* only do the last len increment if we got a complete
235        * char (don't count partial chars)
236        */
237       if (p - start == max)
238         ++len;
239     }
240
241   return len;
242 }
243
244 /**
245  * g_utf8_get_char:
246  * @p: a pointer to unicode character encoded as UTF-8
247  * 
248  * Convert a sequence of bytes encoded as UTF-8 to a unicode character.
249  * If @p does not point to a valid UTF-8 encoded character, results are
250  * undefined. If you are not sure that the bytes are complete
251  * valid unicode characters, you should use g_utf8_get_char_validated()
252  * instead.
253  * 
254  * Return value: the resulting character
255  **/
256 gunichar
257 g_utf8_get_char (const gchar *p)
258 {
259   int i, mask = 0, len;
260   gunichar result;
261   unsigned char c = (unsigned char) *p;
262
263   UTF8_COMPUTE (c, mask, len);
264   if (len == -1)
265     return (gunichar)-1;
266   UTF8_GET (result, p, i, mask, len);
267
268   return result;
269 }
270
271 /**
272  * g_utf8_offset_to_pointer:
273  * @str: a UTF-8 encoded string
274  * @offset: a character offset within the string.
275  * 
276  * Converts from an integer character offset to a pointer to a position
277  * within the string.
278  * 
279  * Return value: the resulting pointer
280  **/
281 gchar *
282 g_utf8_offset_to_pointer  (const gchar *str,
283                            glong        offset)    
284 {
285   const gchar *s = str;
286   while (offset--)
287     s = g_utf8_next_char (s);
288   
289   return (gchar *)s;
290 }
291
292 /**
293  * g_utf8_pointer_to_offset:
294  * @str: a UTF-8 encoded string
295  * @pos: a pointer to a position within @str
296  * 
297  * Converts from a pointer to position within a string to a integer
298  * character offset
299  * 
300  * Return value: the resulting character offset
301  **/
302 glong    
303 g_utf8_pointer_to_offset (const gchar *str,
304                           const gchar *pos)
305 {
306   const gchar *s = str;
307   glong offset = 0;    
308   
309   while (s < pos)
310     {
311       s = g_utf8_next_char (s);
312       offset++;
313     }
314
315   return offset;
316 }
317
318
319 /**
320  * g_utf8_strncpy:
321  * @dest: buffer to fill with characters from @src
322  * @src: UTF-8 string
323  * @n: character count
324  * 
325  * Like the standard C strncpy() function, but copies a given number
326  * of characters instead of a given number of bytes. The @src string
327  * must be valid UTF-8 encoded text. (Use g_utf8_validate() on all
328  * text before trying to use UTF-8 utility functions with it.)
329  * 
330  * Return value: @dest
331  **/
332 gchar *
333 g_utf8_strncpy (gchar       *dest,
334                 const gchar *src,
335                 gsize        n)
336 {
337   const gchar *s = src;
338   while (n && *s)
339     {
340       s = g_utf8_next_char(s);
341       n--;
342     }
343   strncpy(dest, src, s - src);
344   dest[s - src] = 0;
345   return dest;
346 }
347
348 static gboolean
349 g_utf8_get_charset_internal (char **a)
350 {
351   char *charset = getenv("CHARSET");
352
353   if (charset && a && ! *a)
354     *a = charset;
355
356   if (charset && strstr (charset, "UTF-8"))
357       return TRUE;
358
359 #ifdef HAVE_CODESET
360   charset = nl_langinfo(CODESET);
361   if (charset)
362     {
363       if (a && ! *a)
364         *a = charset;
365       if (strcmp (charset, "UTF-8") == 0)
366         return TRUE;
367     }
368 #endif
369   
370 #if 0 /* #ifdef _NL_CTYPE_CODESET_NAME */
371   charset = nl_langinfo (_NL_CTYPE_CODESET_NAME);
372   if (charset)
373     {
374       if (a && ! *a)
375         *a = charset;
376       if (strcmp (charset, "UTF-8") == 0)
377         return TRUE;
378     }
379 #endif
380
381 #ifdef G_PLATFORM_WIN32
382   if (a && ! *a)
383     {
384       static char codepage[10];
385       
386       sprintf (codepage, "CP%d", GetACP ());
387       *a = codepage;
388       /* What about codepage 1200? Is that UTF-8? */
389       return FALSE;
390     }
391 #else
392   if (a && ! *a) 
393     *a = "US-ASCII";
394 #endif
395
396   /* Assume this for compatibility at present.  */
397   return FALSE;
398 }
399
400 static int utf8_locale_cache = -1;
401 static char *utf8_charset_cache = NULL;
402
403 /**
404  * g_get_charset:
405  * @charset: return location for character set name
406  * 
407  * Obtains the character set for the current locale; you might use
408  * this character set as an argument to g_convert(), to convert from
409  * the current locale's encoding to some other encoding. (Frequently
410  * g_locale_to_utf8() and g_locale_from_utf8() are nice shortcuts,
411  * though.)
412  *
413  * The return value is %TRUE if the locale's encoding is UTF-8, in that
414  * case you can perhaps avoid calling g_convert().
415  *
416  * The string returned in @charset is not allocated, and should not be
417  * freed.
418  * 
419  * Return value: %TRUE if the returned charset is UTF-8
420  **/
421 gboolean
422 g_get_charset (G_CONST_RETURN char **charset) 
423 {
424   if (utf8_locale_cache != -1)
425     {
426       if (charset)
427         *charset = utf8_charset_cache;
428       return utf8_locale_cache;
429     }
430   utf8_locale_cache = g_utf8_get_charset_internal (&utf8_charset_cache);
431   if (charset) 
432     *charset = utf8_charset_cache;
433   return utf8_locale_cache;
434 }
435
436 /* unicode_strchr */
437
438 /**
439  * g_unichar_to_utf8:
440  * @c: a ISO10646 character code
441  * @outbuf: output buffer, must have at least 6 bytes of space.
442  *       If %NULL, the length will be computed and returned
443  *       and nothing will be written to @out.
444  * 
445  * Convert a single character to utf8
446  * 
447  * Return value: number of bytes written
448  **/
449 int
450 g_unichar_to_utf8 (gunichar c,
451                    gchar   *outbuf)
452 {
453   guint len = 0;    
454   int first;
455   int i;
456
457   if (c < 0x80)
458     {
459       first = 0;
460       len = 1;
461     }
462   else if (c < 0x800)
463     {
464       first = 0xc0;
465       len = 2;
466     }
467   else if (c < 0x10000)
468     {
469       first = 0xe0;
470       len = 3;
471     }
472    else if (c < 0x200000)
473     {
474       first = 0xf0;
475       len = 4;
476     }
477   else if (c < 0x4000000)
478     {
479       first = 0xf8;
480       len = 5;
481     }
482   else
483     {
484       first = 0xfc;
485       len = 6;
486     }
487
488   if (outbuf)
489     {
490       for (i = len - 1; i > 0; --i)
491         {
492           outbuf[i] = (c & 0x3f) | 0x80;
493           c >>= 6;
494         }
495       outbuf[0] = c | first;
496     }
497
498   return len;
499 }
500
501 /**
502  * g_utf8_strchr:
503  * @p: a nul-terminated utf-8 string
504  * @len: the maximum length of p
505  * @c: a iso-10646 character
506  * 
507  * Find the leftmost occurence of the given iso-10646 character
508  * in a UTF-8 string, while limiting the search to p_len bytes.
509  * If len is -1, allow unbounded search.
510  * 
511  * Return value: NULL if the string does not contain the character, otherwise, a
512  *               a pointer to the start of the leftmost of the character in the string.
513  **/
514 gchar *
515 g_utf8_strchr (const char *p,
516                gssize      len,
517                gunichar    c)
518 {
519   gchar ch[10];
520
521   gint charlen = g_unichar_to_utf8 (c, ch);
522   ch[charlen] = '\0';
523   
524   return g_strstr_len (p, len, ch);
525 }
526
527
528 /**
529  * g_utf8_strrchr:
530  * @p: a nul-terminated utf-8 string
531  * @len: the maximum length of p
532  * @c: a iso-10646 character/
533  * 
534  * Find the rightmost occurence of the given iso-10646 character
535  * in a UTF-8 string, while limiting the search to p_len bytes.
536  * If len is -1, allow unbounded search.
537  * 
538  * Return value: NULL if the string does not contain the character, otherwise, a
539  *               a pointer to the start of the rightmost of the character in the string.
540  **/
541 gchar *
542 g_utf8_strrchr (const char *p,
543                 gssize      len,
544                 gunichar    c)
545 {
546   gchar ch[10];
547
548   gint charlen = g_unichar_to_utf8 (c, ch);
549   ch[charlen] = '\0';
550   
551   return g_strrstr_len (p, len, ch);
552 }
553
554
555 /* Like g_utf8_get_char, but take a maximum length
556  * and return (gunichar)-2 on incomplete trailing character
557  */
558 static inline gunichar
559 g_utf8_get_char_extended (const  gchar *p,
560                           gssize max_len)  
561 {
562   guint i, len;
563   gunichar wc = (guchar) *p;
564
565   if (wc < 0x80)
566     {
567       return wc;
568     }
569   else if (wc < 0xc0)
570     {
571       return (gunichar)-1;
572     }
573   else if (wc < 0xe0)
574     {
575       len = 2;
576       wc &= 0x1f;
577     }
578   else if (wc < 0xf0)
579     {
580       len = 3;
581       wc &= 0x0f;
582     }
583   else if (wc < 0xf8)
584     {
585       len = 4;
586       wc &= 0x07;
587     }
588   else if (wc < 0xfc)
589     {
590       len = 5;
591       wc &= 0x03;
592     }
593   else if (wc < 0xfe)
594     {
595       len = 6;
596       wc &= 0x01;
597     }
598   else
599     {
600       return (gunichar)-1;
601     }
602   
603   if (max_len >= 0 && len > max_len)
604     {
605       for (i = 1; i < max_len; i++)
606         {
607           if ((((guchar *)p)[i] & 0xc0) != 0x80)
608             return (gunichar)-1;
609         }
610       return (gunichar)-2;
611     }
612
613   for (i = 1; i < len; ++i)
614     {
615       gunichar ch = ((guchar *)p)[i];
616       
617       if ((ch & 0xc0) != 0x80)
618         {
619           if (ch)
620             return (gunichar)-1;
621           else
622             return (gunichar)-2;
623         }
624
625       wc <<= 6;
626       wc |= (ch & 0x3f);
627     }
628
629   if (UTF8_LENGTH(wc) != len)
630     return (gunichar)-1;
631   
632   return wc;
633 }
634
635 /**
636  * g_utf8_get_char_validated:
637  * @p: a pointer to unicode character encoded as UTF-8
638  * @max_len: the maximum number of bytes to read, or -1, for no maximum.
639  * 
640  * Convert a sequence of bytes encoded as UTF-8 to a unicode character.
641  * This function checks for incomplete characters, for invalid characters
642  * such as characters that are out of the range of Unicode, and for
643  * overlong encodings of valid characters.
644  * 
645  * Return value: the resulting character. If @p points to a partial
646  *    sequence at the end of a string that could begin a valid character,
647  *    returns (gunichar)-2; otherwise, if @p does not point to a valid
648  *    UTF-8 encoded unicode character, returns (gunichar)-1.
649  **/
650 gunichar
651 g_utf8_get_char_validated (const  gchar *p,
652                            gssize max_len)
653 {
654   gunichar result = g_utf8_get_char_extended (p, max_len);
655
656   if (result & 0x80000000)
657     return result;
658   else if (!UNICODE_VALID (result))
659     return (gunichar)-1;
660   else
661     return result;
662 }
663
664 /**
665  * g_utf8_to_ucs4_fast:
666  * @str: a UTF-8 encoded string
667  * @len: the maximum length of @str to use. If < 0, then
668  *       the string is %NULL terminated.
669  * @items_written: location to store the number of characters in the
670  *                 result, or %NULL.
671  *
672  * Convert a string from UTF-8 to a 32-bit fixed width
673  * representation as UCS-4, assuming valid UTF-8 input.
674  * This function is roughly twice as fast as g_utf8_to_ucs4()
675  * but does no error checking on the input.
676  * 
677  * Return value: a pointer to a newly allocated UCS-4 string.
678  *               This value must be freed with g_free()
679  **/
680 gunichar *
681 g_utf8_to_ucs4_fast (const gchar *str,
682                      glong        len,              
683                      glong       *items_written)    
684 {
685   gint j, charlen;
686   gunichar *result;
687   gint n_chars, i;
688   const gchar *p;
689
690   g_return_val_if_fail (str != NULL, NULL);
691
692   p = str;
693   n_chars = 0;
694   if (len < 0)
695     {
696       while (*p)
697         {
698           p = g_utf8_next_char (p);
699           ++n_chars;
700         }
701     }
702   else
703     {
704       while (p < str + len && *p)
705         {
706           p = g_utf8_next_char (p);
707           ++n_chars;
708         }
709     }
710   
711   result = g_new (gunichar, n_chars + 1);
712   
713   p = str;
714   for (i=0; i < n_chars; i++)
715     {
716       gunichar wc = ((unsigned char *)p)[0];
717
718       if (wc < 0x80)
719         {
720           result[i] = wc;
721           p++;
722         }
723       else
724         { 
725           if (wc < 0xe0)
726             {
727               charlen = 2;
728               wc &= 0x1f;
729             }
730           else if (wc < 0xf0)
731             {
732               charlen = 3;
733               wc &= 0x0f;
734             }
735           else if (wc < 0xf8)
736             {
737               charlen = 4;
738               wc &= 0x07;
739             }
740           else if (wc < 0xfc)
741             {
742               charlen = 5;
743               wc &= 0x03;
744             }
745           else
746             {
747               charlen = 6;
748               wc &= 0x01;
749             }
750
751           for (j = 1; j < charlen; j++)
752             {
753               wc <<= 6;
754               wc |= ((unsigned char *)p)[j] & 0x3f;
755             }
756
757           result[i] = wc;
758           p += charlen;
759         }
760     }
761   result[i] = 0;
762
763   if (items_written)
764     *items_written = i;
765
766   return result;
767 }
768
769 /**
770  * g_utf8_to_ucs4:
771  * @str: a UTF-8 encoded string
772  * @len: the maximum length of @str to use. If < 0, then
773  *       the string is %NULL terminated.
774  * @items_read: location to store number of bytes read, or %NULL.
775  *              If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will be
776  *              returned in case @str contains a trailing partial
777  *              character. If an error occurs then the index of the
778  *              invalid input is stored here.
779  * @items_written: location to store number of characters written or %NULL.
780  *                 The value here stored does not include the trailing 0
781  *                 character. 
782  * @error: location to store the error occuring, or %NULL to ignore
783  *         errors. Any of the errors in #GConvertError other than
784  *         %G_CONVERT_ERROR_NO_CONVERSION may occur.
785  *
786  * Convert a string from UTF-8 to a 32-bit fixed width
787  * representation as UCS-4. A trailing 0 will be added to the
788  * string after the converted text.
789  * 
790  * Return value: a pointer to a newly allocated UCS-4 string.
791  *               This value must be freed with g_free(). If an
792  *               error occurs, %NULL will be returned and
793  *               @error set.
794  **/
795 gunichar *
796 g_utf8_to_ucs4 (const gchar *str,
797                 glong        len,             
798                 glong       *items_read,      
799                 glong       *items_written,   
800                 GError     **error)
801 {
802   gunichar *result = NULL;
803   gint n_chars, i;
804   const gchar *in;
805   
806   in = str;
807   n_chars = 0;
808   while ((len < 0 || str + len - in > 0) && *in)
809     {
810       gunichar wc = g_utf8_get_char_extended (in, str + len - in);
811       if (wc & 0x80000000)
812         {
813           if (wc == (gunichar)-2)
814             {
815               if (items_read)
816                 break;
817               else
818                 g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
819                              _("Partial character sequence at end of input"));
820             }
821           else
822             g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
823                          _("Invalid byte sequence in conversion input"));
824
825           goto err_out;
826         }
827
828       n_chars++;
829
830       in = g_utf8_next_char (in);
831     }
832
833   result = g_new (gunichar, n_chars + 1);
834   
835   in = str;
836   for (i=0; i < n_chars; i++)
837     {
838       result[i] = g_utf8_get_char (in);
839       in = g_utf8_next_char (in);
840     }
841   result[i] = 0;
842
843   if (items_written)
844     *items_written = n_chars;
845
846  err_out:
847   if (items_read)
848     *items_read = in - str;
849
850   return result;
851 }
852
853 /**
854  * g_ucs4_to_utf8:
855  * @str: a UCS-4 encoded string
856  * @len: the maximum length of @str to use. If < 0, then
857  *       the string is %NULL terminated.
858  * @items_read: location to store number of characters read read, or %NULL.
859  * @items_written: location to store number of bytes written or %NULL.
860  *                 The value here stored does not include the trailing 0
861  *                 byte. 
862  * @error: location to store the error occuring, or %NULL to ignore
863  *         errors. Any of the errors in #GConvertError other than
864  *         %G_CONVERT_ERROR_NO_CONVERSION may occur.
865  *
866  * Convert a string from a 32-bit fixed width representation as UCS-4.
867  * to UTF-8. The result will be terminated with a 0 byte.
868  * 
869  * Return value: a pointer to a newly allocated UTF-8 string.
870  *               This value must be freed with g_free(). If an
871  *               error occurs, %NULL will be returned and
872  *               @error set.
873  **/
874 gchar *
875 g_ucs4_to_utf8 (const gunichar *str,
876                 glong           len,              
877                 glong          *items_read,       
878                 glong          *items_written,    
879                 GError        **error)
880 {
881   gint result_length;
882   gchar *result = NULL;
883   gchar *p;
884   gint i;
885
886   result_length = 0;
887   for (i = 0; len < 0 || i < len ; i++)
888     {
889       if (!str[i])
890         break;
891
892       if (str[i] >= 0x80000000)
893         {
894           if (items_read)
895             *items_read = i;
896           
897           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
898                        _("Character out of range for UTF-8"));
899           goto err_out;
900         }
901       
902       result_length += UTF8_LENGTH (str[i]);
903     }
904
905   result = g_malloc (result_length + 1);
906   p = result;
907
908   i = 0;
909   while (p < result + result_length)
910     p += g_unichar_to_utf8 (str[i++], p);
911   
912   *p = '\0';
913
914   if (items_written)
915     *items_written = p - result;
916
917  err_out:
918   if (items_read)
919     *items_read = i;
920
921   return result;
922 }
923
924 #define SURROGATE_VALUE(h,l) (((h) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000)
925
926 /**
927  * g_utf16_to_utf8:
928  * @str: a UTF-16 encoded string
929  * @len: the maximum length of @str to use. If < 0, then
930  *       the string is terminated with a 0 character.
931  * @items_read: location to store number of words read, or %NULL.
932  *              If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will be
933  *              returned in case @str contains a trailing partial
934  *              character. If an error occurs then the index of the
935  *              invalid input is stored here.
936  * @items_written: location to store number of bytes written, or %NULL.
937  *                 The value stored here does not include the trailing
938  *                 0 byte.
939  * @error: location to store the error occuring, or %NULL to ignore
940  *         errors. Any of the errors in #GConvertError other than
941  *         %G_CONVERT_ERROR_NO_CONVERSION may occur.
942  *
943  * Convert a string from UTF-16 to UTF-8. The result will be
944  * terminated with a 0 byte.
945  * 
946  * Return value: a pointer to a newly allocated UTF-8 string.
947  *               This value must be freed with g_free(). If an
948  *               error occurs, %NULL will be returned and
949  *               @error set.
950  **/
951 gchar *
952 g_utf16_to_utf8 (const gunichar2  *str,
953                  glong             len,              
954                  glong            *items_read,       
955                  glong            *items_written,    
956                  GError          **error)
957 {
958   /* This function and g_utf16_to_ucs4 are almost exactly identical - The lines that differ
959    * are marked.
960    */
961   const gunichar2 *in;
962   gchar *out;
963   gchar *result = NULL;
964   gint n_bytes;
965   gunichar high_surrogate;
966
967   g_return_val_if_fail (str != 0, NULL);
968
969   n_bytes = 0;
970   in = str;
971   high_surrogate = 0;
972   while ((len < 0 || in - str < len) && *in)
973     {
974       gunichar2 c = *in;
975       gunichar wc;
976
977       if (c >= 0xdc00 && c < 0xe000) /* low surrogate */
978         {
979           if (high_surrogate)
980             {
981               wc = SURROGATE_VALUE (high_surrogate, c);
982               high_surrogate = 0;
983             }
984           else
985             {
986               g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
987                            _("Invalid sequence in conversion input"));
988               goto err_out;
989             }
990         }
991       else
992         {
993           if (high_surrogate)
994             {
995               g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
996                            _("Invalid sequence in conversion input"));
997               goto err_out;
998             }
999
1000           if (c >= 0xd800 && c < 0xdc00) /* high surrogate */
1001             {
1002               high_surrogate = c;
1003               goto next1;
1004             }
1005           else
1006             wc = c;
1007         }
1008
1009       /********** DIFFERENT for UTF8/UCS4 **********/
1010       n_bytes += UTF8_LENGTH (wc);
1011
1012     next1:
1013       in++;
1014     }
1015
1016   if (high_surrogate && !items_read)
1017     {
1018       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
1019                    _("Partial character sequence at end of input"));
1020       goto err_out;
1021     }
1022   
1023   /* At this point, everything is valid, and we just need to convert
1024    */
1025   /********** DIFFERENT for UTF8/UCS4 **********/
1026   result = g_malloc (n_bytes + 1);
1027   
1028   high_surrogate = 0;
1029   out = result;
1030   in = str;
1031   while (out < result + n_bytes)
1032     {
1033       gunichar2 c = *in;
1034       gunichar wc;
1035
1036       if (c >= 0xdc00 && c < 0xe000) /* low surrogate */
1037         {
1038           wc = SURROGATE_VALUE (high_surrogate, c);
1039           high_surrogate = 0;
1040         }
1041       else if (c >= 0xd800 && c < 0xdc00) /* high surrogate */
1042         {
1043           high_surrogate = c;
1044           goto next2;
1045         }
1046       else
1047         wc = c;
1048
1049       /********** DIFFERENT for UTF8/UCS4 **********/
1050       out += g_unichar_to_utf8 (wc, out);
1051
1052     next2:
1053       in++;
1054     }
1055   
1056   /********** DIFFERENT for UTF8/UCS4 **********/
1057   *out = '\0';
1058
1059   if (items_written)
1060     /********** DIFFERENT for UTF8/UCS4 **********/
1061     *items_written = out - result;
1062
1063  err_out:
1064   if (items_read)
1065     *items_read = in - str;
1066
1067   return result;
1068 }
1069
1070 /**
1071  * g_utf16_to_ucs4:
1072  * @str: a UTF-16 encoded string
1073  * @len: the maximum length of @str to use. If < 0, then
1074  *       the string is terminated with a 0 character.
1075  * @items_read: location to store number of words read, or %NULL.
1076  *              If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will be
1077  *              returned in case @str contains a trailing partial
1078  *              character. If an error occurs then the index of the
1079  *              invalid input is stored here.
1080  * @items_written: location to store number of characters written, or %NULL.
1081  *                 The value stored here does not include the trailing
1082  *                 0 character.
1083  * @error: location to store the error occuring, or %NULL to ignore
1084  *         errors. Any of the errors in #GConvertError other than
1085  *         %G_CONVERT_ERROR_NO_CONVERSION may occur.
1086  *
1087  * Convert a string from UTF-16 to UCS-4. The result will be
1088  * terminated with a 0 character.
1089  * 
1090  * Return value: a pointer to a newly allocated UCS-4 string.
1091  *               This value must be freed with g_free(). If an
1092  *               error occurs, %NULL will be returned and
1093  *               @error set.
1094  **/
1095 gunichar *
1096 g_utf16_to_ucs4 (const gunichar2  *str,
1097                  glong             len,              
1098                  glong            *items_read,       
1099                  glong            *items_written,    
1100                  GError          **error)
1101 {
1102   const gunichar2 *in;
1103   gchar *out;
1104   gchar *result = NULL;
1105   gint n_bytes;
1106   gunichar high_surrogate;
1107
1108   g_return_val_if_fail (str != 0, NULL);
1109
1110   n_bytes = 0;
1111   in = str;
1112   high_surrogate = 0;
1113   while ((len < 0 || in - str < len) && *in)
1114     {
1115       gunichar2 c = *in;
1116       gunichar wc;
1117
1118       if (c >= 0xdc00 && c < 0xe000) /* low surrogate */
1119         {
1120           if (high_surrogate)
1121             {
1122               wc = SURROGATE_VALUE (high_surrogate, c);
1123               high_surrogate = 0;
1124             }
1125           else
1126             {
1127               g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1128                            _("Invalid sequence in conversion input"));
1129               goto err_out;
1130             }
1131         }
1132       else
1133         {
1134           if (high_surrogate)
1135             {
1136               g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1137                            _("Invalid sequence in conversion input"));
1138               goto err_out;
1139             }
1140
1141           if (c >= 0xd800 && c < 0xdc00) /* high surrogate */
1142             {
1143               high_surrogate = c;
1144               goto next1;
1145             }
1146           else
1147             wc = c;
1148         }
1149
1150       /********** DIFFERENT for UTF8/UCS4 **********/
1151       n_bytes += sizeof (gunichar);
1152
1153     next1:
1154       in++;
1155     }
1156
1157   if (high_surrogate && !items_read)
1158     {
1159       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
1160                    _("Partial character sequence at end of input"));
1161       goto err_out;
1162     }
1163   
1164   /* At this point, everything is valid, and we just need to convert
1165    */
1166   /********** DIFFERENT for UTF8/UCS4 **********/
1167   result = g_malloc (n_bytes + 4);
1168   
1169   high_surrogate = 0;
1170   out = result;
1171   in = str;
1172   while (out < result + n_bytes)
1173     {
1174       gunichar2 c = *in;
1175       gunichar wc;
1176
1177       if (c >= 0xdc00 && c < 0xe000) /* low surrogate */
1178         {
1179           wc = SURROGATE_VALUE (high_surrogate, c);
1180           high_surrogate = 0;
1181         }
1182       else if (c >= 0xd800 && c < 0xdc00) /* high surrogate */
1183         {
1184           high_surrogate = c;
1185           goto next2;
1186         }
1187       else
1188         wc = c;
1189
1190       /********** DIFFERENT for UTF8/UCS4 **********/
1191       *(gunichar *)out = wc;
1192       out += sizeof (gunichar);
1193
1194     next2:
1195       in++;
1196     }
1197
1198   /********** DIFFERENT for UTF8/UCS4 **********/
1199   *(gunichar *)out = 0;
1200
1201   if (items_written)
1202     /********** DIFFERENT for UTF8/UCS4 **********/
1203     *items_written = (out - result) / sizeof (gunichar);
1204
1205  err_out:
1206   if (items_read)
1207     *items_read = in - str;
1208
1209   return (gunichar *)result;
1210 }
1211
1212 /**
1213  * g_utf8_to_utf16:
1214  * @str: a UTF-8 encoded string
1215  * @len: the maximum length of @str to use. If < 0, then
1216  *       the string is %NULL terminated.
1217  
1218  * @items_read: location to store number of bytes read, or %NULL.
1219  *              If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will be
1220  *              returned in case @str contains a trailing partial
1221  *              character. If an error occurs then the index of the
1222  *              invalid input is stored here.
1223  * @items_written: location to store number of words written, or %NULL.
1224  *                 The value stored here does not include the trailing
1225  *                 0 word.
1226  * @error: location to store the error occuring, or %NULL to ignore
1227  *         errors. Any of the errors in #GConvertError other than
1228  *         %G_CONVERT_ERROR_NO_CONVERSION may occur.
1229  *
1230  * Convert a string from UTF-8 to UTF-16. A 0 word will be
1231  * added to the result after the converted text.
1232  * 
1233  * Return value: a pointer to a newly allocated UTF-16 string.
1234  *               This value must be freed with g_free(). If an
1235  *               error occurs, %NULL will be returned and
1236  *               @error set.
1237  **/
1238 gunichar2 *
1239 g_utf8_to_utf16 (const gchar *str,
1240                  glong        len,              
1241                  glong       *items_read,       
1242                  glong       *items_written,    
1243                  GError     **error)
1244 {
1245   gunichar2 *result = NULL;
1246   gint n16;
1247   const gchar *in;
1248   gint i;
1249
1250   g_return_val_if_fail (str != NULL, NULL);
1251
1252   in = str;
1253   n16 = 0;
1254   while ((len < 0 || str + len - in > 0) && *in)
1255     {
1256       gunichar wc = g_utf8_get_char_extended (in, str + len - in);
1257       if (wc & 0x80000000)
1258         {
1259           if (wc == (gunichar)-2)
1260             {
1261               if (items_read)
1262                 break;
1263               else
1264                 g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
1265                              _("Partial character sequence at end of input"));
1266             }
1267           else
1268             g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1269                          _("Invalid byte sequence in conversion input"));
1270
1271           goto err_out;
1272         }
1273
1274       if (wc < 0xd800)
1275         n16 += 1;
1276       else if (wc < 0xe000)
1277         {
1278           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1279                        _("Invalid sequence in conversion input"));
1280
1281           goto err_out;
1282         }
1283       else if (wc < 0x10000)
1284         n16 += 1;
1285       else if (wc < 0x110000)
1286         n16 += 2;
1287       else
1288         {
1289           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1290                        _("Character out of range for UTF-16"));
1291
1292           goto err_out;
1293         }
1294       
1295       in = g_utf8_next_char (in);
1296     }
1297
1298   result = g_new (gunichar2, n16 + 1);
1299   
1300   in = str;
1301   for (i = 0; i < n16;)
1302     {
1303       gunichar wc = g_utf8_get_char (in);
1304
1305       if (wc < 0x10000)
1306         {
1307           result[i++] = wc;
1308         }
1309       else
1310         {
1311           result[i++] = (wc - 0x10000) / 0x400 + 0xd800;
1312           result[i++] = (wc - 0x10000) % 0x400 + 0xdc00;
1313         }
1314       
1315       in = g_utf8_next_char (in);
1316     }
1317
1318   result[i] = 0;
1319
1320   if (items_written)
1321     *items_written = n16;
1322
1323  err_out:
1324   if (items_read)
1325     *items_read = in - str;
1326   
1327   return result;
1328 }
1329
1330 /**
1331  * g_ucs4_to_utf16:
1332  * @str: a UCS-4 encoded string
1333  * @len: the maximum length of @str to use. If < 0, then
1334  *       the string is terminated with a zero character.
1335  * @items_read: location to store number of bytes read, or %NULL.
1336  *              If an error occurs then the index of the invalid input
1337  *              is stored here.
1338  * @items_written: location to store number of words written, or %NULL.
1339  *                 The value stored here does not include the trailing
1340  *                 0 word.
1341  * @error: location to store the error occuring, or %NULL to ignore
1342  *         errors. Any of the errors in #GConvertError other than
1343  *         %G_CONVERT_ERROR_NO_CONVERSION may occur.
1344  *
1345  * Convert a string from UCS-4 to UTF-16. A 0 word will be
1346  * added to the result after the converted text.
1347  * 
1348  * Return value: a pointer to a newly allocated UTF-16 string.
1349  *               This value must be freed with g_free(). If an
1350  *               error occurs, %NULL will be returned and
1351  *               @error set.
1352  **/
1353 gunichar2 *
1354 g_ucs4_to_utf16 (const gunichar  *str,
1355                  glong            len,              
1356                  glong           *items_read,       
1357                  glong           *items_written,    
1358                  GError         **error)
1359 {
1360   gunichar2 *result = NULL;
1361   gint n16;
1362   gint i, j;
1363
1364   n16 = 0;
1365   i = 0;
1366   while ((len < 0 || i < len) && str[i])
1367     {
1368       gunichar wc = str[i];
1369
1370       if (wc < 0xd800)
1371         n16 += 1;
1372       else if (wc < 0xe000)
1373         {
1374           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1375                        _("Invalid sequence in conversion input"));
1376
1377           goto err_out;
1378         }
1379       else if (wc < 0x10000)
1380         n16 += 1;
1381       else if (wc < 0x110000)
1382         n16 += 2;
1383       else
1384         {
1385           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1386                        _("Character out of range for UTF-16"));
1387
1388           goto err_out;
1389         }
1390
1391       i++;
1392     }
1393   
1394   result = g_new (gunichar2, n16 + 1);
1395   
1396   for (i = 0, j = 0; j < n16; i++)
1397     {
1398       gunichar wc = str[i];
1399
1400       if (wc < 0x10000)
1401         {
1402           result[j++] = wc;
1403         }
1404       else
1405         {
1406           result[j++] = (wc - 0x10000) / 0x400 + 0xd800;
1407           result[j++] = (wc - 0x10000) % 0x400 + 0xdc00;
1408         }
1409     }
1410   result[j] = 0;
1411
1412   if (items_written)
1413     *items_written = n16;
1414   
1415  err_out:
1416   if (items_read)
1417     *items_read = i;
1418   
1419   return result;
1420 }
1421
1422 /**
1423  * g_utf8_validate:
1424  * @str: a pointer to character data
1425  * @max_len: max bytes to validate, or -1 to go until nul
1426  * @end: return location for end of valid data
1427  * 
1428  * Validates UTF-8 encoded text. @str is the text to validate;
1429  * if @str is nul-terminated, then @max_len can be -1, otherwise
1430  * @max_len should be the number of bytes to validate.
1431  * If @end is non-%NULL, then the end of the valid range
1432  * will be stored there (i.e. the address of the first invalid byte
1433  * if some bytes were invalid, or the end of the text being validated
1434  * otherwise).
1435  *
1436  * Returns TRUE if all of @str was valid. Many GLib and GTK+
1437  * routines <emphasis>require</emphasis> valid UTF8 as input;
1438  * so data read from a file or the network should be checked
1439  * with g_utf8_validate() before doing anything else with it.
1440  * 
1441  * Return value: TRUE if the text was valid UTF-8.
1442  **/
1443 gboolean
1444 g_utf8_validate (const gchar  *str,
1445                  gssize        max_len,    
1446                  const gchar **end)
1447 {
1448
1449   const gchar *p;
1450
1451   g_return_val_if_fail (str != NULL, FALSE);
1452   
1453   if (end)
1454     *end = str;
1455   
1456   p = str;
1457   
1458   while ((max_len < 0 || (p - str) < max_len) && *p)
1459     {
1460       int i, mask = 0, len;
1461       gunichar result;
1462       unsigned char c = (unsigned char) *p;
1463       
1464       UTF8_COMPUTE (c, mask, len);
1465
1466       if (len == -1)
1467         break;
1468
1469       /* check that the expected number of bytes exists in str */
1470       if (max_len >= 0 &&
1471           ((max_len - (p - str)) < len))
1472         break;
1473         
1474       UTF8_GET (result, p, i, mask, len);
1475
1476       if (UTF8_LENGTH (result) != len) /* Check for overlong UTF-8 */
1477         break;
1478
1479       if (result == (gunichar)-1)
1480         break;
1481
1482       if (!UNICODE_VALID (result))
1483         break;
1484       
1485       p += len;
1486     }
1487
1488   if (end)
1489     *end = p;
1490
1491   /* See that we covered the entire length if a length was
1492    * passed in, or that we ended on a nul if not
1493    */
1494   if (max_len >= 0 &&
1495       p != (str + max_len))
1496     return FALSE;
1497   else if (max_len < 0 &&
1498            *p != '\0')
1499     return FALSE;
1500   else
1501     return TRUE;
1502 }
1503
1504 /**
1505  * g_unichar_validate:
1506  * @ch: a Unicode character
1507  * 
1508  * Checks whether @ch is a valid Unicode character. Some possible
1509  * integer values of @ch will not be valid. 0 is considered a valid
1510  * character, though it's normally a string terminator.
1511  * 
1512  * Return value: %TRUE if @ch is a valid Unicode character
1513  **/
1514 gboolean
1515 g_unichar_validate (gunichar ch)
1516 {
1517   return UNICODE_VALID (ch);
1518 }