1 /* nfkc.c Unicode normalization utilities.
2 * Copyright (C) 2002, 2003 Simon Josefsson
4 * This file is part of GNU Libidn.
6 * GNU Libidn 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.1 of the License, or (at your option) any later version.
11 * GNU Libidn 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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
27 #include "stringprep.h"
29 /* This file contains functions from GLIB, including gutf8.c and
30 * gunidecomp.c, all licensed under LGPL and copyright hold by:
32 * Copyright (C) 1999, 2000 Tom Tromey
33 * Copyright 2000 Red Hat, Inc.
36 /* Hacks to make syncing with GLIB code easier. */
39 #define guchar unsigned char
42 #define guint unsigned int
43 #define gushort unsigned short
44 #define gint16 int16_t
45 #define guint16 uint16_t
46 #define gunichar uint32_t
48 #define gssize ssize_t
49 #define g_malloc malloc
52 #define g_set_error(a,b,c,d) ((void) 0)
53 #define g_new(struct_type, n_structs) \
54 ((struct_type *) g_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
55 # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
56 # define G_STMT_START (void)(
59 # if (defined (sun) || defined (__sun__))
60 # define G_STMT_START if (1)
61 # define G_STMT_END else (void)0
63 # define G_STMT_START do
64 # define G_STMT_END while (0)
67 #define g_return_val_if_fail(expr,val) G_STMT_START{ (void)0; }G_STMT_END
68 #define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
72 /* Code from GLIB gunicode.h starts here. */
77 G_NORMALIZE_NFD
= G_NORMALIZE_DEFAULT
,
78 G_NORMALIZE_DEFAULT_COMPOSE
,
79 G_NORMALIZE_NFC
= G_NORMALIZE_DEFAULT_COMPOSE
,
81 G_NORMALIZE_NFKD
= G_NORMALIZE_ALL
,
82 G_NORMALIZE_ALL_COMPOSE
,
83 G_NORMALIZE_NFKC
= G_NORMALIZE_ALL_COMPOSE
87 /* Code from GLIB gutf8.c starts here. */
89 #define UTF8_COMPUTE(Char, Mask, Len) \
95 else if ((Char & 0xe0) == 0xc0) \
100 else if ((Char & 0xf0) == 0xe0) \
105 else if ((Char & 0xf8) == 0xf0) \
110 else if ((Char & 0xfc) == 0xf8) \
115 else if ((Char & 0xfe) == 0xfc) \
123 #define UTF8_LENGTH(Char) \
124 ((Char) < 0x80 ? 1 : \
125 ((Char) < 0x800 ? 2 : \
126 ((Char) < 0x10000 ? 3 : \
127 ((Char) < 0x200000 ? 4 : \
128 ((Char) < 0x4000000 ? 5 : 6)))))
131 #define UTF8_GET(Result, Chars, Count, Mask, Len) \
132 (Result) = (Chars)[0] & (Mask); \
133 for ((Count) = 1; (Count) < (Len); ++(Count)) \
135 if (((Chars)[(Count)] & 0xc0) != 0x80) \
141 (Result) |= ((Chars)[(Count)] & 0x3f); \
144 #define UNICODE_VALID(Char) \
145 ((Char) < 0x110000 && \
146 (((Char) & 0xFFFFF800) != 0xD800) && \
147 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
148 ((Char) & 0xFFFE) != 0xFFFE)
151 static const gchar utf8_skip_data
[256] = {
152 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,
154 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,
156 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,
158 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,
160 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,
162 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,
164 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,
166 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,
170 const gchar
*const g_utf8_skip
= utf8_skip_data
;
172 #define g_utf8_next_char(p) (char *)((p) + g_utf8_skip[*(guchar *)(p)])
176 * @p: pointer to the start of a UTF-8 encoded string.
177 * @max: the maximum number of bytes to examine. If @max
178 * is less than 0, then the string is assumed to be
179 * nul-terminated. If @max is 0, @p will not be examined and
182 * Returns the length of the string in characters.
184 * Return value: the length of the string in characters
187 g_utf8_strlen (const gchar
* p
, gssize max
)
190 const gchar
*start
= p
;
191 g_return_val_if_fail (p
!= NULL
|| max
== 0, 0);
197 p
= g_utf8_next_char (p
);
206 p
= g_utf8_next_char (p
);
208 while (p
- start
< max
&& *p
)
211 p
= g_utf8_next_char (p
);
214 /* only do the last len increment if we got a complete
215 * char (don't count partial chars)
217 if (p
- start
== max
)
226 * @p: a pointer to Unicode character encoded as UTF-8
228 * Converts a sequence of bytes encoded as UTF-8 to a Unicode character.
229 * If @p does not point to a valid UTF-8 encoded character, results are
230 * undefined. If you are not sure that the bytes are complete
231 * valid Unicode characters, you should use g_utf8_get_char_validated()
234 * Return value: the resulting character
237 g_utf8_get_char (const gchar
* p
)
239 int i
, mask
= 0, len
;
241 unsigned char c
= (unsigned char) *p
;
243 UTF8_COMPUTE (c
, mask
, len
);
245 return (gunichar
) - 1;
246 UTF8_GET (result
, p
, i
, mask
, len
);
253 * @c: a ISO10646 character code
254 * @outbuf: output buffer, must have at least 6 bytes of space.
255 * If %NULL, the length will be computed and returned
256 * and nothing will be written to @outbuf.
258 * Converts a single character to UTF-8.
260 * Return value: number of bytes written
263 g_unichar_to_utf8 (gunichar c
, gchar
* outbuf
)
279 else if (c
< 0x10000)
284 else if (c
< 0x200000)
289 else if (c
< 0x4000000)
302 for (i
= len
- 1; i
> 0; --i
)
304 outbuf
[i
] = (c
& 0x3f) | 0x80;
307 outbuf
[0] = c
| first
;
314 * g_utf8_to_ucs4_fast:
315 * @str: a UTF-8 encoded string
316 * @len: the maximum length of @str to use. If @len < 0, then
317 * the string is nul-terminated.
318 * @items_written: location to store the number of characters in the
321 * Convert a string from UTF-8 to a 32-bit fixed width
322 * representation as UCS-4, assuming valid UTF-8 input.
323 * This function is roughly twice as fast as g_utf8_to_ucs4()
324 * but does no error checking on the input.
326 * Return value: a pointer to a newly allocated UCS-4 string.
327 * This value must be freed with g_free().
330 g_utf8_to_ucs4_fast (const gchar
* str
, glong len
, glong
* items_written
)
337 g_return_val_if_fail (str
!= NULL
, NULL
);
345 p
= g_utf8_next_char (p
);
351 while (p
< str
+ len
&& *p
)
353 p
= g_utf8_next_char (p
);
358 result
= g_new (gunichar
, n_chars
+ 1);
363 for (i
= 0; i
< n_chars
; i
++)
365 gunichar wc
= ((unsigned char *) p
)[0];
400 for (j
= 1; j
< charlen
; j
++)
403 wc
|= ((unsigned char *) p
)[j
] & 0x3f;
420 * @str: a UCS-4 encoded string
421 * @len: the maximum length of @str to use. If @len < 0, then
422 * the string is terminated with a 0 character.
423 * @items_read: location to store number of characters read read, or %NULL.
424 * @items_written: location to store number of bytes written or %NULL.
425 * The value here stored does not include the trailing 0
427 * @error: location to store the error occuring, or %NULL to ignore
428 * errors. Any of the errors in #GConvertError other than
429 * %G_CONVERT_ERROR_NO_CONVERSION may occur.
431 * Convert a string from a 32-bit fixed width representation as UCS-4.
432 * to UTF-8. The result will be terminated with a 0 byte.
434 * Return value: a pointer to a newly allocated UTF-8 string.
435 * This value must be freed with g_free(). If an
436 * error occurs, %NULL will be returned and
440 g_ucs4_to_utf8 (const gunichar
* str
,
442 glong
* items_read
, glong
* items_written
, GError
** error
)
445 gchar
*result
= NULL
;
450 for (i
= 0; len
< 0 || i
< len
; i
++)
455 if (str
[i
] >= 0x80000000)
460 g_set_error (error
, G_CONVERT_ERROR
,
461 G_CONVERT_ERROR_ILLEGAL_SEQUENCE
,
462 _("Character out of range for UTF-8"));
466 result_length
+= UTF8_LENGTH (str
[i
]);
469 result
= g_malloc (result_length
+ 1);
475 while (p
< result
+ result_length
)
476 p
+= g_unichar_to_utf8 (str
[i
++], p
);
481 *items_written
= p
- result
;
490 /* Code from GLIB gunidecomp.c starts here. */
492 #include "gunidecomp.h"
493 #include "gunicomp.h"
495 #define CC_PART1(Page, Char) \
496 ((combining_class_table_part1[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
497 ? (combining_class_table_part1[Page] - G_UNICODE_MAX_TABLE_INDEX) \
498 : (cclass_data[combining_class_table_part1[Page]][Char]))
500 #define CC_PART2(Page, Char) \
501 ((combining_class_table_part2[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
502 ? (combining_class_table_part2[Page] - G_UNICODE_MAX_TABLE_INDEX) \
503 : (cclass_data[combining_class_table_part2[Page]][Char]))
505 #define COMBINING_CLASS(Char) \
506 (((Char) <= G_UNICODE_LAST_CHAR_PART1) \
507 ? CC_PART1 ((Char) >> 8, (Char) & 0xff) \
508 : (((Char) >= 0xe0000 && (Char) <= G_UNICODE_LAST_CHAR) \
509 ? CC_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \
512 /* constants for hangul syllable [de]composition */
520 #define NCount (VCount * TCount)
521 #define SCount (LCount * NCount)
524 * g_unicode_canonical_ordering:
525 * @string: a UCS-4 encoded string.
526 * @len: the maximum length of @string to use.
528 * Computes the canonical ordering of a string in-place.
529 * This rearranges decomposed characters in the string
530 * according to their combining classes. See the Unicode
531 * manual for more information.
534 g_unicode_canonical_ordering (gunichar
* string
, gsize len
)
543 last
= COMBINING_CLASS (string
[0]);
544 for (i
= 0; i
< len
- 1; ++i
)
546 int next
= COMBINING_CLASS (string
[i
+ 1]);
547 if (next
!= 0 && last
> next
)
550 /* Percolate item leftward through string. */
551 for (j
= i
+ 1; j
> 0; --j
)
554 if (COMBINING_CLASS (string
[j
- 1]) <= next
)
557 string
[j
] = string
[j
- 1];
561 /* We're re-entering the loop looking at the old
570 /* http://www.unicode.org/unicode/reports/tr15/#Hangul
571 * r should be null or have sufficient space. Calling with r == NULL will
572 * only calculate the result_len; however, a buffer with space for three
573 * characters will always be big enough. */
575 decompose_hangul (gunichar s
, gunichar
* r
, gsize
* result_len
)
577 gint SIndex
= s
- SBase
;
579 /* not a hangul syllable */
580 if (SIndex
< 0 || SIndex
>= SCount
)
588 gunichar L
= LBase
+ SIndex
/ NCount
;
589 gunichar V
= VBase
+ (SIndex
% NCount
) / TCount
;
590 gunichar T
= TBase
+ SIndex
% TCount
;
609 /* returns a pointer to a null-terminated UTF-8 string */
611 find_decomposition (gunichar ch
, gboolean compat
)
614 int end
= G_N_ELEMENTS (decomp_table
);
616 if (ch
>= decomp_table
[start
].ch
&& ch
<= decomp_table
[end
- 1].ch
)
620 int half
= (start
+ end
) / 2;
621 if (ch
== decomp_table
[half
].ch
)
627 offset
= decomp_table
[half
].compat_offset
;
628 if (offset
== G_UNICODE_NOT_PRESENT_OFFSET
)
629 offset
= decomp_table
[half
].canon_offset
;
633 offset
= decomp_table
[half
].canon_offset
;
634 if (offset
== G_UNICODE_NOT_PRESENT_OFFSET
)
638 return &(decomp_expansion_string
[offset
]);
640 else if (half
== start
)
642 else if (ch
> decomp_table
[half
].ch
)
652 /* L,V => LV and LV,T => LVT */
654 combine_hangul (gunichar a
, gunichar b
, gunichar
* result
)
656 gint LIndex
= a
- LBase
;
657 gint SIndex
= a
- SBase
;
659 gint VIndex
= b
- VBase
;
660 gint TIndex
= b
- TBase
;
662 if (0 <= LIndex
&& LIndex
< LCount
&& 0 <= VIndex
&& VIndex
< VCount
)
664 *result
= SBase
+ (LIndex
* VCount
+ VIndex
) * TCount
;
667 else if (0 <= SIndex
&& SIndex
< SCount
&& (SIndex
% TCount
) == 0
668 && 0 <= TIndex
&& TIndex
<= TCount
)
670 *result
= a
+ TIndex
;
677 #define CI(Page, Char) \
678 ((compose_table[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
679 ? (compose_table[Page] - G_UNICODE_MAX_TABLE_INDEX) \
680 : (compose_data[compose_table[Page]][Char]))
682 #define COMPOSE_INDEX(Char) \
683 ((((Char) >> 8) > (COMPOSE_TABLE_LAST)) ? 0 : CI((Char) >> 8, (Char) & 0xff))
686 combine (gunichar a
, gunichar b
, gunichar
* result
)
688 gushort index_a
, index_b
;
690 if (combine_hangul (a
, b
, result
))
693 index_a
= COMPOSE_INDEX (a
);
695 if (index_a
>= COMPOSE_FIRST_SINGLE_START
&& index_a
< COMPOSE_SECOND_START
)
697 if (b
== compose_first_single
[index_a
- COMPOSE_FIRST_SINGLE_START
][0])
700 compose_first_single
[index_a
- COMPOSE_FIRST_SINGLE_START
][1];
707 index_b
= COMPOSE_INDEX (b
);
709 if (index_b
>= COMPOSE_SECOND_SINGLE_START
)
712 compose_second_single
[index_b
- COMPOSE_SECOND_SINGLE_START
][0])
715 compose_second_single
[index_b
- COMPOSE_SECOND_SINGLE_START
][1];
722 if (index_a
>= COMPOSE_FIRST_START
&& index_a
< COMPOSE_FIRST_SINGLE_START
723 && index_b
>= COMPOSE_SECOND_START
724 && index_b
< COMPOSE_SECOND_SINGLE_START
)
727 compose_array
[index_a
- COMPOSE_FIRST_START
][index_b
-
728 COMPOSE_SECOND_START
];
741 _g_utf8_normalize_wc (const gchar
* str
, gssize max_len
, GNormalizeMode mode
)
747 gboolean do_compat
= (mode
== G_NORMALIZE_NFKC
|| mode
== G_NORMALIZE_NFKD
);
748 gboolean do_compose
= (mode
== G_NORMALIZE_NFC
|| mode
== G_NORMALIZE_NFKC
);
752 while ((max_len
< 0 || p
< str
+ max_len
) && *p
)
755 gunichar wc
= g_utf8_get_char (p
);
757 if (wc
>= 0xac00 && wc
<= 0xd7af)
760 decompose_hangul (wc
, NULL
, &result_len
);
765 decomp
= find_decomposition (wc
, do_compat
);
768 n_wc
+= g_utf8_strlen (decomp
, -1);
773 p
= g_utf8_next_char (p
);
776 wc_buffer
= g_new (gunichar
, n_wc
+ 1);
783 while ((max_len
< 0 || p
< str
+ max_len
) && *p
)
785 gunichar wc
= g_utf8_get_char (p
);
788 gsize old_n_wc
= n_wc
;
790 if (wc
>= 0xac00 && wc
<= 0xd7af)
793 decompose_hangul (wc
, wc_buffer
+ n_wc
, &result_len
);
798 decomp
= find_decomposition (wc
, do_compat
);
803 for (pd
= decomp
; *pd
!= '\0'; pd
= g_utf8_next_char (pd
))
804 wc_buffer
[n_wc
++] = g_utf8_get_char (pd
);
807 wc_buffer
[n_wc
++] = wc
;
812 cc
= COMBINING_CLASS (wc_buffer
[old_n_wc
]);
816 g_unicode_canonical_ordering (wc_buffer
+ last_start
,
818 last_start
= old_n_wc
;
822 p
= g_utf8_next_char (p
);
827 g_unicode_canonical_ordering (wc_buffer
+ last_start
,
834 /* All decomposed and reordered */
836 if (do_compose
&& n_wc
> 0)
842 for (i
= 0; i
< n_wc
; i
++)
844 int cc
= COMBINING_CLASS (wc_buffer
[i
]);
847 (last_cc
== 0 || last_cc
!= cc
) &&
848 combine (wc_buffer
[last_start
], wc_buffer
[i
],
849 &wc_buffer
[last_start
]))
851 for (j
= i
+ 1; j
< n_wc
; j
++)
852 wc_buffer
[j
- 1] = wc_buffer
[j
];
859 last_cc
= COMBINING_CLASS (wc_buffer
[i
- 1]);
878 * @str: a UTF-8 encoded string.
879 * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
880 * @mode: the type of normalization to perform.
882 * Converts a string into canonical form, standardizing
883 * such issues as whether a character with an accent
884 * is represented as a base character and combining
885 * accent or as a single precomposed character. You
886 * should generally call g_utf8_normalize() before
887 * comparing two Unicode strings.
889 * The normalization mode %G_NORMALIZE_DEFAULT only
890 * standardizes differences that do not affect the
891 * text content, such as the above-mentioned accent
892 * representation. %G_NORMALIZE_ALL also standardizes
893 * the "compatibility" characters in Unicode, such
894 * as SUPERSCRIPT THREE to the standard forms
895 * (in this case DIGIT THREE). Formatting information
896 * may be lost but for most text operations such
897 * characters should be considered the same.
898 * For example, g_utf8_collate() normalizes
899 * with %G_NORMALIZE_ALL as its first step.
901 * %G_NORMALIZE_DEFAULT_COMPOSE and %G_NORMALIZE_ALL_COMPOSE
902 * are like %G_NORMALIZE_DEFAULT and %G_NORMALIZE_ALL,
903 * but returned a result with composed forms rather
904 * than a maximally decomposed form. This is often
905 * useful if you intend to convert the string to
906 * a legacy encoding or pass it to a system with
907 * less capable Unicode handling.
909 * Return value: a newly allocated string, that is the
910 * normalized form of @str.
913 g_utf8_normalize (const gchar
* str
, gssize len
, GNormalizeMode mode
)
915 gunichar
*result_wc
= _g_utf8_normalize_wc (str
, len
, mode
);
918 result
= g_ucs4_to_utf8 (result_wc
, -1, NULL
, NULL
, NULL
);
924 /* Public Libidn API starts here. */
927 * stringprep_utf8_to_unichar:
928 * @p: a pointer to Unicode character encoded as UTF-8
930 * Converts a sequence of bytes encoded as UTF-8 to a Unicode character.
931 * If @p does not point to a valid UTF-8 encoded character, results are
934 * Return value: the resulting character.
937 stringprep_utf8_to_unichar (const char *p
)
939 return g_utf8_get_char (p
);
943 * stringprep_unichar_to_utf8:
944 * @c: a ISO10646 character code
945 * @outbuf: output buffer, must have at least 6 bytes of space.
946 * If %NULL, the length will be computed and returned
947 * and nothing will be written to @outbuf.
949 * Converts a single character to UTF-8.
951 * Return value: number of bytes written.
954 stringprep_unichar_to_utf8 (uint32_t c
, char *outbuf
)
956 return g_unichar_to_utf8 (c
, outbuf
);
960 * stringprep_utf8_to_ucs4:
961 * @str: a UTF-8 encoded string
962 * @len: the maximum length of @str to use. If @len < 0, then
963 * the string is nul-terminated.
964 * @items_written: location to store the number of characters in the
967 * Convert a string from UTF-8 to a 32-bit fixed width
968 * representation as UCS-4, assuming valid UTF-8 input.
969 * This function does no error checking on the input.
971 * Return value: a pointer to a newly allocated UCS-4 string.
972 * This value must be freed with free().
975 stringprep_utf8_to_ucs4 (const char *str
, ssize_t len
, size_t * items_written
)
977 return g_utf8_to_ucs4_fast (str
, (glong
) len
, (glong
*) items_written
);
981 * stringprep_ucs4_to_utf8:
982 * @str: a UCS-4 encoded string
983 * @len: the maximum length of @str to use. If @len < 0, then
984 * the string is terminated with a 0 character.
985 * @items_read: location to store number of characters read read, or %NULL.
986 * @items_written: location to store number of bytes written or %NULL.
987 * The value here stored does not include the trailing 0
990 * Convert a string from a 32-bit fixed width representation as UCS-4.
991 * to UTF-8. The result will be terminated with a 0 byte.
993 * Return value: a pointer to a newly allocated UTF-8 string.
994 * This value must be freed with free(). If an
995 * error occurs, %NULL will be returned and
999 stringprep_ucs4_to_utf8 (const uint32_t * str
, ssize_t len
,
1000 size_t * items_read
, size_t * items_written
)
1002 return g_ucs4_to_utf8 (str
, len
, (glong
*) items_read
,
1003 (glong
*) items_written
, NULL
);
1007 * stringprep_utf8_nfkc_normalize:
1008 * @str: a UTF-8 encoded string.
1009 * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
1011 * Converts a string into canonical form, standardizing
1012 * such issues as whether a character with an accent
1013 * is represented as a base character and combining
1014 * accent or as a single precomposed character.
1016 * The normalization mode is NFKC (ALL COMPOSE). It standardizes
1017 * differences that do not affect the text content, such as the
1018 * above-mentioned accent representation. It standardizes the
1019 * "compatibility" characters in Unicode, such as SUPERSCRIPT THREE to
1020 * the standard forms (in this case DIGIT THREE). Formatting
1021 * information may be lost but for most text operations such
1022 * characters should be considered the same. It returns a result with
1023 * composed forms rather than a maximally decomposed form.
1025 * Return value: a newly allocated string, that is the
1026 * NFKC normalized form of @str.
1029 stringprep_utf8_nfkc_normalize (const char *str
, ssize_t len
)
1031 return g_utf8_normalize (str
, len
, G_NORMALIZE_NFKC
);
1035 * stringprep_ucs4_nfkc_normalize:
1036 * @str: a Unicode string.
1037 * @len: length of @str array, or -1 if @str is nul-terminated.
1039 * Converts UCS4 string into UTF-8 and runs
1040 * stringprep_utf8_nfkc_normalize().
1042 * Return value: a newly allocated Unicode string, that is the NFKC
1043 * normalized form of @str.
1046 stringprep_ucs4_nfkc_normalize (uint32_t * str
, ssize_t len
)
1049 uint32_t *result_wc
;
1051 p
= stringprep_ucs4_to_utf8 (str
, len
, 0, 0);
1052 result_wc
= _g_utf8_normalize_wc (p
, -1, G_NORMALIZE_NFKC
);