File Coverage

src/xh_encoder.c
Criterion Covered Total %
statement 24 42 57.1
branch 7 16 43.7
condition n/a
subroutine n/a
pod n/a
total 31 58 53.4


line stmt bran cond sub pod time code
1             #include "xh_config.h"
2             #include "xh_core.h"
3              
4             #ifdef XH_HAVE_ENCODER
5              
6             #ifdef XH_HAVE_ICU
7             static void
8             xh_encoder_uconv_destroy(UConverter *uconv)
9             {
10             if (uconv != NULL) {
11             ucnv_close(uconv);
12             }
13             }
14              
15             static UConverter *
16             xh_encoder_uconv_create(xh_char_t *encoding, xh_bool_t toUnicode)
17             {
18             UConverter *uconv;
19             UErrorCode status = U_ZERO_ERROR;
20              
21             uconv = ucnv_open((char *) encoding, &status);
22             if ( U_FAILURE(status) ) {
23             return NULL;
24             }
25              
26             if (toUnicode) {
27             ucnv_setToUCallBack(uconv, UCNV_TO_U_CALLBACK_STOP,
28             NULL, NULL, NULL, &status);
29             }
30             else {
31             ucnv_setFromUCallBack(uconv, UCNV_FROM_U_CALLBACK_STOP,
32             NULL, NULL, NULL, &status);
33             }
34              
35             return uconv;
36             }
37             #endif
38              
39             void
40 41           xh_encoder_destroy(xh_encoder_t *encoder)
41             {
42 41 100         if (encoder != NULL) {
43             #ifdef XH_HAVE_ICONV
44 2 50         if (encoder->iconv != NULL) {
45             xh_log_debug0("destroy iconv encoder");
46 2           iconv_close(encoder->iconv);
47             }
48             #endif
49              
50             #ifdef XH_HAVE_ICU
51             if (encoder->uconv_from != NULL) {
52             xh_log_debug0("destroy icu encoder");
53             xh_encoder_uconv_destroy(encoder->uconv_from);
54             xh_encoder_uconv_destroy(encoder->uconv_to);
55             }
56             #endif
57 2           free(encoder);
58             }
59 41           }
60              
61             xh_encoder_t *
62 2           xh_encoder_create(xh_char_t *tocode, xh_char_t *fromcode)
63             {
64             xh_encoder_t *encoder;
65              
66 2           encoder = malloc(sizeof(xh_encoder_t));
67 2 50         if (encoder == NULL) {
68 0           return NULL;
69             }
70 2           memset(encoder, 0, sizeof(xh_encoder_t));
71              
72 2           xh_str_copy(encoder->tocode, tocode, XH_PARAM_LEN);
73 2           xh_str_copy(encoder->fromcode, fromcode, XH_PARAM_LEN);
74              
75             #ifdef XH_HAVE_ICONV
76             xh_log_debug2("create iconv encoder from: '%s' to: '%s'", fromcode, tocode);
77 2           encoder->iconv = iconv_open((char *) tocode, (char *) fromcode);
78 2 50         if (encoder->iconv != (iconv_t) -1) {
79 2           encoder->type = XH_ENC_ICONV;
80 2           return encoder;
81             }
82 0           encoder->iconv = NULL;
83             #endif
84              
85             #ifdef XH_HAVE_ICU
86             xh_log_debug2("create icu encoder from: '%s' to: '%s'", fromcode, tocode);
87             encoder->uconv_to = xh_encoder_uconv_create(tocode, 1);
88             if (encoder->uconv_to != NULL) {
89             encoder->uconv_from = xh_encoder_uconv_create(fromcode, 0);
90             if (encoder->uconv_from != NULL) {
91             encoder->type = XH_ENC_ICU;
92             encoder->pivotSource = encoder->pivotTarget = encoder->pivotStart = encoder->pivotBuffer;
93             encoder->pivotLimit = encoder->pivotBuffer + sizeof(encoder->pivotBuffer) / sizeof(encoder->pivotBuffer[0]);
94             return encoder;
95             }
96             }
97             #endif
98              
99 0           xh_encoder_destroy(encoder);
100              
101 0           return NULL;
102             }
103              
104             void
105 2           xh_encoder_encode_perl_buffer(xh_encoder_t *encoder, xh_perl_buffer_t *main_buf, xh_perl_buffer_t *enc_buf)
106             {
107 2           xh_char_t *src = main_buf->start;
108              
109             #ifdef XH_HAVE_ICONV
110 2 50         if (encoder->type == XH_ENC_ICONV) {
111 2           size_t in_left = main_buf->cur - main_buf->start;
112 2           size_t out_left = enc_buf->end - enc_buf->cur;
113              
114 2           size_t converted = iconv(encoder->iconv, (char **) &src, &in_left, (char **) &enc_buf->cur, &out_left);
115 2 50         if (converted == (size_t) -1) {
116 0           croak("Encoding error");
117             }
118 2           return;
119             }
120             #endif
121              
122             #ifdef XH_HAVE_ICU
123             UErrorCode err = U_ZERO_ERROR;
124             ucnv_convertEx(encoder->uconv_to, encoder->uconv_from, (char **) &enc_buf->cur, (char *) enc_buf->end,
125             (const char **) &src, (char *) main_buf->cur, NULL, NULL, NULL, NULL,
126             FALSE, TRUE, &err);
127              
128             if ( U_FAILURE(err) ) {
129             croak("Encoding error: %d", err);
130             }
131             #endif
132             }
133              
134             void
135 0           xh_encoder_encode_string(xh_encoder_t *encoder, xh_char_t **src, size_t *src_left, xh_char_t **dst, size_t *dst_left)
136             {
137             #ifdef XH_HAVE_ICONV
138 0 0         if (encoder->type == XH_ENC_ICONV) {
139 0           size_t converted = iconv(encoder->iconv, (char **) src, src_left, (char **) dst, dst_left);
140 0 0         if (converted == (size_t) -1) {
141 0           switch (errno) {
142             case EILSEQ:
143 0           croak("Encoding error: invalid char found");
144             case E2BIG:
145 0           encoder->state = XH_ENC_BUFFER_OVERFLOW;
146 0           break;
147             case EINVAL:
148 0           encoder->state = XH_ENC_TRUNCATED_CHAR_FOUND;
149 0           break;
150             default:
151 0           croak("Encoding error");
152             }
153             }
154             else {
155 0           encoder->state = XH_ENC_OK;
156             }
157 0           return;
158             }
159             #endif
160              
161             #ifdef XH_HAVE_ICU
162             UErrorCode err = U_ZERO_ERROR;
163             xh_char_t *old_src = *src;
164             xh_char_t *old_dst = *dst;
165              
166             ucnv_convertEx(encoder->uconv_to, encoder->uconv_from, (char **) dst, (char *) (*dst + *dst_left),
167             (const char **) src, (char *) (*src + *src_left), encoder->pivotStart, &encoder->pivotSource, &encoder->pivotTarget, encoder->pivotLimit,
168             FALSE, FALSE, &err);
169              
170             *src_left -= *src - old_src;
171             *dst_left -= *dst - old_dst;
172              
173             if ( U_FAILURE(err) ) {
174             switch (err) {
175             case U_INVALID_CHAR_FOUND:
176             croak("Encoding error: invalid char found");
177             case U_BUFFER_OVERFLOW_ERROR:
178             encoder->state = XH_ENC_BUFFER_OVERFLOW;
179             break;
180             case U_TRUNCATED_CHAR_FOUND:
181             encoder->state = XH_ENC_TRUNCATED_CHAR_FOUND;
182             break;
183             default:
184             croak("Encoding error: %d", err);
185             }
186             }
187             else {
188             encoder->state = XH_ENC_OK;
189             }
190             #endif
191             }
192              
193             #endif /* XH_HAVE_ENCODER */