Merge branch 'debian'
[hcoop/debian/courier-authlib.git] / libs / unicode / unicodecpp.C
CommitLineData
b0322a85
CE
1/*
2** Copyright 2011 Double Precision, Inc.
3** See COPYING for distribution information.
4**
5*/
6
7#include "unicode_config.h"
8#include "unicode.h"
9
10extern "C" {
11
12 static int iconv_trampoline(const char *str, size_t cnt, void *arg)
13 {
14 return reinterpret_cast<mail::iconvert *>(arg)
15 ->converted(str, cnt);
16 }
17
18 int mail::linebreak_trampoline(int value, void *ptr)
19 {
20 return (*reinterpret_cast<mail::linebreak_callback_base *>
21 (ptr))(value);
22 }
23
24 int mail::linebreakc_trampoline(int value, unicode_char ch, void *ptr)
25 {
26 return (*reinterpret_cast<mail::linebreakc_callback_base *>
27 (ptr))(value, ch);
28 }
29
30 int mail::wordbreak_trampoline(int value, void *ptr)
31 {
32 return (*reinterpret_cast<mail::wordbreak_callback_base *>
33 (ptr))(value != 0);
34 }
35
36}
37
38size_t unicode_wcwidth(const std::vector<unicode_char> &uc)
39{
40 size_t w=0;
41
42 for (std::vector<unicode_char>::const_iterator
43 b(uc.begin()), e(uc.end()); b != e; ++b)
44 w += unicode_wcwidth(*b);
45 return w;
46}
47
48mail::iconvert::iconvert() : handle(NULL)
49{
50}
51
52mail::iconvert::~iconvert()
53{
54 end();
55}
56
57int mail::iconvert::converted(const char *, size_t)
58{
59 return 0;
60}
61
62bool mail::iconvert::begin(const std::string &src_chset,
63 const std::string &dst_chset)
64{
65 end();
66
67 if ((handle=libmail_u_convert_init(src_chset.c_str(),
68 dst_chset.c_str(),
69 &iconv_trampoline,
70 this)) == NULL)
71 return false;
72 return true;
73}
74
75bool mail::iconvert::end(bool *errflag)
76{
77 int errptr;
78
79 int rc;
80
81 if (!handle)
82 return true;
83
84 rc=libmail_u_convert_deinit(handle, &errptr);
85 handle=NULL;
86
87 if (errflag)
88 *errflag=errptr != 0;
89 return rc == 0;
90}
91
92bool mail::iconvert::operator()(const char *str, size_t cnt)
93{
94 if (!handle)
95 return false;
96
97 return (libmail_u_convert(handle, str, cnt) == 0);
98}
99
100bool mail::iconvert::operator()(const unicode_char *str, size_t cnt)
101{
102 if (!handle)
103 return false;
104
105 return (libmail_u_convert_uc(handle, str, cnt) == 0);
106}
107
108std::string mail::iconvert::convert(const std::string &text,
109 const std::string &charset,
110 const std::string &dstcharset,
111 bool &errflag)
112{
113 std::string buf;
114 int errptr;
115
116 char *p=libmail_u_convert_tobuf(text.c_str(),
117 charset.c_str(),
118 dstcharset.c_str(),
119 &errptr);
120
121 errflag= errptr != 0;
122
123 try {
124 buf=p;
125 free(p);
126 } catch (...) {
127 free(p);
128 throw;
129 }
130
131 return buf;
132}
133
134
135std::string mail::iconvert::convert(const std::vector<unicode_char> &uc,
136 const std::string &dstcharset,
137 bool &errflag)
138{
139 std::string buf;
140
141 char *c;
142 size_t csize;
143 int err;
144
145 if (libmail_u_convert_fromu_tobuf(&uc[0], uc.size(),
146 dstcharset.c_str(), &c, &csize,
147 &err))
148 {
149 err=1;
150 }
151 else
152 {
153 if (csize)
154 --csize; // Trailing NULL
155 try {
156 buf.append(c, c+csize);
157 free(c);
158 } catch (...)
159 {
160 free(c);
161 throw;
162 }
163 }
164
165 errflag= err != 0;
166
167 return buf;
168}
169
170bool mail::iconvert::convert(const std::string &text,
171 const std::string &charset,
172 std::vector<unicode_char> &uc)
173{
174 int err;
175
176 unicode_char *ucbuf;
177 size_t ucsize;
178
179 if (libmail_u_convert_tou_tobuf(text.c_str(),
180 text.size(),
181 charset.c_str(),
182 &ucbuf,
183 &ucsize,
184 &err))
185 return false;
186
187 try {
188 uc.clear();
189 uc.reserve(ucsize);
190 uc.insert(uc.end(), ucbuf, ucbuf+ucsize);
191 free(ucbuf);
192 } catch (...)
193 {
194 free(ucbuf);
195 throw;
196 }
197
198 return err == 0;
199}
200
201int mail::iconvert::tou::converted(const unicode_char *, size_t)
202{
203 return 0;
204}
205
206bool mail::iconvert::tou::begin(const std::string &chset)
207{
208 return iconvert::begin(chset, libmail_u_ucs4_native);
209}
210
211int mail::iconvert::tou::converted(const char *ptr, size_t cnt)
212{
213 return converted(reinterpret_cast<const unicode_char *>(ptr),
214 cnt/sizeof(unicode_char));
215}
216
217void mail::iconvert::tou::convert(const std::string &str,
218 const std::string &chset,
219 std::vector<unicode_char> &out_buf)
220{
221 convert(str.begin(), str.end(), chset, out_buf);
222}
223
224bool mail::iconvert::fromu::begin(const std::string &chset)
225{
226 return iconvert::begin(libmail_u_ucs4_native, chset);
227}
228
229std::string mail::iconvert::fromu::convert(const std::vector<unicode_char>
230 &ubuf,
231 const std::string &chset)
232{
233 std::string s;
234
235 convert(ubuf, chset, s);
236 return s;
237}
238
239void mail::iconvert::fromu::convert(const std::vector<unicode_char> &ubuf,
240 const std::string &chset,
241 std::string &out_buf)
242{
243 convert(ubuf.begin(), ubuf.end(), chset, out_buf);
244}
245
246std::string mail::iconvert::convert_tocase(const std::string &text,
247 const std::string &charset,
248 bool &err,
249 unicode_char (*first_char_func)(unicode_char),
250 unicode_char (*char_func)(unicode_char))
251{
252 err=false;
253 std::string s;
254
255 char *p=libmail_u_convert_tocase(text.c_str(),
256 charset.c_str(),
257 first_char_func,
258 char_func);
259
260 if (!p)
261 {
262 err=true;
263 return s;
264 }
265
266 try {
267 s=p;
268 free(p);
269 } catch (...) {
270 free(p);
271 throw;
272 }
273 return s;
274}
275
276mail::linebreak_callback_base::linebreak_callback_base()
277 : handle(NULL), opts(0)
278{
279}
280
281
282void mail::linebreak_callback_base::set_opts(int optsArg)
283{
284 opts=optsArg;
285
286 if (handle)
287 unicode_lb_set_opts(handle, opts);
288}
289
290mail::linebreak_callback_base::~linebreak_callback_base()
291{
292 finish();
293}
294
295int mail::linebreak_callback_base::operator()(int)
296{
297 return 0;
298}
299
300mail::linebreak_callback_base
301&mail::linebreak_callback_base::operator<<(unicode_char uc)
302{
303 if (!handle)
304 {
305 handle=unicode_lb_init(linebreak_trampoline,
306 reinterpret_cast<void *>
307 (static_cast<linebreak_callback_base *>
308 (this)));
309 set_opts(opts);
310 }
311
312 if (handle)
313 if (unicode_lb_next(handle, uc))
314 finish();
315 return *this;
316}
317
318void mail::linebreak_callback_base::finish()
319{
320 if (handle)
321 unicode_lb_end(handle);
322 handle=NULL;
323}
324
325
326mail::linebreak_callback_save_buf::linebreak_callback_save_buf()
327{
328}
329
330mail::linebreak_callback_save_buf::~linebreak_callback_save_buf()
331{
332}
333
334int mail::linebreak_callback_save_buf::operator()(int value)
335{
336 lb_buf.push_back(value);
337 return 0;
338}
339
340mail::linebreakc_callback_base::linebreakc_callback_base()
341 : handle(NULL), opts(0)
342{
343}
344
345mail::linebreakc_callback_base::~linebreakc_callback_base()
346{
347 finish();
348}
349
350int mail::linebreakc_callback_base::operator()(int, unicode_char)
351{
352 return 0;
353}
354
355void mail::linebreakc_callback_base::set_opts(int optsArg)
356{
357 opts=optsArg;
358
359 if (handle)
360 unicode_lbc_set_opts(handle, opts);
361}
362
363mail::linebreakc_callback_base
364&mail::linebreakc_callback_base::operator<<(unicode_char uc)
365{
366 if (handle == NULL)
367 {
368 handle=unicode_lbc_init(linebreakc_trampoline,
369 reinterpret_cast<void *>
370 (static_cast<linebreakc_callback_base *>
371 (this)));
372 set_opts(opts);
373 }
374
375 if (handle)
376 if (unicode_lbc_next(handle, uc))
377 finish();
378 return *this;
379}
380
381void mail::linebreakc_callback_base::finish()
382{
383 if (handle)
384 unicode_lbc_end(handle);
385 handle=NULL;
386}
387
388
389mail::linebreakc_callback_save_buf::linebreakc_callback_save_buf()
390{
391}
392
393mail::linebreakc_callback_save_buf::~linebreakc_callback_save_buf()
394{
395}
396
397int mail::linebreakc_callback_save_buf::operator()(int c, unicode_char ch)
398{
399 lb_buf.push_back(std::make_pair(c, ch));
400 return 0;
401}
402
403mail::wordbreak_callback_base::wordbreak_callback_base()
404 : handle(NULL)
405{
406}
407
408mail::wordbreak_callback_base::~wordbreak_callback_base()
409{
410 finish();
411}
412
413int mail::wordbreak_callback_base::operator()(bool)
414{
415 return 0;
416}
417
418mail::wordbreak_callback_base
419&mail::wordbreak_callback_base::operator<<(unicode_char uc)
420{
421 if (!handle)
422 {
423 handle=unicode_wb_init(wordbreak_trampoline,
424 reinterpret_cast<void *>
425 (static_cast<wordbreak_callback_base *>
426 (this)));
427 }
428
429 if (handle)
430 if (unicode_wb_next(handle, uc))
431 finish();
432 return *this;
433}
434
435void mail::wordbreak_callback_base::finish()
436{
437 if (handle)
438 unicode_wb_end(handle);
439 handle=NULL;
440}
441
442/* -------------------------------------------- */
443
444mail::wordbreakscan::wordbreakscan() : handle(NULL)
445{
446}
447
448mail::wordbreakscan::~wordbreakscan()
449{
450 finish();
451}
452
453bool mail::wordbreakscan::operator<<(unicode_char uc)
454{
455 if (!handle)
456 handle=unicode_wbscan_init();
457
458 if (handle)
459 return unicode_wbscan_next(handle, uc) != 0;
460
461 return false;
462}
463
464size_t mail::wordbreakscan::finish()
465{
466 size_t n=0;
467
468 if (handle)
469 {
470 n=unicode_wbscan_end(handle);
471 handle=NULL;
472 }
473 return n;
474}