Skip to content
This repository has been archived by the owner on Oct 10, 2019. It is now read-only.

Commit

Permalink
Check for iconv() TRANSLIT support
Browse files Browse the repository at this point in the history
Some iconv() implementations don't support transliteration.
When iconv with //TRANSLIT is first attempted and fails,
try again without it, and remember the result.

Fixes #364
  • Loading branch information
kobezda committed Sep 29, 2016
1 parent fcbe4fd commit d41345f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 4 deletions.
1 change: 1 addition & 0 deletions include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class utils {
static bool try_fs_lock(const std::string& lock_file, pid_t & pid);
static void remove_fs_lock(const std::string& lock_file);

static std::string translit(const std::string& tocode, const std::string& fromcode);
static std::string convert_text(const std::string& text, const std::string& tocode, const std::string& fromcode);

static std::string get_command_output(const std::string& cmd);
Expand Down
5 changes: 3 additions & 2 deletions src/stflpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cerrno>

#include <langinfo.h>
#include <utils.h>

namespace newsbeuter {

Expand All @@ -16,7 +17,7 @@ namespace newsbeuter {
*/

stfl::form::form(const std::string& text) : f(0) {
ipool = stfl_ipool_create((std::string(nl_langinfo(CODESET)) + "//TRANSLIT").c_str());
ipool = stfl_ipool_create(utils::translit(std::string(nl_langinfo(CODESET)), "WCHAR_T").c_str());
if (!ipool) {
throw exception(errno);
}
Expand Down Expand Up @@ -82,7 +83,7 @@ static std::mutex quote_mtx;

std::string stfl::quote(const std::string& text) {
std::lock_guard<std::mutex> lock(quote_mtx);
stfl_ipool * ipool = stfl_ipool_create((std::string(nl_langinfo(CODESET)) + "//TRANSLIT").c_str());
stfl_ipool * ipool = stfl_ipool_create(utils::translit(std::string(nl_langinfo(CODESET)), "WCHAR_T").c_str());
std::string retval = stfl_ipool_fromwc(ipool,stfl_quote(stfl_ipool_towc(ipool,text.c_str())));
stfl_ipool_destroy(ipool);
return retval;
Expand Down
44 changes: 42 additions & 2 deletions src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,54 @@ bool utils::try_fs_lock(const std::string& lock_file, pid_t & pid) {
return false;
}

std::string utils::translit(const std::string& tocode, const std::string& fromcode)
{
std::string tlit = "//TRANSLIT";

typedef enum translit_state {
UNKNOWN,
SUPPORTED,
UNSUPPORTED
} translit_state_t;

static translit_state_t state = UNKNOWN;

// TRANSLIT is not needed when converting to unicode encodings
if (tocode == "utf-8" || tocode == "WCHAR_T") return tocode;

if (state == UNKNOWN) {
iconv_t cd = ::iconv_open((tocode + "//TRANSLIT").c_str(), fromcode.c_str());

if (cd == reinterpret_cast<iconv_t>(-1)) {
if (errno == EINVAL) {
iconv_t cd = ::iconv_open(tocode.c_str(), fromcode.c_str());
if (cd != reinterpret_cast<iconv_t>(-1)) {
state = UNSUPPORTED;
} else {
fprintf(stderr, "iconv_open('%s', '%s') failed: %s", tocode.c_str(), fromcode.c_str(), strerror(errno));
abort();
}
} else {
fprintf(stderr, "iconv_open('%s//TRANSLIT', '%s') failed: %s", tocode.c_str(), fromcode.c_str(), strerror(errno));
abort();
}
} else {
state = SUPPORTED;
}

iconv_close(cd);
}

return ((state == SUPPORTED) ? (tocode + tlit) : (tocode));
}

std::string utils::convert_text(const std::string& text, const std::string& tocode, const std::string& fromcode) {
std::string result;

if (strcasecmp(tocode.c_str(), fromcode.c_str())==0)
return text;

iconv_t cd = ::iconv_open((tocode + "//TRANSLIT").c_str(), fromcode.c_str());
iconv_t cd = ::iconv_open(translit(tocode, fromcode).c_str(), fromcode.c_str());

if (cd == reinterpret_cast<iconv_t>(-1))
return result;
Expand Down Expand Up @@ -499,7 +539,7 @@ std::wstring utils::str2wstr(const std::string& str) {

std::string utils::wstr2str(const std::wstring& wstr) {
std::string codeset = nl_langinfo(CODESET);
codeset.append("//TRANSLIT");
codeset = translit(codeset, "WCHAR_T");
struct stfl_ipool * ipool = stfl_ipool_create(codeset.c_str());
std::string result = stfl_ipool_fromwc(ipool, wstr.c_str());
stfl_ipool_destroy(ipool);
Expand Down

0 comments on commit d41345f

Please sign in to comment.