1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
#include <iconv.h>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include "CharsetConverter.h"
using namespace std;
using namespace htmlcxx;
CharsetConverter::CharsetConverter(const string &from, const string &to)
{
mIconvDescriptor = iconv_open(to.c_str(), from.c_str());
if (mIconvDescriptor == (iconv_t)(-1))
{
const char *error_str = strerror(errno);
int size = strlen(error_str) + from.length() + to.length() + 26;
char error[size];
snprintf(error, size, "Can't convert from %s to %s: %s", from.c_str(), to.c_str(), error_str);
throw Exception(error);
}
}
CharsetConverter::~CharsetConverter()
{
iconv_close(mIconvDescriptor);
}
string CharsetConverter::convert(const string &input)
{
const char *inbuf = input.c_str();
size_t inbytesleft = input.length();
size_t outbuf_len = 2 * input.length();
char *outbuf_start = new char[outbuf_len];
char *outbuf = outbuf_start;
size_t outbytesleft = outbuf_len;
size_t ret;
while (1) {
ret = iconv(mIconvDescriptor, const_cast<char**>(&inbuf), &inbytesleft, &outbuf, &outbytesleft);
if (ret == 0) break;
if (ret == (size_t)-1 && errno == E2BIG) return string();
// fprintf(stderr, "invalid byte: %d\n", inbuf - input.c_str());
inbuf++; inbytesleft--;
}
string out(outbuf_start, outbuf_len - outbytesleft);
delete [] outbuf_start;
return out;
}
|