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