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