3 /// iconv wrapper class, and pluggable interface for records
7 Copyright (C) 2008-2010, 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.
30 //////////////////////////////////////////////////////////////////////////////
33 IConvHandle::IConvHandle(const char *fromcode
, const char *tocode
)
35 m_handle
= iconv_open(tocode
, fromcode
);
36 if( m_handle
== (iconv_t
)(-1) ) {
37 throw ErrnoError(std::string("iconv_open failed: from ") + fromcode
+ " to " + tocode
, errno
);
41 IConvHandle::IConvHandle(const char *fromcode
, const IConverter
&ic
)
43 m_handle
= iconv_open(ic
.m_tocode
.c_str(), fromcode
);
44 if( m_handle
== (iconv_t
)(-1) ) {
45 throw ErrnoError(std::string("iconv_open failed: from ") + fromcode
+ " to " + ic
.m_tocode
, errno
);
49 IConvHandle::IConvHandle(const IConverter
&ic
, const char *tocode
)
51 m_handle
= iconv_open(tocode
, ic
.m_tocode
.c_str());
52 if( m_handle
== (iconv_t
)(-1) ) {
53 throw ErrnoError(std::string("iconv_open failed: from ") + ic
.m_tocode
+ " to " + tocode
, errno
);
57 IConvHandle::~IConvHandle()
59 iconv_close(m_handle
);
63 //////////////////////////////////////////////////////////////////////////////
66 IConverter::IConverter(const char *tocode
, bool throw_on_conv_err
)
67 : m_from(BLACKBERRY_CHARSET
, tocode
)
68 , m_to(tocode
, BLACKBERRY_CHARSET
)
70 , m_throw_on_conv_err(throw_on_conv_err
)
74 IConverter::~IConverter()
78 std::string
IConverter::Convert(iconv_t cd
, const std::string
&str
) const
80 size_t target
= str
.size() * 2;
81 char *out
= 0, *outstart
= 0;
82 size_t outbytesleft
= 0;
85 // this loop is for the very odd case that the output string
86 // needs more than twice the input size
87 for( int tries
= 0; ; tries
++ ) {
89 const char *in
= str
.data();
90 size_t inbytesleft
= str
.size();
91 out
= outstart
= (char*) m_buffer
.GetBuffer(target
);
92 outbytesleft
= m_buffer
.GetBufSize();
94 iconv(cd
, NULL
, NULL
, NULL
, NULL
); // reset cd's state
95 size_t status
= iconv(cd
, (ICONV_CONST
char**) &in
, &inbytesleft
, &out
, &outbytesleft
);
97 if( status
== (size_t)(-1) ) {
98 if( errno
== E2BIG
&& tries
< 2 ) {
99 target
+= inbytesleft
* 2;
100 // try again with more memory...
104 // should never happen :-)
105 // but if it does, and we get here, check
106 // whether the user wants to be notified by
107 // exception... if not, just fall through and
108 // store as much converted data as possible
109 if( m_throw_on_conv_err
) {
110 throw ErrnoError("iconv failed", errno
);
119 // store any available converted data
120 ret
.assign(outstart
, out
- outstart
);
124 std::string
IConverter::FromBB(const std::string
&str
) const
126 return Convert(m_from
.m_handle
, str
);
129 std::string
IConverter::ToBB(const std::string
&str
) const
131 return Convert(m_to
.m_handle
, str
);
134 std::string
IConverter::Convert(const IConvHandle
&custom
, const std::string
&str
) const
136 return Convert(custom
.m_handle
, str
);