00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include "config.h"
00024 #endif
00025
00026 #include <stdlib.h>
00027 #include <string.h>
00028
00029 #include "stringprep.h"
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #define gboolean int
00040 #define gchar char
00041 #define guchar unsigned char
00042 #define glong long
00043 #define gint int
00044 #define guint unsigned int
00045 #define gushort unsigned short
00046 #define gint16 int16_t
00047 #define guint16 uint16_t
00048 #define gunichar uint32_t
00049 #define gsize size_t
00050 #define gssize ssize_t
00051 #define g_malloc malloc
00052 #define g_free free
00053 #define g_new(struct_type, n_structs) \
00054 ((struct_type *) g_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
00055 # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
00056 # define G_STMT_START (void)(
00057 # define G_STMT_END )
00058 # else
00059 # if (defined (sun) || defined (__sun__))
00060 # define G_STMT_START if (1)
00061 # define G_STMT_END else (void)0
00062 # else
00063 # define G_STMT_START do
00064 # define G_STMT_END while (0)
00065 # endif
00066 # endif
00067 #define g_return_val_if_fail(expr,val) G_STMT_START{ (void)0; }G_STMT_END
00068 #define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
00069 #define TRUE 1
00070 #define FALSE 0
00071
00072
00073
00074 typedef enum
00075 {
00076 G_NORMALIZE_DEFAULT,
00077 G_NORMALIZE_NFD = G_NORMALIZE_DEFAULT,
00078 G_NORMALIZE_DEFAULT_COMPOSE,
00079 G_NORMALIZE_NFC = G_NORMALIZE_DEFAULT_COMPOSE,
00080 G_NORMALIZE_ALL,
00081 G_NORMALIZE_NFKD = G_NORMALIZE_ALL,
00082 G_NORMALIZE_ALL_COMPOSE,
00083 G_NORMALIZE_NFKC = G_NORMALIZE_ALL_COMPOSE
00084 }
00085 GNormalizeMode;
00086
00087
00088
00089 #define UTF8_COMPUTE(Char, Mask, Len) \
00090 if (Char < 128) \
00091 { \
00092 Len = 1; \
00093 Mask = 0x7f; \
00094 } \
00095 else if ((Char & 0xe0) == 0xc0) \
00096 { \
00097 Len = 2; \
00098 Mask = 0x1f; \
00099 } \
00100 else if ((Char & 0xf0) == 0xe0) \
00101 { \
00102 Len = 3; \
00103 Mask = 0x0f; \
00104 } \
00105 else if ((Char & 0xf8) == 0xf0) \
00106 { \
00107 Len = 4; \
00108 Mask = 0x07; \
00109 } \
00110 else if ((Char & 0xfc) == 0xf8) \
00111 { \
00112 Len = 5; \
00113 Mask = 0x03; \
00114 } \
00115 else if ((Char & 0xfe) == 0xfc) \
00116 { \
00117 Len = 6; \
00118 Mask = 0x01; \
00119 } \
00120 else \
00121 Len = -1;
00122
00123 #define UTF8_LENGTH(Char) \
00124 ((Char) < 0x80 ? 1 : \
00125 ((Char) < 0x800 ? 2 : \
00126 ((Char) < 0x10000 ? 3 : \
00127 ((Char) < 0x200000 ? 4 : \
00128 ((Char) < 0x4000000 ? 5 : 6)))))
00129
00130
00131 #define UTF8_GET(Result, Chars, Count, Mask, Len) \
00132 (Result) = (Chars)[0] & (Mask); \
00133 for ((Count) = 1; (Count) < (Len); ++(Count)) \
00134 { \
00135 if (((Chars)[(Count)] & 0xc0) != 0x80) \
00136 { \
00137 (Result) = -1; \
00138 break; \
00139 } \
00140 (Result) <<= 6; \
00141 (Result) |= ((Chars)[(Count)] & 0x3f); \
00142 }
00143
00144 static const gchar utf8_skip_data[256] = {
00145 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,
00146 1, 1, 1, 1, 1, 1, 1,
00147 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,
00148 1, 1, 1, 1, 1, 1, 1,
00149 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,
00150 1, 1, 1, 1, 1, 1, 1,
00151 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,
00152 1, 1, 1, 1, 1, 1, 1,
00153 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,
00154 1, 1, 1, 1, 1, 1, 1,
00155 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,
00156 1, 1, 1, 1, 1, 1, 1,
00157 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,
00158 2, 2, 2, 2, 2, 2, 2,
00159 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,
00160 5, 5, 5, 6, 6, 1, 1
00161 };
00162
00163 static const gchar *const g_utf8_skip = utf8_skip_data;
00164
00165 #define g_utf8_next_char(p) ((p) + g_utf8_skip[*(const guchar *)(p)])
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 static glong
00180 g_utf8_strlen (const gchar * p, gssize max)
00181 {
00182 glong len = 0;
00183 const gchar *start = p;
00184 g_return_val_if_fail (p != NULL || max == 0, 0);
00185
00186 if (max < 0)
00187 {
00188 while (*p)
00189 {
00190 p = g_utf8_next_char (p);
00191 ++len;
00192 }
00193 }
00194 else
00195 {
00196 if (max == 0 || !*p)
00197 return 0;
00198
00199 p = g_utf8_next_char (p);
00200
00201 while (p - start < max && *p)
00202 {
00203 ++len;
00204 p = g_utf8_next_char (p);
00205 }
00206
00207
00208
00209
00210 if (p - start == max)
00211 ++len;
00212 }
00213
00214 return len;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 static gunichar
00230 g_utf8_get_char (const gchar * p)
00231 {
00232 int i, mask = 0, len;
00233 gunichar result;
00234 unsigned char c = (unsigned char) *p;
00235
00236 UTF8_COMPUTE (c, mask, len);
00237 if (len == -1)
00238 return (gunichar) - 1;
00239 UTF8_GET (result, p, i, mask, len);
00240
00241 return result;
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 static int
00256 g_unichar_to_utf8 (gunichar c, gchar * outbuf)
00257 {
00258 guint len = 0;
00259 int first;
00260
00261 if (c < 0x80)
00262 {
00263 first = 0;
00264 len = 1;
00265 }
00266 else if (c < 0x800)
00267 {
00268 first = 0xc0;
00269 len = 2;
00270 }
00271 else if (c < 0x10000)
00272 {
00273 first = 0xe0;
00274 len = 3;
00275 }
00276 else if (c < 0x200000)
00277 {
00278 first = 0xf0;
00279 len = 4;
00280 }
00281 else if (c < 0x4000000)
00282 {
00283 first = 0xf8;
00284 len = 5;
00285 }
00286 else
00287 {
00288 first = 0xfc;
00289 len = 6;
00290 }
00291
00292 if (outbuf)
00293 {
00294 guint i;
00295 for (i = len - 1; i > 0; --i)
00296 {
00297 outbuf[i] = (c & 0x3f) | 0x80;
00298 c >>= 6;
00299 }
00300 outbuf[0] = c | first;
00301 }
00302
00303 return len;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 static gunichar *
00323 g_utf8_to_ucs4_fast (const gchar * str, glong len, glong * items_written)
00324 {
00325 gint j, charlen;
00326 gunichar *result;
00327 gint n_chars, i;
00328 const gchar *p;
00329
00330 g_return_val_if_fail (str != NULL, NULL);
00331
00332 p = str;
00333 n_chars = 0;
00334 if (len < 0)
00335 {
00336 while (*p)
00337 {
00338 p = g_utf8_next_char (p);
00339 ++n_chars;
00340 }
00341 }
00342 else
00343 {
00344 while (p < str + len && *p)
00345 {
00346 p = g_utf8_next_char (p);
00347 ++n_chars;
00348 }
00349 }
00350
00351 result = g_new (gunichar, n_chars + 1);
00352 if (!result)
00353 return NULL;
00354
00355 p = str;
00356 for (i = 0; i < n_chars; i++)
00357 {
00358 gunichar wc = ((const unsigned char *) p)[0];
00359
00360 if (wc < 0x80)
00361 {
00362 result[i] = wc;
00363 p++;
00364 }
00365 else
00366 {
00367 if (wc < 0xe0)
00368 {
00369 charlen = 2;
00370 wc &= 0x1f;
00371 }
00372 else if (wc < 0xf0)
00373 {
00374 charlen = 3;
00375 wc &= 0x0f;
00376 }
00377 else if (wc < 0xf8)
00378 {
00379 charlen = 4;
00380 wc &= 0x07;
00381 }
00382 else if (wc < 0xfc)
00383 {
00384 charlen = 5;
00385 wc &= 0x03;
00386 }
00387 else
00388 {
00389 charlen = 6;
00390 wc &= 0x01;
00391 }
00392
00393 for (j = 1; j < charlen; j++)
00394 {
00395 wc <<= 6;
00396 wc |= ((const unsigned char *) p)[j] & 0x3f;
00397 }
00398
00399 result[i] = wc;
00400 p += charlen;
00401 }
00402 }
00403 result[i] = 0;
00404
00405 if (items_written)
00406 *items_written = i;
00407
00408 return result;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 static gchar *
00433 g_ucs4_to_utf8 (const gunichar * str,
00434 glong len,
00435 glong * items_read, glong * items_written)
00436 {
00437 gint result_length;
00438 gchar *result = NULL;
00439 gchar *p;
00440 gint i;
00441
00442 result_length = 0;
00443 for (i = 0; len < 0 || i < len; i++)
00444 {
00445 if (!str[i])
00446 break;
00447
00448 if (str[i] >= 0x80000000)
00449 {
00450 if (items_read)
00451 *items_read = i;
00452
00453 goto err_out;
00454 }
00455
00456 result_length += UTF8_LENGTH (str[i]);
00457 }
00458
00459 result = g_malloc (result_length + 1);
00460 if (!result)
00461 return NULL;
00462 p = result;
00463
00464 i = 0;
00465 while (p < result + result_length)
00466 p += g_unichar_to_utf8 (str[i++], p);
00467
00468 *p = '\0';
00469
00470 if (items_written)
00471 *items_written = p - result;
00472
00473 err_out:
00474 if (items_read)
00475 *items_read = i;
00476
00477 return result;
00478 }
00479
00480
00481
00482 #include "gunidecomp.h"
00483 #include "gunicomp.h"
00484
00485 #define CC_PART1(Page, Char) \
00486 ((combining_class_table_part1[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
00487 ? (combining_class_table_part1[Page] - G_UNICODE_MAX_TABLE_INDEX) \
00488 : (cclass_data[combining_class_table_part1[Page]][Char]))
00489
00490 #define CC_PART2(Page, Char) \
00491 ((combining_class_table_part2[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
00492 ? (combining_class_table_part2[Page] - G_UNICODE_MAX_TABLE_INDEX) \
00493 : (cclass_data[combining_class_table_part2[Page]][Char]))
00494
00495 #define COMBINING_CLASS(Char) \
00496 (((Char) <= G_UNICODE_LAST_CHAR_PART1) \
00497 ? CC_PART1 ((Char) >> 8, (Char) & 0xff) \
00498 : (((Char) >= 0xe0000 && (Char) <= G_UNICODE_LAST_CHAR) \
00499 ? CC_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \
00500 : 0))
00501
00502
00503 #define SBase 0xAC00
00504 #define LBase 0x1100
00505 #define VBase 0x1161
00506 #define TBase 0x11A7
00507 #define LCount 19
00508 #define VCount 21
00509 #define TCount 28
00510 #define NCount (VCount * TCount)
00511 #define SCount (LCount * NCount)
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 static void
00524 g_unicode_canonical_ordering (gunichar * string, gsize len)
00525 {
00526 gsize i;
00527 int swap = 1;
00528
00529 while (swap)
00530 {
00531 int last;
00532 swap = 0;
00533 last = COMBINING_CLASS (string[0]);
00534 for (i = 0; i < len - 1; ++i)
00535 {
00536 int next = COMBINING_CLASS (string[i + 1]);
00537 if (next != 0 && last > next)
00538 {
00539 gsize j;
00540
00541 for (j = i + 1; j > 0; --j)
00542 {
00543 gunichar t;
00544 if (COMBINING_CLASS (string[j - 1]) <= next)
00545 break;
00546 t = string[j];
00547 string[j] = string[j - 1];
00548 string[j - 1] = t;
00549 swap = 1;
00550 }
00551
00552
00553 next = last;
00554 }
00555 last = next;
00556 }
00557 }
00558 }
00559
00560
00561
00562
00563
00564 static void
00565 decompose_hangul (gunichar s, gunichar * r, gsize * result_len)
00566 {
00567 gint SIndex = s - SBase;
00568
00569
00570 if (SIndex < 0 || SIndex >= SCount)
00571 {
00572 if (r)
00573 r[0] = s;
00574 *result_len = 1;
00575 }
00576 else
00577 {
00578 gunichar L = LBase + SIndex / NCount;
00579 gunichar V = VBase + (SIndex % NCount) / TCount;
00580 gunichar T = TBase + SIndex % TCount;
00581
00582 if (r)
00583 {
00584 r[0] = L;
00585 r[1] = V;
00586 }
00587
00588 if (T != TBase)
00589 {
00590 if (r)
00591 r[2] = T;
00592 *result_len = 3;
00593 }
00594 else
00595 *result_len = 2;
00596 }
00597 }
00598
00599
00600 static const gchar *
00601 find_decomposition (gunichar ch, gboolean compat)
00602 {
00603 int start = 0;
00604 int end = G_N_ELEMENTS (decomp_table);
00605
00606 if (ch >= decomp_table[start].ch && ch <= decomp_table[end - 1].ch)
00607 {
00608 while (TRUE)
00609 {
00610 int half = (start + end) / 2;
00611 if (ch == decomp_table[half].ch)
00612 {
00613 int offset;
00614
00615 if (compat)
00616 {
00617 offset = decomp_table[half].compat_offset;
00618 if (offset == G_UNICODE_NOT_PRESENT_OFFSET)
00619 offset = decomp_table[half].canon_offset;
00620 }
00621 else
00622 {
00623 offset = decomp_table[half].canon_offset;
00624 if (offset == G_UNICODE_NOT_PRESENT_OFFSET)
00625 return NULL;
00626 }
00627
00628 return &(decomp_expansion_string[offset]);
00629 }
00630 else if (half == start)
00631 break;
00632 else if (ch > decomp_table[half].ch)
00633 start = half;
00634 else
00635 end = half;
00636 }
00637 }
00638
00639 return NULL;
00640 }
00641
00642
00643 static gboolean
00644 combine_hangul (gunichar a, gunichar b, gunichar * result)
00645 {
00646 gint LIndex = a - LBase;
00647 gint SIndex = a - SBase;
00648
00649 gint VIndex = b - VBase;
00650 gint TIndex = b - TBase;
00651
00652 if (0 <= LIndex && LIndex < LCount && 0 <= VIndex && VIndex < VCount)
00653 {
00654 *result = SBase + (LIndex * VCount + VIndex) * TCount;
00655 return TRUE;
00656 }
00657 else if (0 <= SIndex && SIndex < SCount && (SIndex % TCount) == 0
00658 && 0 <= TIndex && TIndex <= TCount)
00659 {
00660 *result = a + TIndex;
00661 return TRUE;
00662 }
00663
00664 return FALSE;
00665 }
00666
00667 #define CI(Page, Char) \
00668 ((compose_table[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
00669 ? (compose_table[Page] - G_UNICODE_MAX_TABLE_INDEX) \
00670 : (compose_data[compose_table[Page]][Char]))
00671
00672 #define COMPOSE_INDEX(Char) \
00673 ((((Char) >> 8) > (COMPOSE_TABLE_LAST)) ? 0 : CI((Char) >> 8, (Char) & 0xff))
00674
00675 static gboolean
00676 combine (gunichar a, gunichar b, gunichar * result)
00677 {
00678 gushort index_a, index_b;
00679
00680 if (combine_hangul (a, b, result))
00681 return TRUE;
00682
00683 index_a = COMPOSE_INDEX (a);
00684
00685 if (index_a >= COMPOSE_FIRST_SINGLE_START && index_a < COMPOSE_SECOND_START)
00686 {
00687 if (b == compose_first_single[index_a - COMPOSE_FIRST_SINGLE_START][0])
00688 {
00689 *result =
00690 compose_first_single[index_a - COMPOSE_FIRST_SINGLE_START][1];
00691 return TRUE;
00692 }
00693 else
00694 return FALSE;
00695 }
00696
00697 index_b = COMPOSE_INDEX (b);
00698
00699 if (index_b >= COMPOSE_SECOND_SINGLE_START)
00700 {
00701 if (a ==
00702 compose_second_single[index_b - COMPOSE_SECOND_SINGLE_START][0])
00703 {
00704 *result =
00705 compose_second_single[index_b - COMPOSE_SECOND_SINGLE_START][1];
00706 return TRUE;
00707 }
00708 else
00709 return FALSE;
00710 }
00711
00712 if (index_a >= COMPOSE_FIRST_START && index_a < COMPOSE_FIRST_SINGLE_START
00713 && index_b >= COMPOSE_SECOND_START
00714 && index_b < COMPOSE_SECOND_SINGLE_START)
00715 {
00716 gunichar res =
00717 compose_array[index_a - COMPOSE_FIRST_START][index_b -
00718 COMPOSE_SECOND_START];
00719
00720 if (res)
00721 {
00722 *result = res;
00723 return TRUE;
00724 }
00725 }
00726
00727 return FALSE;
00728 }
00729
00730 static gunichar *
00731 _g_utf8_normalize_wc (const gchar * str, gssize max_len, GNormalizeMode mode)
00732 {
00733 gsize n_wc;
00734 gunichar *wc_buffer;
00735 const char *p;
00736 gsize last_start;
00737 gboolean do_compat = (mode == G_NORMALIZE_NFKC || mode == G_NORMALIZE_NFKD);
00738 gboolean do_compose = (mode == G_NORMALIZE_NFC || mode == G_NORMALIZE_NFKC);
00739
00740 n_wc = 0;
00741 p = str;
00742 while ((max_len < 0 || p < str + max_len) && *p)
00743 {
00744 const gchar *decomp;
00745 gunichar wc = g_utf8_get_char (p);
00746
00747 if (wc >= 0xac00 && wc <= 0xd7af)
00748 {
00749 gsize result_len;
00750 decompose_hangul (wc, NULL, &result_len);
00751 n_wc += result_len;
00752 }
00753 else
00754 {
00755 decomp = find_decomposition (wc, do_compat);
00756
00757 if (decomp)
00758 n_wc += g_utf8_strlen (decomp, -1);
00759 else
00760 n_wc++;
00761 }
00762
00763 p = g_utf8_next_char (p);
00764 }
00765
00766 wc_buffer = g_new (gunichar, n_wc + 1);
00767 if (!wc_buffer)
00768 return NULL;
00769
00770 last_start = 0;
00771 n_wc = 0;
00772 p = str;
00773 while ((max_len < 0 || p < str + max_len) && *p)
00774 {
00775 gunichar wc = g_utf8_get_char (p);
00776 const gchar *decomp;
00777 int cc;
00778 gsize old_n_wc = n_wc;
00779
00780 if (wc >= 0xac00 && wc <= 0xd7af)
00781 {
00782 gsize result_len;
00783 decompose_hangul (wc, wc_buffer + n_wc, &result_len);
00784 n_wc += result_len;
00785 }
00786 else
00787 {
00788 decomp = find_decomposition (wc, do_compat);
00789
00790 if (decomp)
00791 {
00792 const char *pd;
00793 for (pd = decomp; *pd != '\0'; pd = g_utf8_next_char (pd))
00794 wc_buffer[n_wc++] = g_utf8_get_char (pd);
00795 }
00796 else
00797 wc_buffer[n_wc++] = wc;
00798 }
00799
00800 if (n_wc > 0)
00801 {
00802 cc = COMBINING_CLASS (wc_buffer[old_n_wc]);
00803
00804 if (cc == 0)
00805 {
00806 g_unicode_canonical_ordering (wc_buffer + last_start,
00807 n_wc - last_start);
00808 last_start = old_n_wc;
00809 }
00810 }
00811
00812 p = g_utf8_next_char (p);
00813 }
00814
00815 if (n_wc > 0)
00816 {
00817 g_unicode_canonical_ordering (wc_buffer + last_start,
00818 n_wc - last_start);
00819 last_start = n_wc;
00820 }
00821
00822 wc_buffer[n_wc] = 0;
00823
00824
00825
00826 if (do_compose && n_wc > 0)
00827 {
00828 gsize i, j;
00829 int last_cc = 0;
00830 last_start = 0;
00831
00832 for (i = 0; i < n_wc; i++)
00833 {
00834 int cc = COMBINING_CLASS (wc_buffer[i]);
00835
00836 if (i > 0 &&
00837 (last_cc == 0 || last_cc != cc) &&
00838 combine (wc_buffer[last_start], wc_buffer[i],
00839 &wc_buffer[last_start]))
00840 {
00841 for (j = i + 1; j < n_wc; j++)
00842 wc_buffer[j - 1] = wc_buffer[j];
00843 n_wc--;
00844 i--;
00845
00846 if (i == last_start)
00847 last_cc = 0;
00848 else
00849 last_cc = COMBINING_CLASS (wc_buffer[i - 1]);
00850
00851 continue;
00852 }
00853
00854 if (cc == 0)
00855 last_start = i;
00856
00857 last_cc = cc;
00858 }
00859 }
00860
00861 wc_buffer[n_wc] = 0;
00862
00863 return wc_buffer;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 static gchar *
00903 g_utf8_normalize (const gchar * str, gssize len, GNormalizeMode mode)
00904 {
00905 gunichar *result_wc = _g_utf8_normalize_wc (str, len, mode);
00906 gchar *result;
00907
00908 result = g_ucs4_to_utf8 (result_wc, -1, NULL, NULL);
00909 g_free (result_wc);
00910
00911 return result;
00912 }
00913
00914
00915
00926 uint32_t
00927 stringprep_utf8_to_unichar (const char *p)
00928 {
00929 return g_utf8_get_char (p);
00930 }
00931
00943 int
00944 stringprep_unichar_to_utf8 (uint32_t c, char *outbuf)
00945 {
00946 return g_unichar_to_utf8 (c, outbuf);
00947 }
00948
00964 uint32_t *
00965 stringprep_utf8_to_ucs4 (const char *str, ssize_t len, size_t * items_written)
00966 {
00967 return g_utf8_to_ucs4_fast (str, (glong) len, (glong *) items_written);
00968 }
00969
00988 char *
00989 stringprep_ucs4_to_utf8 (const uint32_t * str, ssize_t len,
00990 size_t * items_read, size_t * items_written)
00991 {
00992 return g_ucs4_to_utf8 (str, len, (glong *) items_read,
00993 (glong *) items_written);
00994 }
00995
01018 char *
01019 stringprep_utf8_nfkc_normalize (const char *str, ssize_t len)
01020 {
01021 return g_utf8_normalize (str, len, G_NORMALIZE_NFKC);
01022 }
01023
01035 uint32_t *
01036 stringprep_ucs4_nfkc_normalize (uint32_t * str, ssize_t len)
01037 {
01038 char *p;
01039 uint32_t *result_wc;
01040
01041 p = stringprep_ucs4_to_utf8 (str, len, 0, 0);
01042 result_wc = _g_utf8_normalize_wc (p, -1, G_NORMALIZE_NFKC);
01043 free (p);
01044
01045 return result_wc;
01046 }