1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2008 Index Data
3 * See the file LICENSE for details.
12 #include <yaz/timing.h>
16 #include <yaz/xmalloc.h>
18 #include <yaz/icu_I18N.h>
26 #include <unicode/ustring.h> /* some more string fcns*/
27 #include <unicode/uchar.h> /* char names */
30 #include <unicode/ucol.h>
33 int icu_check_status (UErrorCode status)
35 if (U_FAILURE(status))
37 yaz_log(YLOG_WARN, "ICU: %d %s\n", status, u_errorName(status));
46 struct icu_buf_utf16 * icu_buf_utf16_create(size_t capacity)
48 struct icu_buf_utf16 * buf16
49 = (struct icu_buf_utf16 *) xmalloc(sizeof(struct icu_buf_utf16));
56 buf16->utf16 = (UChar *) xmalloc(sizeof(UChar) * capacity);
57 buf16->utf16[0] = (UChar) 0;
58 buf16->utf16_cap = capacity;
63 struct icu_buf_utf16 * icu_buf_utf16_clear(struct icu_buf_utf16 * buf16)
67 buf16->utf16[0] = (UChar) 0;
73 struct icu_buf_utf16 * icu_buf_utf16_resize(struct icu_buf_utf16 * buf16,
80 if (0 == buf16->utf16)
81 buf16->utf16 = (UChar *) xmalloc(sizeof(UChar) * capacity);
84 = (UChar *) xrealloc(buf16->utf16, sizeof(UChar) * capacity);
86 icu_buf_utf16_clear(buf16);
87 buf16->utf16_cap = capacity;
100 struct icu_buf_utf16 * icu_buf_utf16_copy(struct icu_buf_utf16 * dest16,
101 struct icu_buf_utf16 * src16)
107 if (dest16->utf16_cap < src16->utf16_len)
108 icu_buf_utf16_resize(dest16, src16->utf16_len * 2);
110 u_strncpy(dest16->utf16, src16->utf16, src16->utf16_len);
111 dest16->utf16_len = src16->utf16_len;
117 void icu_buf_utf16_destroy(struct icu_buf_utf16 * buf16)
126 struct icu_buf_utf8 * icu_buf_utf8_create(size_t capacity)
128 struct icu_buf_utf8 * buf8
129 = (struct icu_buf_utf8 *) xmalloc(sizeof(struct icu_buf_utf8));
136 buf8->utf8 = (uint8_t *) xmalloc(sizeof(uint8_t) * capacity);
137 buf8->utf8[0] = (uint8_t) 0;
138 buf8->utf8_cap = capacity;
144 struct icu_buf_utf8 * icu_buf_utf8_clear(struct icu_buf_utf8 * buf8)
148 buf8->utf8[0] = (uint8_t) 0;
155 struct icu_buf_utf8 * icu_buf_utf8_resize(struct icu_buf_utf8 * buf8,
163 buf8->utf8 = (uint8_t *) xmalloc(sizeof(uint8_t) * capacity);
166 = (uint8_t *) xrealloc(buf8->utf8, sizeof(uint8_t) * capacity);
168 buf8->utf8_cap = capacity;
181 const char *icu_buf_utf8_to_cstr(struct icu_buf_utf8 *src8)
183 if (!src8 || src8->utf8_len == 0)
186 if (src8->utf8_len == src8->utf8_cap)
187 src8 = icu_buf_utf8_resize(src8, src8->utf8_len * 2 + 1);
189 src8->utf8[src8->utf8_len] = '\0';
191 return (const char *) src8->utf8;
195 void icu_buf_utf8_destroy(struct icu_buf_utf8 * buf8)
204 UErrorCode icu_utf16_from_utf8(struct icu_buf_utf16 * dest16,
205 struct icu_buf_utf8 * src8,
208 int32_t utf16_len = 0;
210 u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
212 (const char *) src8->utf8, src8->utf8_len, status);
214 /* check for buffer overflow, resize and retry */
215 if (*status == U_BUFFER_OVERFLOW_ERROR)
217 icu_buf_utf16_resize(dest16, utf16_len * 2);
218 *status = U_ZERO_ERROR;
219 u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
221 (const char *) src8->utf8, src8->utf8_len, status);
224 if (U_SUCCESS(*status)
225 && utf16_len <= dest16->utf16_cap)
226 dest16->utf16_len = utf16_len;
228 icu_buf_utf16_clear(dest16);
235 UErrorCode icu_utf16_from_utf8_cstr(struct icu_buf_utf16 * dest16,
236 const char * src8cstr,
239 size_t src8cstr_len = 0;
240 int32_t utf16_len = 0;
242 *status = U_ZERO_ERROR;
243 src8cstr_len = strlen(src8cstr);
245 u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
247 src8cstr, src8cstr_len, status);
249 /* check for buffer overflow, resize and retry */
250 if (*status == U_BUFFER_OVERFLOW_ERROR)
252 icu_buf_utf16_resize(dest16, utf16_len * 2);
253 *status = U_ZERO_ERROR;
254 u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
256 src8cstr, src8cstr_len, status);
259 if (U_SUCCESS(*status)
260 && utf16_len <= dest16->utf16_cap)
261 dest16->utf16_len = utf16_len;
263 icu_buf_utf16_clear(dest16);
271 UErrorCode icu_utf16_to_utf8(struct icu_buf_utf8 * dest8,
272 struct icu_buf_utf16 * src16,
275 int32_t utf8_len = 0;
277 u_strToUTF8((char *) dest8->utf8, dest8->utf8_cap,
279 src16->utf16, src16->utf16_len, status);
281 /* check for buffer overflow, resize and retry */
282 if (*status == U_BUFFER_OVERFLOW_ERROR)
284 icu_buf_utf8_resize(dest8, utf8_len * 2);
285 *status = U_ZERO_ERROR;
286 u_strToUTF8((char *) dest8->utf8, dest8->utf8_cap,
288 src16->utf16, src16->utf16_len, status);
292 if (U_SUCCESS(*status)
293 && utf8_len <= dest8->utf8_cap)
294 dest8->utf8_len = utf8_len;
296 icu_buf_utf8_clear(dest8);
303 struct icu_casemap * icu_casemap_create(char action, UErrorCode *status)
305 struct icu_casemap * casemap
306 = (struct icu_casemap *) xmalloc(sizeof(struct icu_casemap));
307 casemap->action = action;
309 switch(casemap->action) {
320 icu_casemap_destroy(casemap);
327 void icu_casemap_destroy(struct icu_casemap * casemap)
333 int icu_casemap_casemap(struct icu_casemap * casemap,
334 struct icu_buf_utf16 * dest16,
335 struct icu_buf_utf16 * src16,
342 return icu_utf16_casemap(dest16, src16, locale,
343 casemap->action, status);
347 int icu_utf16_casemap(struct icu_buf_utf16 * dest16,
348 struct icu_buf_utf16 * src16,
349 const char *locale, char action,
352 int32_t dest16_len = 0;
355 if (!src16->utf16_len){ /* guarding for empty source string */
357 dest16->utf16[0] = (UChar) 0;
358 dest16->utf16_len = 0;
366 dest16_len = u_strToLower(dest16->utf16, dest16->utf16_cap,
367 src16->utf16, src16->utf16_len,
372 dest16_len = u_strToUpper(dest16->utf16, dest16->utf16_cap,
373 src16->utf16, src16->utf16_len,
378 dest16_len = u_strToTitle(dest16->utf16, dest16->utf16_cap,
379 src16->utf16, src16->utf16_len,
384 dest16_len = u_strFoldCase(dest16->utf16, dest16->utf16_cap,
385 src16->utf16, src16->utf16_len,
386 U_FOLD_CASE_DEFAULT, status);
390 return U_UNSUPPORTED_ERROR;
394 /* check for buffer overflow, resize and retry */
395 if (*status == U_BUFFER_OVERFLOW_ERROR
396 && dest16 != src16 /* do not resize if in-place conversion */
398 icu_buf_utf16_resize(dest16, dest16_len * 2);
399 *status = U_ZERO_ERROR;
405 dest16_len = u_strToLower(dest16->utf16, dest16->utf16_cap,
406 src16->utf16, src16->utf16_len,
411 dest16_len = u_strToUpper(dest16->utf16, dest16->utf16_cap,
412 src16->utf16, src16->utf16_len,
417 dest16_len = u_strToTitle(dest16->utf16, dest16->utf16_cap,
418 src16->utf16, src16->utf16_len,
423 dest16_len = u_strFoldCase(dest16->utf16, dest16->utf16_cap,
424 src16->utf16, src16->utf16_len,
425 U_FOLD_CASE_DEFAULT, status);
429 return U_UNSUPPORTED_ERROR;
434 if (U_SUCCESS(*status)
435 && dest16_len <= dest16->utf16_cap)
436 dest16->utf16_len = dest16_len;
439 dest16->utf16[0] = (UChar) 0;
440 dest16->utf16_len = 0;
448 void icu_sortkey8_from_utf16(UCollator *coll,
449 struct icu_buf_utf8 * dest8,
450 struct icu_buf_utf16 * src16,
454 int32_t sortkey_len = 0;
456 sortkey_len = ucol_getSortKey(coll, src16->utf16, src16->utf16_len,
457 dest8->utf8, dest8->utf8_cap);
459 /* check for buffer overflow, resize and retry */
460 if (sortkey_len > dest8->utf8_cap) {
461 icu_buf_utf8_resize(dest8, sortkey_len * 2);
462 sortkey_len = ucol_getSortKey(coll, src16->utf16, src16->utf16_len,
463 dest8->utf8, dest8->utf8_cap);
466 if (U_SUCCESS(*status)
468 dest8->utf8_len = sortkey_len;
470 icu_buf_utf8_clear(dest8);
475 struct icu_tokenizer * icu_tokenizer_create(const char *locale, char action,
478 struct icu_tokenizer * tokenizer
479 = (struct icu_tokenizer *) xmalloc(sizeof(struct icu_tokenizer));
481 tokenizer->action = action;
483 tokenizer->buf16 = 0;
484 tokenizer->token_count = 0;
485 tokenizer->token_id = 0;
486 tokenizer->token_start = 0;
487 tokenizer->token_end = 0;
490 switch(tokenizer->action) {
493 tokenizer->bi = ubrk_open(UBRK_LINE, locale, 0, 0, status);
497 tokenizer->bi = ubrk_open(UBRK_SENTENCE, locale, 0, 0, status);
501 tokenizer->bi = ubrk_open(UBRK_WORD, locale, 0, 0, status);
505 tokenizer->bi = ubrk_open(UBRK_CHARACTER, locale, 0, 0, status);
509 tokenizer->bi = ubrk_open(UBRK_TITLE, locale, 0, 0, status);
512 *status = U_UNSUPPORTED_ERROR;
517 /* ICU error stuff is a very funny business */
518 if (U_SUCCESS(*status))
521 /* freeing if failed */
522 icu_tokenizer_destroy(tokenizer);
526 void icu_tokenizer_destroy(struct icu_tokenizer * tokenizer)
530 ubrk_close(tokenizer->bi);
535 int icu_tokenizer_attach(struct icu_tokenizer * tokenizer,
536 struct icu_buf_utf16 * src16,
539 if (!tokenizer || !tokenizer->bi || !src16)
543 tokenizer->buf16 = src16;
544 tokenizer->token_count = 0;
545 tokenizer->token_id = 0;
546 tokenizer->token_start = 0;
547 tokenizer->token_end = 0;
549 ubrk_setText(tokenizer->bi, src16->utf16, src16->utf16_len, status);
552 if (U_FAILURE(*status))
558 int32_t icu_tokenizer_next_token(struct icu_tokenizer * tokenizer,
559 struct icu_buf_utf16 * tkn16,
562 int32_t tkn_start = 0;
567 if (!tokenizer || !tokenizer->bi
568 || !tokenizer->buf16 || !tokenizer->buf16->utf16_len)
572 never change tokenizer->buf16 and keep always invariant
573 0 <= tokenizer->token_start
574 <= tokenizer->token_end
575 <= tokenizer->buf16->utf16_len
576 returns length of token
579 if (0 == tokenizer->token_end) /* first call */
580 tkn_start = ubrk_first(tokenizer->bi);
581 else /* successive calls */
582 tkn_start = tokenizer->token_end;
584 /* get next position */
585 tkn_end = ubrk_next(tokenizer->bi);
587 /* repairing invariant at end of ubrk, which is UBRK_DONE = -1 */
588 if (UBRK_DONE == tkn_end)
589 tkn_end = tokenizer->buf16->utf16_len;
591 /* copy out if everything is well */
592 if(U_FAILURE(*status))
595 /* everything OK, now update internal state */
596 tkn_len = tkn_end - tkn_start;
599 tokenizer->token_count++;
600 tokenizer->token_id++;
602 tokenizer->token_id = 0;
604 tokenizer->token_start = tkn_start;
605 tokenizer->token_end = tkn_end;
608 /* copying into token buffer if it exists */
610 if (tkn16->utf16_cap < tkn_len)
611 icu_buf_utf16_resize(tkn16, (size_t) tkn_len * 2);
613 u_strncpy(tkn16->utf16, &(tokenizer->buf16->utf16)[tkn_start],
616 tkn16->utf16_len = tkn_len;
623 int32_t icu_tokenizer_token_id(struct icu_tokenizer * tokenizer)
625 return tokenizer->token_id;
628 int32_t icu_tokenizer_token_start(struct icu_tokenizer * tokenizer)
630 return tokenizer->token_start;
633 int32_t icu_tokenizer_token_end(struct icu_tokenizer * tokenizer)
635 return tokenizer->token_end;
638 int32_t icu_tokenizer_token_length(struct icu_tokenizer * tokenizer)
640 return (tokenizer->token_end - tokenizer->token_start);
643 int32_t icu_tokenizer_token_count(struct icu_tokenizer * tokenizer)
645 return tokenizer->token_count;
650 struct icu_normalizer * icu_normalizer_create(const char *rules, char action,
654 struct icu_normalizer * normalizer
655 = (struct icu_normalizer *) xmalloc(sizeof(struct icu_normalizer));
657 normalizer->action = action;
658 normalizer->trans = 0;
659 normalizer->rules16 = icu_buf_utf16_create(0);
660 icu_utf16_from_utf8_cstr(normalizer->rules16, rules, status);
662 switch(normalizer->action) {
666 = utrans_openU(normalizer->rules16->utf16,
667 normalizer->rules16->utf16_len,
670 normalizer->parse_error, status);
675 = utrans_openU(normalizer->rules16->utf16,
676 normalizer->rules16->utf16_len,
679 normalizer->parse_error, status);
682 *status = U_UNSUPPORTED_ERROR;
687 if (U_SUCCESS(*status))
690 /* freeing if failed */
691 icu_normalizer_destroy(normalizer);
696 void icu_normalizer_destroy(struct icu_normalizer * normalizer){
698 if (normalizer->rules16)
699 icu_buf_utf16_destroy(normalizer->rules16);
700 if (normalizer->trans)
701 utrans_close(normalizer->trans);
708 int icu_normalizer_normalize(struct icu_normalizer * normalizer,
709 struct icu_buf_utf16 * dest16,
710 struct icu_buf_utf16 * src16,
713 if (!normalizer || !normalizer->trans
718 if (!src16->utf16_len){ /* guarding for empty source string */
719 icu_buf_utf16_clear(dest16);
723 if (!icu_buf_utf16_copy(dest16, src16))
727 utrans_transUChars (normalizer->trans,
728 dest16->utf16, &(dest16->utf16_len),
730 0, &(src16->utf16_len), status);
732 if (U_FAILURE(*status))
733 icu_buf_utf16_clear(dest16);
735 return dest16->utf16_len;
741 struct icu_chain_step * icu_chain_step_create(struct icu_chain * chain,
742 enum icu_chain_step_type type,
743 const uint8_t * rule,
744 struct icu_buf_utf16 * buf16,
747 struct icu_chain_step * step = 0;
749 if(!chain || !type || !rule)
752 step = (struct icu_chain_step *) xmalloc(sizeof(struct icu_chain_step));
758 /* create auxilary objects */
760 case ICU_chain_step_type_display:
762 case ICU_chain_step_type_casemap:
763 step->u.casemap = icu_casemap_create(rule[0], status);
765 case ICU_chain_step_type_normalize:
766 step->u.normalizer = icu_normalizer_create((char *) rule, 'f', status);
768 case ICU_chain_step_type_tokenize:
769 step->u.tokenizer = icu_tokenizer_create((char *) chain->locale,
770 (char) rule[0], status);
780 void icu_chain_step_destroy(struct icu_chain_step * step){
785 icu_chain_step_destroy(step->previous);
788 case ICU_chain_step_type_display:
790 case ICU_chain_step_type_casemap:
791 icu_casemap_destroy(step->u.casemap);
792 icu_buf_utf16_destroy(step->buf16);
794 case ICU_chain_step_type_normalize:
795 icu_normalizer_destroy(step->u.normalizer);
796 icu_buf_utf16_destroy(step->buf16);
798 case ICU_chain_step_type_tokenize:
799 icu_tokenizer_destroy(step->u.tokenizer);
800 icu_buf_utf16_destroy(step->buf16);
810 struct icu_chain * icu_chain_create(const char *locale, int sort,
813 struct icu_chain * chain
814 = (struct icu_chain *) xmalloc(sizeof(struct icu_chain));
816 *status = U_ZERO_ERROR;
818 chain->locale = xstrdup(locale);
822 chain->coll = ucol_open((const char *) chain->locale, status);
824 if (U_FAILURE(*status))
827 chain->token_count = 0;
831 chain->display8 = icu_buf_utf8_create(0);
832 chain->norm8 = icu_buf_utf8_create(0);
833 chain->sort8 = icu_buf_utf8_create(0);
835 chain->src16 = icu_buf_utf16_create(0);
843 void icu_chain_destroy(struct icu_chain * chain)
848 ucol_close(chain->coll);
850 icu_buf_utf8_destroy(chain->display8);
851 icu_buf_utf8_destroy(chain->norm8);
852 icu_buf_utf8_destroy(chain->sort8);
854 icu_buf_utf16_destroy(chain->src16);
856 icu_chain_step_destroy(chain->steps);
857 xfree(chain->locale);
864 struct icu_chain * icu_chain_xml_config(const xmlNode *xml_node,
869 struct icu_chain * chain = 0;
871 *status = U_ZERO_ERROR;
873 if (!xml_node ||xml_node->type != XML_ELEMENT_NODE)
877 xmlChar * xml_locale = xmlGetProp((xmlNode *) xml_node,
878 (xmlChar *) "locale");
882 chain = icu_chain_create((const char *) xml_locale, sort, status);
890 for (node = xml_node->children; node; node = node->next)
893 struct icu_chain_step * step = 0;
895 if (node->type != XML_ELEMENT_NODE)
898 xml_rule = xmlGetProp(node, (xmlChar *) "rule");
900 if (!strcmp((const char *) node->name, "casemap"))
901 step = icu_chain_insert_step(chain, ICU_chain_step_type_casemap,
902 (const uint8_t *) xml_rule, status);
903 else if (!strcmp((const char *) node->name, "transform"))
904 step = icu_chain_insert_step(chain, ICU_chain_step_type_normalize,
905 (const uint8_t *) xml_rule, status);
906 else if (!strcmp((const char *) node->name, "tokenize"))
907 step = icu_chain_insert_step(chain, ICU_chain_step_type_tokenize,
908 (const uint8_t *) xml_rule, status);
909 else if (!strcmp((const char *) node->name, "display"))
910 step = icu_chain_insert_step(chain, ICU_chain_step_type_display,
911 (const uint8_t *) "", status);
913 if (!step || U_FAILURE(*status))
915 icu_chain_destroy(chain);
926 struct icu_chain_step * icu_chain_insert_step(struct icu_chain * chain,
927 enum icu_chain_step_type type,
928 const uint8_t * rule,
931 struct icu_chain_step * step = 0;
932 struct icu_buf_utf16 * src16 = 0;
933 struct icu_buf_utf16 * buf16 = 0;
935 if (!chain || !type || !rule)
938 /* assign utf16 src buffers as needed */
939 if (chain->steps && chain->steps->buf16)
940 src16 = chain->steps->buf16;
941 else if (chain->src16)
942 src16 = chain->src16;
947 /* create utf16 destination buffers as needed, or */
950 case ICU_chain_step_type_display:
953 case ICU_chain_step_type_casemap:
954 buf16 = icu_buf_utf16_create(0);
956 case ICU_chain_step_type_normalize:
957 buf16 = icu_buf_utf16_create(0);
959 case ICU_chain_step_type_tokenize:
960 buf16 = icu_buf_utf16_create(0);
966 /* create actual chain step with this buffer */
967 step = icu_chain_step_create(chain, type, rule, buf16, status);
969 step->previous = chain->steps;
976 int icu_chain_step_next_token(struct icu_chain * chain,
977 struct icu_chain_step * step,
980 struct icu_buf_utf16 * src16 = 0;
981 int got_new_token = 0;
983 if (!chain || !chain->src16 || !step || !step->more_tokens)
986 /* assign utf16 src buffers as neeed, advance in previous steps
987 tokens until non-zero token met, and setting stop condition */
991 src16 = step->previous->buf16;
992 /* tokens might be killed in previous steps, therefore looping */
994 while (step->need_new_token
995 && step->previous->more_tokens
998 = icu_chain_step_next_token(chain, step->previous, status);
1001 { /* first step can only work once on chain->src16 input buffer */
1002 src16 = chain->src16;
1003 step->more_tokens = 0;
1010 /* stop if nothing to process */
1011 if (step->need_new_token && !got_new_token)
1013 step->more_tokens = 0;
1017 /* either an old token not finished yet, or a new token, thus
1018 perform the work, eventually put this steps output in
1019 step->buf16 or the chains UTF8 output buffers */
1023 case ICU_chain_step_type_display:
1024 icu_utf16_to_utf8(chain->display8, src16, status);
1026 case ICU_chain_step_type_casemap:
1027 icu_casemap_casemap(step->u.casemap,
1028 step->buf16, src16, status,
1031 case ICU_chain_step_type_normalize:
1032 icu_normalizer_normalize(step->u.normalizer,
1033 step->buf16, src16, status);
1035 case ICU_chain_step_type_tokenize:
1036 /* attach to new src16 token only first time during splitting */
1037 if (step->need_new_token)
1039 icu_tokenizer_attach(step->u.tokenizer, src16, status);
1040 step->need_new_token = 0;
1043 /* splitting one src16 token into multiple buf16 tokens */
1045 = icu_tokenizer_next_token(step->u.tokenizer,
1046 step->buf16, status);
1048 /* make sure to get new previous token if this one had been used up
1049 by recursive call to _same_ step */
1051 if (!step->more_tokens)
1053 step->more_tokens = icu_chain_step_next_token(chain, step, status);
1054 return step->more_tokens; /* avoid one token count too much! */
1062 if (U_FAILURE(*status))
1065 /* if token disappered into thin air, tell caller */
1066 /* if (!step->buf16->utf16_len && !step->more_tokens) */
1073 int icu_chain_assign_cstr(struct icu_chain * chain,
1074 const char * src8cstr,
1077 struct icu_chain_step * stp = 0;
1079 if (!chain || !src8cstr)
1082 chain->src8cstr = src8cstr;
1086 /* clear token count */
1087 chain->token_count = 0;
1089 /* clear all steps stop states */
1092 stp->more_tokens = 1;
1093 stp->need_new_token = 1;
1094 stp = stp->previous;
1097 /* finally convert UTF8 to UTF16 string if needed */
1098 if (chain->steps || chain->sort)
1099 icu_utf16_from_utf8_cstr(chain->src16, chain->src8cstr, status);
1101 if (U_FAILURE(*status))
1109 int icu_chain_next_token(struct icu_chain * chain,
1114 *status = U_ZERO_ERROR;
1119 /* special case with no steps - same as index type binary */
1122 if (chain->token_count)
1126 chain->token_count++;
1129 icu_sortkey8_from_utf16(chain->coll,
1130 chain->sort8, chain->steps->buf16,
1132 return chain->token_count;
1135 /* usual case, one or more icu chain steps existing */
1138 while(!got_token && chain->steps && chain->steps->more_tokens)
1139 got_token = icu_chain_step_next_token(chain, chain->steps, status);
1143 chain->token_count++;
1145 icu_utf16_to_utf8(chain->norm8, chain->steps->buf16, status);
1148 icu_sortkey8_from_utf16(chain->coll,
1149 chain->sort8, chain->steps->buf16,
1152 return chain->token_count;
1159 int icu_chain_token_number(struct icu_chain * chain)
1164 return chain->token_count;
1168 const char * icu_chain_token_display(struct icu_chain * chain)
1170 if (chain->display8)
1171 return icu_buf_utf8_to_cstr(chain->display8);
1176 const char * icu_chain_token_norm(struct icu_chain * chain)
1179 return chain->src8cstr;
1182 return icu_buf_utf8_to_cstr(chain->norm8);
1187 const char * icu_chain_token_sortkey(struct icu_chain * chain)
1190 return icu_buf_utf8_to_cstr(chain->sort8);
1195 const UCollator * icu_chain_get_coll(struct icu_chain * chain)
1200 #endif /* YAZ_HAVE_ICU */
1205 * indent-tabs-mode: nil
1207 * vim: shiftwidth=4 tabstop=8 expandtab