Improve error reporting for ICU chains YAZ-707
[yaz-moved-to-github.git] / src / icu_transform.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file
8  * \brief ICU transforms - using utrans_-functions from ICU
9  */
10
11 #if HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #if YAZ_HAVE_ICU
16 #include <yaz/xmalloc.h>
17
18 #include <yaz/icu_I18N.h>
19
20 #include <yaz/log.h>
21
22 #include <assert.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26
27 #include <unicode/utrans.h>
28
29 struct icu_transform
30 {
31     char action;
32     UParseError parse_error;
33     UTransliterator *trans;
34 };
35
36 struct icu_transform *icu_transform_clone(struct icu_transform *old)
37 {
38     struct icu_transform *transform
39         = (struct icu_transform *) xmalloc(sizeof(struct icu_transform));
40     UErrorCode status = U_ZERO_ERROR;
41     assert(old);
42     transform->action = old->action;
43     assert(old->trans);
44     transform->trans = utrans_clone(old->trans, &status);
45     assert(transform->trans);
46     return transform;
47 }
48
49 struct icu_transform *icu_transform_create(const char *id, char action,
50                                            const char *rules,
51                                            UErrorCode *status)
52 {
53     struct icu_buf_utf16 *id16 = icu_buf_utf16_create(0);
54     struct icu_buf_utf16 *rules16 = icu_buf_utf16_create(0);
55
56     struct icu_transform *transform
57         = (struct icu_transform *) xmalloc(sizeof(struct icu_transform));
58
59     transform->action = action;
60     transform->trans = 0;
61
62     if (id)
63         icu_utf16_from_utf8_cstr(id16, id, status);
64
65     if (rules)
66         icu_utf16_from_utf8_cstr(rules16, rules, status);
67
68     switch (transform->action)
69     {
70     case 'f':
71     case 'F':
72         transform->trans
73             = utrans_openU(id16->utf16,
74                            id16->utf16_len,
75                            UTRANS_FORWARD,
76                            rules16->utf16,
77                            rules16->utf16_len,
78                            &transform->parse_error, status);
79         break;
80     case 'r':
81     case 'R':
82         transform->trans
83             = utrans_openU(id16->utf16,
84                            id16->utf16_len,
85                            UTRANS_REVERSE ,
86                            rules16->utf16,
87                            rules16->utf16_len,
88                            &transform->parse_error, status);
89         break;
90     default:
91         *status = U_UNSUPPORTED_ERROR;
92         break;
93     }
94     icu_buf_utf16_destroy(rules16);
95     icu_buf_utf16_destroy(id16);
96
97     if (U_SUCCESS(*status))
98         return transform;
99
100     /* freeing if failed */
101     icu_transform_destroy(transform);
102     return 0;
103 }
104
105 void icu_transform_destroy(struct icu_transform *transform)
106 {
107     if (transform)
108     {
109         if (transform->trans)
110             utrans_close(transform->trans);
111         xfree(transform);
112     }
113 }
114
115 int icu_transform_trans(struct icu_transform *transform,
116                         struct icu_buf_utf16 *dest16,
117                         const struct icu_buf_utf16 *src16,
118                         UErrorCode *status)
119 {
120     if (!transform || !transform->trans
121         || !src16  || !dest16)
122         return 0;
123
124     if (!src16->utf16_len)
125     {           /* guarding for empty source string */
126         icu_buf_utf16_clear(dest16);
127         return 0;
128     }
129
130     if (!icu_buf_utf16_copy(dest16, src16))
131         return 0;
132
133     utrans_transUChars(transform->trans,
134                        dest16->utf16, &(dest16->utf16_len),
135                        dest16->utf16_cap,
136                        0, &(dest16->utf16_len), status);
137
138     if (U_FAILURE(*status))
139         icu_buf_utf16_clear(dest16);
140
141     return dest16->utf16_len;
142 }
143
144
145 #endif /* YAZ_HAVE_ICU */
146
147 /*
148  * Local variables:
149  * c-basic-offset: 4
150  * c-file-style: "Stroustrup"
151  * indent-tabs-mode: nil
152  * End:
153  * vim: shiftwidth=4 tabstop=8 expandtab
154  */
155