3 /// iconv wrapper class, and pluggable interface for records
7 Copyright (C) 2008, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
29 IConverter::IConverter(const char *tocode
, bool throw_on_conv_err
)
30 : m_throw_on_conv_err(throw_on_conv_err
)
32 m_from
= iconv_open(tocode
, BLACKBERRY_CHARSET
);
33 if( m_from
== (iconv_t
)(-1) ) {
34 throw ErrnoError("iconv_open failed (from)", errno
);
37 m_to
= iconv_open(BLACKBERRY_CHARSET
, tocode
);
38 if( m_to
== (iconv_t
)(-1) ) {
39 ErrnoError
err("iconv_open failed (to)", errno
);
45 IConverter::~IConverter()
51 std::string
IConverter::Convert(iconv_t cd
, const std::string
&str
) const
53 size_t target
= str
.size() * 2;
54 char *out
= 0, *outstart
= 0;
55 size_t outbytesleft
= 0;
58 // this loop is for the very odd case that the output string
59 // needs more than twice the input size
60 for( int tries
= 0; ; tries
++ ) {
62 const char *in
= str
.data();
63 size_t inbytesleft
= str
.size();
64 out
= outstart
= (char*) m_buffer
.GetBuffer(target
);
65 outbytesleft
= m_buffer
.GetBufSize();
67 iconv(cd
, NULL
, NULL
, NULL
, NULL
); // reset cd's state
68 size_t status
= iconv(cd
, (char**)&in
, &inbytesleft
, &out
, &outbytesleft
);
70 if( status
== (size_t)(-1) ) {
71 if( errno
== E2BIG
&& tries
< 2 ) {
72 target
+= inbytesleft
* 2;
73 // try again with more memory...
77 // should never happen :-)
78 // but if it does, and we get here, check
79 // whether the user wants to be notified by
80 // exception... if not, just fall through and
81 // store as much converted data as possible
82 if( m_throw_on_conv_err
) {
83 throw ErrnoError("iconv failed", errno
);
92 // store any available converted data
93 ret
.assign(outstart
, out
- outstart
);
97 std::string
IConverter::FromBB(const std::string
&str
) const
99 return Convert(m_from
, str
);
102 std::string
IConverter::ToBB(const std::string
&str
) const
104 return Convert(m_to
, str
);