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