Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "iconv.h"
00023 #include "common.h"
00024 #include "error.h"
00025 #include "config.h"
00026 #include <errno.h>
00027
00028 namespace Barry {
00029
00030
00031
00032
00033 IConvHandle::IConvHandle(const char *fromcode, const char *tocode)
00034 {
00035 m_handle = iconv_open(tocode, fromcode);
00036 if( m_handle == (iconv_t)(-1) ) {
00037 throw ErrnoError(std::string("iconv_open failed: from ") + fromcode + " to " + tocode, errno);
00038 }
00039 }
00040
00041 IConvHandle::IConvHandle(const char *fromcode, const IConverter &ic)
00042 {
00043 m_handle = iconv_open(ic.m_tocode.c_str(), fromcode);
00044 if( m_handle == (iconv_t)(-1) ) {
00045 throw ErrnoError(std::string("iconv_open failed: from ") + fromcode + " to " + ic.m_tocode, errno);
00046 }
00047 }
00048
00049 IConvHandle::IConvHandle(const IConverter &ic, const char *tocode)
00050 {
00051 m_handle = iconv_open(tocode, ic.m_tocode.c_str());
00052 if( m_handle == (iconv_t)(-1) ) {
00053 throw ErrnoError(std::string("iconv_open failed: from ") + ic.m_tocode + " to " + tocode, errno);
00054 }
00055 }
00056
00057 IConvHandle::~IConvHandle()
00058 {
00059 iconv_close(m_handle);
00060 }
00061
00062
00063
00064
00065
00066 IConverter::IConverter(const char *tocode, bool throw_on_conv_err)
00067 : m_from(BLACKBERRY_CHARSET, tocode)
00068 , m_to(tocode, BLACKBERRY_CHARSET)
00069 , m_tocode(tocode)
00070 , m_throw_on_conv_err(throw_on_conv_err)
00071 {
00072 }
00073
00074 IConverter::~IConverter()
00075 {
00076 }
00077
00078 std::string IConverter::Convert(iconv_t cd, const std::string &str) const
00079 {
00080 size_t target = str.size() * 2;
00081 char *out = 0, *outstart = 0;
00082 size_t outbytesleft = 0;
00083 std::string ret;
00084
00085
00086
00087 for( int tries = 0; ; tries++ ) {
00088
00089 const char *in = str.data();
00090 size_t inbytesleft = str.size();
00091 out = outstart = (char*) m_buffer.GetBuffer(target);
00092 outbytesleft = m_buffer.GetBufSize();
00093
00094 iconv(cd, NULL, NULL, NULL, NULL);
00095 size_t status = iconv(cd, (ICONV_CONST char**) &in, &inbytesleft, &out, &outbytesleft);
00096
00097 if( status == (size_t)(-1) ) {
00098 if( errno == E2BIG && tries < 2 ) {
00099 target += inbytesleft * 2;
00100
00101 continue;
00102 }
00103
00104
00105
00106
00107
00108
00109 if( m_throw_on_conv_err ) {
00110 throw ErrnoError("iconv failed", errno);
00111 }
00112 }
00113 else {
00114
00115 break;
00116 }
00117 }
00118
00119
00120 ret.assign(outstart, out - outstart);
00121 return ret;
00122 }
00123
00124 std::string IConverter::FromBB(const std::string &str) const
00125 {
00126 return Convert(m_from.m_handle, str);
00127 }
00128
00129 std::string IConverter::ToBB(const std::string &str) const
00130 {
00131 return Convert(m_to.m_handle, str);
00132 }
00133
00134 std::string IConverter::Convert(const IConvHandle &custom, const std::string &str) const
00135 {
00136 return Convert(custom.m_handle, str);
00137 }
00138
00139 }
00140