Changeset View
Changeset View
Standalone View
Standalone View
source/third_party/tinygettext/src/iconv.cpp
Show All 26 Lines | |||||
#include <string.h> | #include <string.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include "tinygettext/iconv.hpp" | #include "tinygettext/iconv.hpp" | ||||
#include "tinygettext/log_stream.hpp" | #include "tinygettext/log_stream.hpp" | ||||
namespace tinygettext { | namespace tinygettext { | ||||
#ifndef tinygettext_ICONV_CONST | |||||
# define tinygettext_ICONV_CONST | |||||
#endif | |||||
IConv::IConv() | IConv::IConv() | ||||
: to_charset(), | : to_charset(), | ||||
from_charset(), | from_charset(), | ||||
cd(0) | cd(nullptr) | ||||
{} | {} | ||||
IConv::IConv(const std::string& from_charset_, const std::string& to_charset_) | IConv::IConv(const std::string& from_charset_, const std::string& to_charset_) | ||||
: to_charset(), | : to_charset(), | ||||
from_charset(), | from_charset(), | ||||
cd(0) | cd(nullptr) | ||||
{ | { | ||||
set_charsets(from_charset_, to_charset_); | set_charsets(from_charset_, to_charset_); | ||||
} | } | ||||
IConv::~IConv() | IConv::~IConv() | ||||
{ | { | ||||
if (cd) | if (cd) | ||||
tinygettext_iconv_close(cd); | iconv_close(cd); | ||||
} | } | ||||
void | void | ||||
IConv::set_charsets(const std::string& from_charset_, const std::string& to_charset_) | IConv::set_charsets(const std::string& from_charset_, const std::string& to_charset_) | ||||
{ | { | ||||
if (cd) | if (cd) | ||||
tinygettext_iconv_close(cd); | iconv_close(cd); | ||||
from_charset = from_charset_; | from_charset = from_charset_; | ||||
to_charset = to_charset_; | to_charset = to_charset_; | ||||
for(std::string::iterator i = to_charset.begin(); i != to_charset.end(); ++i) | for(std::string::iterator i = to_charset.begin(); i != to_charset.end(); ++i) | ||||
*i = static_cast<char>(toupper(*i)); | *i = static_cast<char>(toupper(*i)); | ||||
for(std::string::iterator i = from_charset.begin(); i != from_charset.end(); ++i) | for(std::string::iterator i = from_charset.begin(); i != from_charset.end(); ++i) | ||||
*i = static_cast<char>(toupper(*i)); | *i = static_cast<char>(toupper(*i)); | ||||
if (to_charset == from_charset) | if (to_charset == from_charset) | ||||
{ | { | ||||
cd = 0; | cd = nullptr; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
cd = tinygettext_iconv_open(to_charset.c_str(), from_charset.c_str()); | cd = iconv_open(to_charset.c_str(), from_charset.c_str()); | ||||
if (cd == reinterpret_cast<tinygettext_iconv_t>(-1)) | if (cd == reinterpret_cast<iconv_t>(-1)) | ||||
{ | { | ||||
if(errno == EINVAL) | if(errno == EINVAL) | ||||
{ | { | ||||
std::ostringstream str; | std::ostringstream str; | ||||
str << "IConv construction failed: conversion from '" << from_charset | str << "IConv construction failed: conversion from '" << from_charset | ||||
<< "' to '" << to_charset << "' not available"; | << "' to '" << to_charset << "' not available"; | ||||
throw std::runtime_error(str.str()); | throw std::runtime_error(str.str()); | ||||
} | } | ||||
Show All 17 Lines | IConv::convert(const std::string& text) | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
size_t inbytesleft = text.size(); | size_t inbytesleft = text.size(); | ||||
size_t outbytesleft = 4*inbytesleft; // Worst case scenario: ASCII -> UTF-32? | size_t outbytesleft = 4*inbytesleft; // Worst case scenario: ASCII -> UTF-32? | ||||
// We try to avoid to much copying around, so we write directly into | // We try to avoid to much copying around, so we write directly into | ||||
// a std::string | // a std::string | ||||
tinygettext_ICONV_CONST char* inbuf = const_cast<char*>(&text[0]); | const char* inbuf = &text[0]; | ||||
std::string result(outbytesleft, 'X'); | std::string result(outbytesleft, 'X'); | ||||
char* outbuf = &result[0]; | char* outbuf = &result[0]; | ||||
// Try to convert the text. | // Try to convert the text. | ||||
size_t ret = tinygettext_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); | size_t ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); | ||||
if (ret == static_cast<size_t>(-1)) | if (ret == static_cast<size_t>(-1)) | ||||
{ | { | ||||
if (errno == EILSEQ || errno == EINVAL) | if (errno == EILSEQ || errno == EINVAL) | ||||
{ // invalid multibyte sequence | { // invalid multibyte sequence | ||||
tinygettext_iconv(cd, NULL, NULL, NULL, NULL); // reset state | iconv(cd, nullptr, nullptr, nullptr, nullptr); // reset state | ||||
// FIXME: Could try to skip the invalid byte and continue | // FIXME: Could try to skip the invalid byte and continue | ||||
log_error << "error: tinygettext:iconv: invalid multibyte sequence in: \"" << text << "\"" << std::endl; | log_error << "error: tinygettext:iconv: invalid multibyte sequence in: \"" << text << "\"" << std::endl; | ||||
} | } | ||||
else if (errno == E2BIG) | else if (errno == E2BIG) | ||||
{ // output buffer to small | { // output buffer to small | ||||
assert(false && "tinygettext/iconv.cpp: E2BIG: This should never be reached"); | assert(false && "tinygettext/iconv.cpp: E2BIG: This should never be reached"); | ||||
} | } | ||||
Show All 19 Lines |
Wildfire Games · Phabricator