[Fedora-i18n-list] iconv help required

Mustafa Jamil mustafa_jamil at yahoo.com
Fri Sep 8 19:09:01 UTC 2006


Hey.

I'm trying to write a simple C++ string converter that
takes ISO-8859-1-encoded strings and converts them to
UTF8-encoded strings.

Unfortunately, iconv is dying with EILSEQ, and I don't
know why.  I'd appreciate any ideas you may have.

Here's my test program (you can run it with 'g++
main.cpp; ./a.out'):

-- START --
#include <string>
#include <vector>
#include <iostream>
#include "errno.h"

using namespace std;

struct i18nError {
        i18nError(const std::string &m) : message(m) {
        }
        const std::string message;
};

std::string
ConvertString(const std::string& input,
                const std::string& from,
                const std::string& to)
{
        cout << "DEBUG: Input string = " << input <<
endl;
        size_t input_bytes_to_read = input.size();
//returns the byte size
        cout << "DEBUG: input_bytes_to_read = " <<
input_bytes_to_read << endl;
        char *input_pointer = (char *)input.c_str();
//cast away the const

        size_t output_buffer_size =
(input_bytes_to_read * 4) + 1;
        cout << "DEBUG: output_buffer_size = " <<
output_buffer_size << endl;
        size_t output_bytes_left = output_buffer_size;
        std::vector<char>
output_buffer(output_bytes_left);
        char *output_buffer_pointer =
&output_buffer[0];

        iconv_t cd = iconv_open(from.c_str(),
to.c_str());
        if (cd == (iconv_t) -1) {
                // Could not get suitable conversion
descriptor
                if (errno == EINVAL) {
                        throw i18nError("Conversion
from " + from + " to " + to + " is not available");
                } else {
                        throw i18nError("iconv_open
failed");
                }
        }

        size_t nconv = iconv(cd, 
                        &input_pointer,
&input_bytes_to_read,
                        &output_buffer_pointer,
&output_bytes_left);
        if (nconv == (size_t) -1) {
                std::string msg = "iconv failed, errno
= ";
                if (errno == E2BIG) {
                        msg += "E2BIG";
                } else if (errno == EILSEQ) {
                        msg += "EILSEQ";
                } else if (errno == EINVAL) {
                        msg += "EINVAL";
                } else {
                        msg += "Unknown";
                }
                throw i18nError(msg);
        }

        if (iconv_close(cd) != 0) {
                throw i18nError("iconv_close failed");
        }
        cout << "DEBUG: input_bytes_to_read = " <<
input_bytes_to_read << endl;
        cout << "DEBUG: nconv = " << nconv << endl;

        cout << "DEBUG: output_bytes_left = " <<
output_bytes_left << endl;
        size_t output_bytes_written =
output_buffer_size - output_bytes_left;
        cout << "DEBUG: output_bytes_written = " <<
output_bytes_written 
                << endl;
        if (output_bytes_written < output_buffer_size)
{
                *output_buffer_pointer = '\0'; //
explicitly null-terminate
        }

        std::string retVal = 
                std::string(&output_buffer[0],
output_buffer.size());
        cout << "DEBUG: Output string = " << retVal <<
endl;
        cout << "DEBUG: Output string size = " <<
retVal.size() << endl;
        return (retVal);
}

main() 
{
        try {
                cout <<
"------------------------------------" << endl;
                std::string bar = ConvertString("Hello
world", "ISO-8859-1", "UTF8");
                cout <<
"------------------------------------" << endl;
                std::string baz =
ConvertString("\xA2", "ISO-8859-1", "UTF8");
                cout <<
"------------------------------------" << endl;
        } catch (i18nError e) {
                cout << e.message << endl;
        }
}
-- END --

And here's the output:

------------------------------------
DEBUG: Input string = Hello world
DEBUG: input_bytes_to_read = 11
DEBUG: output_buffer_size = 45
DEBUG: input_bytes_to_read = 0
DEBUG: nconv = 0
DEBUG: output_bytes_left = 34
DEBUG: output_bytes_written = 11
DEBUG: Output string = Hello world
DEBUG: Output string size = 45
------------------------------------
DEBUG: Input string = �
DEBUG: input_bytes_to_read = 1
DEBUG: output_buffer_size = 5
iconv failed, errno = EILSEQ

I'd appreciate any help you can offer.

Thanks!

Mustafa

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 




More information about the Fedora-i18n-list mailing list