Mercurial > libpst
comparison src/vbuf.c @ 151:cda7c812ec01
track character set individually for each mapi element
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sun, 08 Mar 2009 14:35:26 -0700 |
parents | 2189a6b8134e |
children | ab384fed78c5 |
comparison
equal
deleted
inserted
replaced
150:06aa84023b48 | 151:cda7c812ec01 |
---|---|
41 // UTF8 <-> UTF16 <-> ISO8859 Character set conversion functions and (ack) their globals | 41 // UTF8 <-> UTF16 <-> ISO8859 Character set conversion functions and (ack) their globals |
42 | 42 |
43 static int unicode_up = 0; | 43 static int unicode_up = 0; |
44 static iconv_t i16to8; | 44 static iconv_t i16to8; |
45 static const char *target_charset = NULL; | 45 static const char *target_charset = NULL; |
46 static int target_open = 0; | 46 static int target_open_from = 0; |
47 static iconv_t i8totarget; | 47 static int target_open_to = 0; |
48 static iconv_t i8totarget = (iconv_t)-1; | |
49 static iconv_t target2i8 = (iconv_t)-1; | |
48 | 50 |
49 | 51 |
50 void unicode_init() | 52 void unicode_init() |
51 { | 53 { |
52 if (unicode_up) unicode_close(); | 54 if (unicode_up) unicode_close(); |
53 i16to8 = iconv_open("UTF-8", "UTF-16LE"); | 55 i16to8 = iconv_open("utf-8", "utf-16le"); |
54 if (i16to8 == (iconv_t)-1) { | 56 if (i16to8 == (iconv_t)-1) { |
55 fprintf(stderr, "Couldn't open iconv descriptor for UTF-16LE to UTF-8.\n"); | 57 WARN(("Couldn't open iconv descriptor for utf-16le to utf-8.\n")); |
56 exit(1); | 58 exit(1); |
57 } | 59 } |
58 unicode_up = 1; | 60 unicode_up = 1; |
59 } | 61 } |
60 | 62 |
61 | 63 |
62 void unicode_close() | 64 void unicode_close() |
63 { | 65 { |
64 iconv_close(i16to8); | 66 iconv_close(i16to8); |
65 if (target_open) { | 67 if (target_open_from) iconv_close(i8totarget); |
66 iconv_close(i8totarget); | 68 if (target_open_to) iconv_close(target2i8); |
67 free((char *)target_charset); | 69 if (target_charset) free((char *)target_charset); |
68 target_charset = NULL; | 70 target_charset = NULL; |
69 target_open = 0; | 71 target_open_from = 0; |
70 } | 72 target_open_to = 0; |
71 unicode_up = 0; | 73 unicode_up = 0; |
72 } | 74 } |
73 | 75 |
74 | 76 |
75 int utf16_is_terminated(const char *str, int length) | 77 int utf16_is_terminated(const char *str, int length) |
123 } | 125 } |
124 return (icresult) ? (size_t)-1 : 0; | 126 return (icresult) ? (size_t)-1 : 0; |
125 } | 127 } |
126 | 128 |
127 | 129 |
128 size_t vb_utf8to8bit(vbuf *dest, const char *inbuf, int iblen, const char* charset) | 130 static void open_targets(const char* charset); |
131 static void open_targets(const char* charset) | |
132 { | |
133 if (!target_charset || strcasecmp(target_charset, charset)) { | |
134 if (target_open_from) iconv_close(i8totarget); | |
135 if (target_open_to) iconv_close(target2i8); | |
136 if (target_charset) free((char *)target_charset); | |
137 target_charset = strdup(charset); | |
138 target_open_from = 1; | |
139 target_open_to = 1; | |
140 i8totarget = iconv_open(target_charset, "utf-8"); | |
141 if (i8totarget == (iconv_t)-1) { | |
142 target_open_from = 0; | |
143 WARN(("Couldn't open iconv descriptor for utf-8 to %s.\n", target_charset)); | |
144 } | |
145 target2i8 = iconv_open("utf-8", target_charset); | |
146 if (target2i8 == (iconv_t)-1) { | |
147 target_open_to = 0; | |
148 WARN(("Couldn't open iconv descriptor for %s to utf-8.\n", target_charset)); | |
149 } | |
150 } | |
151 } | |
152 | |
153 | |
154 static size_t sbcs_conversion(vbuf *dest, const char *inbuf, int iblen, iconv_t conversion); | |
155 static size_t sbcs_conversion(vbuf *dest, const char *inbuf, int iblen, iconv_t conversion) | |
129 { | 156 { |
130 size_t inbytesleft = iblen; | 157 size_t inbytesleft = iblen; |
131 size_t icresult = (size_t)-1; | 158 size_t icresult = (size_t)-1; |
132 size_t outbytesleft = 0; | 159 size_t outbytesleft = 0; |
133 char *outbuf = NULL; | 160 char *outbuf = NULL; |
134 | 161 |
135 if (!target_charset || strcasecmp(target_charset, charset)) { | 162 vbresize(dest, 2*iblen); |
136 if (target_open) { | |
137 iconv_close(i8totarget); | |
138 free((char *)target_charset); | |
139 } | |
140 target_charset = strdup(charset); | |
141 target_open = 1; | |
142 i8totarget = iconv_open(target_charset, "UTF-8"); | |
143 if (i8totarget == (iconv_t)-1) { | |
144 target_open = 0; | |
145 fprintf(stderr, "Couldn't open iconv descriptor for UTF-8 to %s.\n", target_charset); | |
146 return (size_t)-1; | |
147 } | |
148 } | |
149 | |
150 if (!target_open) return (size_t)-1; // previous failure to open the target | |
151 | |
152 if (2 > dest->blen) vbresize(dest, 2); | |
153 dest->dlen = 0; | 163 dest->dlen = 0; |
154 | 164 |
155 do { | 165 do { |
156 outbytesleft = dest->blen - dest->dlen; | 166 outbytesleft = dest->blen - dest->dlen; |
157 outbuf = dest->b + dest->dlen; | 167 outbuf = dest->b + dest->dlen; |
158 icresult = iconv(i8totarget, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft); | 168 icresult = iconv(conversion, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft); |
159 dest->dlen = outbuf - dest->b; | 169 dest->dlen = outbuf - dest->b; |
160 vbgrow(dest, 20); | 170 if (inbytesleft) vbgrow(dest, 2*inbytesleft); |
161 } while ((size_t)-1 == icresult && E2BIG == errno); | 171 } while ((size_t)-1 == icresult && E2BIG == errno); |
162 | 172 |
163 if (icresult == (size_t)-1) { | 173 if (icresult == (size_t)-1) { |
164 WARN(("iconv failure: %s\n", strerror(errno))); | 174 WARN(("iconv failure: %s\n", strerror(errno))); |
165 unicode_init(); | 175 unicode_init(); |
166 return (size_t)-1; | 176 return (size_t)-1; |
167 } | 177 } |
168 return (icresult) ? (size_t)-1 : 0; | 178 return (icresult) ? (size_t)-1 : 0; |
179 } | |
180 | |
181 | |
182 size_t vb_utf8to8bit(vbuf *dest, const char *inbuf, int iblen, const char* charset) | |
183 { | |
184 open_targets(charset); | |
185 if (!target_open_from) return (size_t)-1; // failure to open the target | |
186 return sbcs_conversion(dest, inbuf, iblen, i8totarget); | |
187 } | |
188 | |
189 | |
190 size_t vb_8bit2utf8(vbuf *dest, const char *inbuf, int iblen, const char* charset) | |
191 { | |
192 open_targets(charset); | |
193 if (!target_open_to) return (size_t)-1; // failure to open the target | |
194 return sbcs_conversion(dest, inbuf, iblen, target2i8); | |
169 } | 195 } |
170 | 196 |
171 | 197 |
172 vbuf *vballoc(size_t len) | 198 vbuf *vballoc(size_t len) |
173 { | 199 { |
222 | 248 |
223 size_t vbavail(vbuf * vb) | 249 size_t vbavail(vbuf * vb) |
224 { | 250 { |
225 return vb->blen - vb->dlen - (size_t)(vb->b - vb->buf); | 251 return vb->blen - vb->dlen - (size_t)(vb->b - vb->buf); |
226 } | 252 } |
227 | |
228 | |
229 //void vbdump( vbuf *vb ) // TODO: to stdout? Yuck | |
230 //{ | |
231 // printf("vb dump-------------\n"); | |
232 // printf("dlen: %d\n", vb->dlen ); | |
233 // printf("blen: %d\n", vb->blen ); | |
234 // printf("b - buf: %d\n", vb->b - vb->buf ); | |
235 // printf("buf:\n"); | |
236 // hexdump( vb->buf, 0, vb->blen, 1 ); | |
237 // printf("b:\n"); | |
238 // hexdump( vb->b, 0, vb->dlen, 1 ); | |
239 // printf("^^^^^^^^^^^^^^^^^^^^\n"); | |
240 //} | |
241 | 253 |
242 | 254 |
243 void vbgrow(struct varbuf *vb, size_t len) // out: vbavail(vb) >= len, data are preserved | 255 void vbgrow(struct varbuf *vb, size_t len) // out: vbavail(vb) >= len, data are preserved |
244 { | 256 { |
245 if (0 == len) | 257 if (0 == len) |