Lars Gullik Bjønnes wrote:
Angus Leeming <[EMAIL PROTECTED]> writes:

| In fact, when I look at your code, why don't you make iconv_convert a
| template and return a vector of the correct type directly. All that's
| needed is a change to the last couple of lines of iconv_convert where
| you fill outvec:
| | int const bytes = 1000 - outbytesleft;
|       std::size_t length_outvec = bytes * sizeof(char) / sizeof(T);
|       ASSERT(length_outvec * sizeof(T) / sizeof(char) == bytes);
| | std::vector<T> outvec(length_outvec);
|       std::memcpy(&outvec[0], out, bytes);
|       return outvec;
| | I think that the only assumption is that "ucs-4-internal" is a valid
| flag to pass to iconv itself and that iconv will then do the right
| thing when filling the char* buffer.
| | What do I miss?

converting to utf-8.

Sorry, don't follow.

std::vector<char>
ucs4_to_utf8(std::vector<boost::uint32_t> const & ucs4str)
{
        // ucs4str has a machine-specific byte order, but that
        // doesn't actually matter because *we* generated it in
        // the first place, passing "UCS-4-INTERNAL" to iconv.
        std::vector<char> in(ucs4str.size() * 4);
        std::memcpy(&in[0], &ucs4str[0], ucs4str.size() * 4);
        return iconv_convert<char>("UTF-8", "UCS-4-INTERNAL", in);
}


std::vector<boost::uint32_t>
utf8_to_ucs4(std::vector<char> const & utf8str)
{
        return iconv_convert<boost::uint32_t>(
                "UCS-4-INTERNAL", "UTF-8", utf8str);
}


template <typename T>
std::vector<T>
iconv_convert(
        std::string const & tocode,
        std::string const & fromcode,
        std::vector const & indata)
{
        char outdata[1000] = { 0 };
        int const bytes = icon_fill_buffer(
                tocode, fromcode, indata, outdata);

        // conversion failed.
        if (bytes == 0)
                return std::vector<T>();

        std::size_t length_outvec = bytes * sizeof(char) / sizeof(T);
        ASSERT(length_outvec * sizeof(T) / sizeof(char) == bytes);

        std::vector<T> outvec(length_outvec);
        std::memcpy(&outvec[0], outdata, bytes);
        return outvec;
}


template <char>
std::vector<char>
iconv_convert(
        std::string const & tocode,
        std::string const & fromcode,
        std::vector const & indata)
{
        // specialize the copying to outvec for char.
        // No need for anything more complicated that the
        // existing code at the tail of the existing iconv_convert.
        ...
}


// returns the number of bytes converted.
// (0 if conversion failed.)
int iconv_fill_buffer(
        std::string const & tocode,
        std::string const & fromcode,
        std::vector const & indata,
        char* outdata)
{
        // The existing iconv_convert goes here.
        // Just move out the final copying of outdata
        // to vector<char>.
        ...
}



Reply via email to