Preparation to use libiconv

master
Unknown 2019-02-23 09:46:31 +01:00
parent 6d958c2274
commit e219fd8896
6 changed files with 72 additions and 70 deletions

View File

@ -29,6 +29,8 @@ set(sources
main.cpp main.cpp
CharEncodingConverter.cpp CharEncodingConverter.cpp
CharEncodingConverter.h CharEncodingConverter.h
CharEncodingConverterIConv.cpp
CharEncodingConverterIConv.h
PaintEngine.h PaintEngine.h
PaintEngine_libgd.cpp PaintEngine_libgd.cpp
PaintEngine_libgd.h PaintEngine_libgd.h

View File

@ -1,37 +1,26 @@
#include "CharEncodingConverter.h"
#include <iostream>
#include "build_config.h" #include "build_config.h"
#include "CharEncodingConverter.h" #include <iostream>
#ifdef _WIN32 #ifdef USE_ICONV
#pragma message ("No standard charset converter defined for WIN32 - disabling conversion")
#else
#include "CharEncodingConverterIConv.h" #include "CharEncodingConverterIConv.h"
#endif #endif
CharEncodingConverter *CharEncodingConverter::createStandardConverter(const std::string to, const std::string from) CharEncodingConverter *CharEncodingConverter::createStandardConverter(const std::string &to, const std::string &from)
{ {
#ifdef _WIN32 #ifdef USE_ICONV
return new CharEncodingConverterDummy(to, from);
#else
#if USE_ICONV
return new CharEncodingConverterIConv(to, from); return new CharEncodingConverterIConv(to, from);
#else #else
return new CharEncodingConverterDummy(to, from); return new CharEncodingConverterDummy(to, from);
#endif
#endif #endif
} }
std::string CharEncodingConverter::getCurrentCharEncoding(void) std::string CharEncodingConverter::getCurrentCharEncoding(void)
{ {
#ifdef _WIN32 #ifdef USE_ICONV
return CharEncodingConverterDummy::getCurrentCharEncoding();
#else
#if USE_ICONV
return CharEncodingConverterIConv::getCurrentCharEncoding(); return CharEncodingConverterIConv::getCurrentCharEncoding();
#else #else
return CharEncodingConverterDummy::getCurrentCharEncoding(); return CharEncodingConverterDummy::getCurrentCharEncoding();
#endif
#endif #endif
} }

View File

@ -1,27 +1,29 @@
#pragma once
#ifndef _CHARENCODINGCONVERTER_H_INCLUDED_
#define _CHARENCODINGCONVERTER_H_INCLUDED_
#include <string> #include <string>
class CharEncodingConverter class CharEncodingConverter
{ {
public: public:
CharEncodingConverter(const std::string to, const std::string from) CharEncodingConverter(const std::string &to, const std::string &from)
: m_toFormat(to), m_fromFormat(from) { : m_toFormat(to), m_fromFormat(from)
if (m_toFormat == "") m_toFormat = getCurrentCharEncoding(); {
if (m_fromFormat == "") m_fromFormat = getCurrentCharEncoding(); if (m_toFormat.empty())
} m_toFormat = getCurrentCharEncoding();
if (m_fromFormat.empty())
m_fromFormat = getCurrentCharEncoding();
}
virtual ~CharEncodingConverter(void) {} virtual ~CharEncodingConverter(void) {}
// Create a converter with an unspecified but suitable backend. // Create a converter with an unspecified but suitable backend.
// (for usage convenience) // (for usage convenience)
static CharEncodingConverter *createStandardConverter(const std::string to, const std::string from = ""); static CharEncodingConverter *createStandardConverter(const std::string &to, const std::string &from = "");
static std::string getCurrentCharEncoding(void); static std::string getCurrentCharEncoding();
virtual std::string convert(const std::string &src) = 0; virtual std::string convert(const std::string &src) = 0;
virtual std::string fromFormat(void) { return m_fromFormat; } virtual std::string fromFormat() { return m_fromFormat; }
virtual std::string toFormat(void) { return m_toFormat; } virtual std::string toFormat() { return m_toFormat; }
protected: protected:
std::string m_toFormat; std::string m_toFormat;
std::string m_fromFormat; std::string m_fromFormat;
@ -30,13 +32,10 @@ protected:
class CharEncodingConverterDummy : public CharEncodingConverter class CharEncodingConverterDummy : public CharEncodingConverter
{ {
public: public:
CharEncodingConverterDummy(const std::string to, const std::string from = "") CharEncodingConverterDummy(const std::string &to, const std::string &from = "")
: CharEncodingConverter(to, from) {} : CharEncodingConverter(to, from) {}
virtual ~CharEncodingConverterDummy(void) {} virtual ~CharEncodingConverterDummy() {}
static std::string getCurrentCharEncoding(void) { return "UTF-8"; } static std::string getCurrentCharEncoding() { return "UTF-8"; }
std::string convert(const std::string &src) override { return src; } std::string convert(const std::string &src) override { return src; }
}; };
#endif // _CHARENCODINGCONVERTER_H_INCLUDED_

View File

@ -1,17 +1,22 @@
#include "CharEncodingConverterIConv.h" #include "CharEncodingConverterIConv.h"
#include <cstring> #ifdef USE_ICONV
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <langinfo.h>
#include <cerrno> #include <cerrno>
#include <cstring>
#include <iostream>
#ifndef _WIN32
#include <langinfo.h>
#endif
#include <sstream>
#include <stdexcept>
#define ICONV_BUFSIZE 16 #define ICONV_BUFSIZE 16
std::string CharEncodingConverterIConv::getCurrentCharEncoding(void) std::string CharEncodingConverterIConv::getCurrentCharEncoding()
{ {
#ifdef _WIN32
return "UTF-8"; // TODO: Get the correct codepage on Windows and convert it to something that iconv can use
#else
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
char *enc = nl_langinfo(CODESET); char *enc = nl_langinfo(CODESET);
std::string encoding; std::string encoding;
@ -31,27 +36,31 @@ std::string CharEncodingConverterIConv::getCurrentCharEncoding(void)
// Alternative: modify conversion to replace unknown chars with '?' manually. // Alternative: modify conversion to replace unknown chars with '?' manually.
setlocale(LC_CTYPE, "C"); setlocale(LC_CTYPE, "C");
return encoding; return encoding;
#endif
} }
CharEncodingConverterIConv::CharEncodingConverterIConv(std::string to, std::string from) CharEncodingConverterIConv::CharEncodingConverterIConv(const std::string &to, const std::string &from)
: CharEncodingConverter(to, from) : CharEncodingConverter(to, from)
{ {
to = m_toFormat + "//TRANSLIT"; std::string toFormat = m_toFormat + "//TRANSLIT";
from = m_fromFormat; std::string fromFormat = m_fromFormat;
m_iconv = iconv_open(to.c_str(), from.c_str()); m_iconv = iconv_open(toFormat.c_str(), fromFormat.c_str());
if (m_iconv == (iconv_t) -1) { if (m_iconv == (iconv_t)-1) {
int rno = errno; int rno = errno;
std::string msg = std::string("Error initializing iconv charset converter (") std::ostringstream oss;
+ (from=="" ? std::string("(default)") : from) + " --> " oss << "Error initializing iconv charset converter ("
+ (to=="" ? std::string("(default)") : to) + "): " + strerror(rno); << (fromFormat.empty() ? "(default)" : from) << " --> "
throw std::runtime_error(msg); << (toFormat.empty() ? "(default)" : toFormat) << "): "
<< strerror(rno) << std::endl;
throw std::runtime_error(oss.str());
} }
} }
CharEncodingConverterIConv::~CharEncodingConverterIConv(void) CharEncodingConverterIConv::~CharEncodingConverterIConv(void)
{ {
if (m_iconv != (iconv_t) -1) if (m_iconv != (iconv_t)-1)
iconv_close(m_iconv); iconv_close(m_iconv);
} }
@ -72,7 +81,7 @@ std::string CharEncodingConverterIConv::convert(const std::string &src)
size_t rv; size_t rv;
do { do {
rv = iconv(m_iconv, &fromBufP, &fromBufLen, &toBufP, &toBufLen); rv = iconv(m_iconv, &fromBufP, &fromBufLen, &toBufP, &toBufLen);
if (rv == (size_t) -1) { if (rv == (size_t)-1) {
int rno = errno; int rno = errno;
if (rno != E2BIG) { if (rno != E2BIG) {
std::ostringstream oss; std::ostringstream oss;
@ -80,19 +89,19 @@ std::string CharEncodingConverterIConv::convert(const std::string &src)
<< fromFormat() << " to " << toFormat() << fromFormat() << " to " << toFormat()
<< " (text: '[" << std::string(src.c_str(), 0, fromBufP - src.c_str()) << "]" << std::string(fromBufP) << "'): " << " (text: '[" << std::string(src.c_str(), 0, fromBufP - src.c_str()) << "]" << std::string(fromBufP) << "'): "
<< strerror(rno); << strerror(rno);
// Note: strerror() can be misleading, e.g. complaining about invalid input // Note: strerror() can be misleading, e.g. complaining about invalid input
// when really the character cannot be represented in the output... // when really the character cannot be represented in the output...
// (but //TRANSLIT avoids (most of?) those kinds of errors...) // (but //TRANSLIT avoids (most of?) those kinds of errors...)
throw std::runtime_error(oss.str()); throw std::runtime_error(oss.str());
} }
} }
dst += std::string(toBuffer, ICONV_BUFSIZE - toBufLen); dst += std::string(toBuffer, ICONV_BUFSIZE - toBufLen);
toBufLen = ICONV_BUFSIZE; toBufLen = ICONV_BUFSIZE;
toBufP = toBuffer; toBufP = toBuffer;
} while (rv == (size_t) -1); } while (rv == (size_t)-1);
iconv(m_iconv, NULL, NULL, NULL, NULL); iconv(m_iconv, NULL, NULL, NULL, NULL);
return dst; return dst;
} }
#endif

View File

@ -1,21 +1,22 @@
#pragma once
#ifndef _CHARENCODINGCONVERTERICONV_H_INCLUDED_
#define _CHARENCODINGCONVERTERICONV_H_INCLUDED_
#include <iconv.h>
#include "CharEncodingConverter.h" #include "CharEncodingConverter.h"
#include "build_config.h"
#ifdef USE_ICONV
#include <iconv.h>
class CharEncodingConverterIConv : public CharEncodingConverter class CharEncodingConverterIConv : public CharEncodingConverter
{ {
public: public:
CharEncodingConverterIConv(std::string to, std::string from = ""); CharEncodingConverterIConv(const std::string &to, const std::string &from = "");
virtual ~CharEncodingConverterIConv(void); virtual ~CharEncodingConverterIConv();
static std::string getCurrentCharEncoding(void); static std::string getCurrentCharEncoding();
std::string convert(const std::string &src) override; std::string convert(const std::string &src) override;
private: private:
iconv_t m_iconv; iconv_t m_iconv;
}; };
#endif
#endif // _CHARENCODINGCONVERTERICONV_H_INCLUDED_

View File

@ -7,3 +7,5 @@
#cmakedefine USE_LEVELDB #cmakedefine USE_LEVELDB
#cmakedefine USE_REDIS #cmakedefine USE_REDIS
#cmakedefine USE_ICONV