* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
*
* Full author contact details are available in file CREDITS.
*
#include <config.h>
-#include "unicode.h"
-
-#include "debug.h"
+#include "support/unicode.h"
+#include "support/debug.h"
#include <iconv.h>
#include <cerrno>
#include <iomanip>
+#include <ostream>
#include <map>
+#include <string>
-using std::endl;
-using std::map;
-using std::make_pair;
-using std::string;
-using std::vector;
+using namespace std;
namespace {
static const iconv_t invalid_cd = (iconv_t)(-1);
-struct IconvProcessor::Private {
- Private(): cd(invalid_cd) {}
- ~Private()
+struct IconvProcessor::Impl
+{
+ Impl(string const & to, string const & from)
+ : cd(invalid_cd), tocode_(to), fromcode_(from)
+ {}
+
+ ~Impl()
{
- if (cd != invalid_cd) {
- if (iconv_close(cd) == -1) {
- lyxerr << "Error returned from iconv_close("
- << errno << ")" << endl;
- }
- }
+ if (cd != invalid_cd && iconv_close(cd) == -1)
+ LYXERR0("Error returned from iconv_close(" << errno << ")");
}
+
iconv_t cd;
+ string tocode_;
+ string fromcode_;
};
-IconvProcessor::IconvProcessor(char const * tocode,
- char const * fromcode): tocode_(tocode), fromcode_(fromcode),
- pimpl_(new IconvProcessor::Private)
+IconvProcessor::IconvProcessor(char const * tocode, char const * fromcode)
+ : pimpl_(new IconvProcessor::Impl(tocode, fromcode))
{
}
IconvProcessor::IconvProcessor(IconvProcessor const & other)
- : tocode_(other.tocode_), fromcode_(other.fromcode_),
- pimpl_(new IconvProcessor::Private)
+ : pimpl_(new IconvProcessor::Impl(other.pimpl_->tocode_, other.pimpl_->fromcode_))
{
}
-IconvProcessor & IconvProcessor::operator=(IconvProcessor const & other)
+IconvProcessor::~IconvProcessor()
{
- if (&other == this)
- return *this;
- tocode_ = other.tocode_;
- fromcode_ = other.fromcode_;
- pimpl_.reset(new Private);
- return *this;
+ delete pimpl_;
}
-IconvProcessor::~IconvProcessor() {}
+void IconvProcessor::operator=(IconvProcessor const & other)
+{
+ if (&other != this)
+ pimpl_ = new Impl(other.pimpl_->tocode_, other.pimpl_->fromcode_);
+}
bool IconvProcessor::init()
if (pimpl_->cd != invalid_cd)
return true;
- pimpl_->cd = iconv_open(tocode_.c_str(), fromcode_.c_str());
+ pimpl_->cd = iconv_open(pimpl_->tocode_.c_str(), pimpl_->fromcode_.c_str());
if (pimpl_->cd != invalid_cd)
return true;
lyxerr << "Error returned from iconv_open" << endl;
switch (errno) {
case EINVAL:
- lyxerr << "EINVAL The conversion from " << fromcode_
- << " to " << tocode_
+ lyxerr << "EINVAL The conversion from " << pimpl_->fromcode_
+ << " to " << pimpl_->tocode_
<< " is not supported by the implementation."
<< endl;
break;
int res = iconv(pimpl_->cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
- //lyxerr << std::dec;
+ // flush out remaining data. This is needed because iconv sometimes
+ // holds back chars in the stream, waiting for a combination character
+ // (see e.g. http://sources.redhat.com/bugzilla/show_bug.cgi?id=1124)
+ iconv(pimpl_->cd, NULL, NULL, &outbuf, &outbytesleft);
+
+ //lyxerr << dec;
//lyxerr << "Inbytesleft: " << inbytesleft << endl;
//lyxerr << "Outbytesleft: " << outbytesleft << endl;
case EILSEQ:
lyxerr << "EILSEQ An invalid multibyte sequence"
<< " has been encountered in the input.\n"
- << "When converting from " << fromcode_
- << " to " << tocode_ << ".\n";
- lyxerr << "Input:" << std::hex;
+ << "When converting from " << pimpl_->fromcode_
+ << " to " << pimpl_->tocode_ << ".\n";
+ lyxerr << "Input:" << hex;
for (size_t i = 0; i < buflen; ++i) {
// char may be signed, avoid output of
// something like 0xffffffc2
boost::uint32_t const b =
*reinterpret_cast<unsigned char const *>(buf + i);
- lyxerr << " 0x" << b;
+ lyxerr << " 0x" << (unsigned int)b;
}
- lyxerr << std::dec << endl;
+ lyxerr << dec << endl;
break;
case EINVAL:
lyxerr << "EINVAL An incomplete multibyte sequence"
<< " has been encountered in the input.\n"
- << "When converting from " << fromcode_
- << " to " << tocode_ << ".\n";
- lyxerr << "Input:" << std::hex;
+ << "When converting from " << pimpl_->fromcode_
+ << " to " << pimpl_->tocode_ << ".\n";
+ lyxerr << "Input:" << hex;
for (size_t i = 0; i < buflen; ++i) {
// char may be signed, avoid output of
// something like 0xffffffc2
boost::uint32_t const b =
*reinterpret_cast<unsigned char const *>(buf + i);
- lyxerr << " 0x" << b;
+ lyxerr << " 0x" << (unsigned int)b;
}
- lyxerr << std::dec << endl;
+ lyxerr << dec << endl;
break;
default:
lyxerr << "\tSome other error: " << errno << endl;
template<typename RetType, typename InType>
vector<RetType>
-iconv_convert(IconvProcessor & processor,
- InType const * buf,
- size_t buflen)
+iconv_convert(IconvProcessor & processor, InType const * buf, size_t buflen)
{
if (buflen == 0)
return vector<RetType>();