lib: show offset and rectype in HexDumpParser
[barry.git] / src / iconv.cc
blobbd0f59b288f2422c569cb9a0f26ba787d2110be2
1 ///
2 /// \file iconv.cc
3 /// iconv wrapper class, and pluggable interface for records
4 ///
6 /*
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.
22 #include "iconv.h"
23 #include "common.h"
24 #include "error.h"
25 #include "config.h"
26 #include <errno.h>
28 namespace Barry {
30 //////////////////////////////////////////////////////////////////////////////
31 // IConvHandle class
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 //////////////////////////////////////////////////////////////////////////////
64 // IConvHandle class
66 IConverter::IConverter(const char *tocode, bool throw_on_conv_err)
67 : m_from(BLACKBERRY_CHARSET, tocode)
68 , m_to(tocode, BLACKBERRY_CHARSET)
69 , m_tocode(tocode)
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;
83 std::string ret;
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...
101 continue;
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);
113 else {
114 // success
115 break;
119 // store any available converted data
120 ret.assign(outstart, out - outstart);
121 return ret;
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);
139 } // namespace Barry