std::string decode_to_ascii(char* input, const size_t& input_len)
{
iconv_t cb = iconv_open("ASCII//IGNORE", "UTF-8");
if (cb == (iconv_t)(-1))
{
return "";
}
char* out = new char[input_len];
size_t in_l = input_len;
size_t out_l = input_len;
size_t cvtlen = iconv(cb, &input, &in_l, &out, &out_l);
if (cvtlen == (size_t)(-1))
{
auto err = errno;
return "";
}
std::string result(out);
iconv_close(cb);
return result;
}
iconv всегда выдает ошибку EILSEQ с указанием на последний символ, что не так?
входной буфер гарантированно имеет кодировку УТФ-8, строка корректно кодируется другими средствами и корректно отображается в текстовом редакторе, если её сохранить в файл.
//IGNORE или //TRANSLIT не дают эффекта, пробовал совать туда 1 двухбайтовый символ, эффекта нет
Замечено, что на одних и тех же входных данных iconv выдает различный результат...
Ошибка EILSEQ означает невалидные символы во входном буфере, однако при использовании с "ASCII//IGNORE" эта ошибка будет возвращаться в случае, если некоторые символы были отброшены. При этом указатель на входную строку будет указывать на проблемный байт - сразу за пределом входной строки. Таким образом, можно разделить ситуации, когда невалидная последовательность реально была во входной строке, и когда какие-то символы были отброшены. Также не следует передавать оригинальный указатель на выходной буфер (после вызовы функции он будет указывать на байт сразу после записанных) и не следует передавать оригинальный указатель на выходной буфер в функции, ожидающие заканчивающуюся нулем строку:
char * p_in{input};
size_t out_l{input_len};
char * p_out{out};
size_t out_l{input_len};
errno = 0;
size_t const cvtlen{iconv(cb, &p_in, &in_l, &p_out, &out_l)};
if (cvtlen == (size_t)(-1))
{
auto const err{errno};
if((EILSEQ != errno) || (p_in != (input + input_len)))
{
return "";
}
}
std::string result(out, static_cast<::std::size_t>(p_out - out));
Сборка персонального компьютера от Artline: умный выбор для современных пользователей