1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2 
3 #include "ef_big5_conv.h"
4 
5 #include <string.h> /* strncmp */
6 #include <pobl/bl_mem.h>
7 #include <pobl/bl_debug.h>
8 #include <pobl/bl_locale.h>
9 
10 #include "ef_zh_tw_map.h"
11 #include "ef_zh_hk_map.h"
12 
13 /* --- static functions --- */
14 
remap_unsupported_charset(ef_char_t * ch)15 static void remap_unsupported_charset(ef_char_t *ch) {
16   ef_char_t c;
17 
18   if (ch->cs == ISO10646_UCS4_1) {
19     char *locale;
20 
21     locale = bl_get_locale();
22 
23     if (strncmp(locale, "zh_HK", 5) == 0) {
24       if (!ef_map_ucs4_to_zh_hk(&c, ch)) {
25         return;
26       }
27     } else {
28       if (!ef_map_ucs4_to_zh_tw(&c, ch)) {
29         return;
30       }
31     }
32 
33     *ch = c;
34   }
35 
36   if (ch->cs == CNS11643_1992_1) {
37     if (ef_map_cns11643_1992_1_to_big5(&c, ch)) {
38       *ch = c;
39     }
40   } else if (ch->cs == CNS11643_1992_2) {
41     if (ef_map_cns11643_1992_2_to_big5(&c, ch)) {
42       *ch = c;
43     }
44   }
45 }
46 
convert_to_big5(ef_conv_t * conv,u_char * dst,size_t dst_size,ef_parser_t * parser)47 static size_t convert_to_big5(ef_conv_t *conv, u_char *dst, size_t dst_size,
48                               ef_parser_t *parser) {
49   size_t filled_size;
50   ef_char_t ch;
51 
52   filled_size = 0;
53   while (ef_parser_next_char(parser, &ch)) {
54     remap_unsupported_charset(&ch);
55 
56     if (ch.cs == BIG5 || ch.cs == HKSCS) {
57       if (filled_size + 1 >= dst_size) {
58         ef_parser_full_reset(parser);
59 
60         return filled_size;
61       }
62 
63       *(dst++) = ch.ch[0];
64       *(dst++) = ch.ch[1];
65 
66       filled_size += 2;
67     } else if (ch.cs == US_ASCII) {
68       if (filled_size >= dst_size) {
69         ef_parser_full_reset(parser);
70 
71         return filled_size;
72       }
73 
74       *(dst++) = ch.ch[0];
75 
76       filled_size++;
77     } else if (conv->illegal_char) {
78       size_t size;
79       int is_full;
80 
81       size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch);
82       if (is_full) {
83         ef_parser_full_reset(parser);
84 
85         return filled_size;
86       }
87 
88       dst += size;
89       filled_size += size;
90     }
91   }
92 
93   return filled_size;
94 }
95 
conv_init(ef_conv_t * conv)96 static void conv_init(ef_conv_t *conv) {}
97 
conv_destroy(ef_conv_t * conv)98 static void conv_destroy(ef_conv_t *conv) { free(conv); }
99 
100 /* --- global functions --- */
101 
ef_big5_conv_new(void)102 ef_conv_t *ef_big5_conv_new(void) {
103   ef_conv_t *conv;
104 
105   if ((conv = malloc(sizeof(ef_conv_t))) == NULL) {
106     return NULL;
107   }
108 
109   conv->convert = convert_to_big5;
110   conv->init = conv_init;
111   conv->destroy = conv_destroy;
112   conv->illegal_char = NULL;
113 
114   return conv;
115 }
116 
ef_big5hkscs_conv_new(void)117 ef_conv_t *ef_big5hkscs_conv_new(void) {
118   ef_conv_t *conv;
119 
120   if ((conv = malloc(sizeof(ef_conv_t))) == NULL) {
121     return NULL;
122   }
123 
124   conv->convert = convert_to_big5;
125   conv->init = conv_init;
126   conv->destroy = conv_destroy;
127   conv->illegal_char = NULL;
128 
129   return conv;
130 }
131