Happy new year
[yaz-moved-to-github.git] / src / icu_transform.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 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     {
64         icu_utf16_from_utf8_cstr(id16, id, status);
65         id16->utf16[id16->utf16_len] = 0;
66     }
67     if (rules)
68         icu_utf16_from_utf8_cstr(rules16, rules, status);
69
70     switch (transform->action)
71     {
72     case 'f':
73     case 'F':
74         transform->trans
75             = utrans_openU(id16->utf16, 
76                            id16->utf16_len,
77                            UTRANS_FORWARD,
78                            rules16->utf16, 
79                            rules16->utf16_len,
80                            &transform->parse_error, status);
81         break;
82     case 'r':
83     case 'R':
84         transform->trans
85             = utrans_openU(id16->utf16,
86                            id16->utf16_len,
87                            UTRANS_REVERSE ,
88                            rules16->utf16, 
89                            rules16->utf16_len,
90                            &transform->parse_error, status);
91         break;
92     default:
93         *status = U_UNSUPPORTED_ERROR;
94         break;
95     }
96     icu_buf_utf16_destroy(rules16);
97     icu_buf_utf16_destroy(id16);
98     
99     if (U_SUCCESS(*status))
100         return transform;
101
102     /* freeing if failed */
103     icu_transform_destroy(transform);
104     return 0;
105 }
106
107 void icu_transform_destroy(struct icu_transform * transform)
108 {
109     if (transform)
110     {
111         if (transform->trans)
112             utrans_close(transform->trans);
113         xfree(transform);
114     }
115 }
116
117 int icu_transform_trans(struct icu_transform * transform,
118                         struct icu_buf_utf16 * dest16,
119                         const struct icu_buf_utf16 * src16,
120                         UErrorCode *status)
121 {
122     if (!transform || !transform->trans 
123         || !src16  || !dest16)
124         return 0;
125
126     if (!src16->utf16_len)
127     {           /* guarding for empty source string */
128         icu_buf_utf16_clear(dest16);
129         return 0;
130     }
131
132     if (!icu_buf_utf16_copy(dest16, src16))
133         return 0;
134
135     utrans_transUChars (transform->trans, 
136                         dest16->utf16, &(dest16->utf16_len),
137                         dest16->utf16_cap,
138                         0, &(dest16->utf16_len), status);
139
140     if (U_FAILURE(*status))
141         icu_buf_utf16_clear(dest16);
142     
143     return dest16->utf16_len;
144 }
145
146
147 #endif /* YAZ_HAVE_ICU */
148
149 /*
150  * Local variables:
151  * c-basic-offset: 4
152  * c-file-style: "Stroustrup"
153  * indent-tabs-mode: nil
154  * End:
155  * vim: shiftwidth=4 tabstop=8 expandtab
156  */
157