Hi,
I have some problem with locales on FreeBSD 6.3. The attached test case fails with uncaught std::runtime_error exception:

shell::wilx:~/tmp> locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_ALL=

shell::wilx:~/tmp> ./codecvt_test "abcdŠ<"
terminate called after throwing an instance of 'std::runtime_error'
  what():  locale::facet::_S_create_c_locale name not valid
zsh: abort (core dumped)  ./codecvt_test "abcdŠ<"

shell::wilx:~/tmp> locale -a |grep en_US.UTF-8
en_US.UTF-8

I don't understand why? It works without change on both Windows and Gentoo/Linux.

--
VH
// codecvt_test.cpp : Defines the entry point for the console application.
//

#include <string>
#include <locale>
#include <cwctype>
#include <iostream>
#include <vector>
#include <cassert>


std::wstring
towstring(const std::string& src)
{
    std::wstring outstr;

    typedef std::codecvt<wchar_t, char, std::mbstate_t> CodeCvt;
    std::locale loc ("");
    const CodeCvt & cdcvt = std::use_facet<CodeCvt>(loc);
    std::mbstate_t state = {0};

    char const * const from_first = src.c_str ();
    size_t const from_size = src.size ();
    char const * const from_last = from_first + from_size;
    char const * from_next = from_first;

    // XXX: Intentionally allocate only half the size of the input.
    std::vector<wchar_t> dest (from_size / 2);

    wchar_t * to_first = &dest.front ();
    size_t to_size = dest.size ();
    wchar_t * to_last = to_first + to_size;
    wchar_t * to_next = to_first;

    CodeCvt::result result;
    size_t converted = 0;
    while (true)
    {
        result = cdcvt.in (
            state, from_first, from_last,
            from_next, to_first, to_last,
            to_next);
        if ((result == CodeCvt::partial || result == CodeCvt::ok) 
            && from_next != from_last)
        {
            to_size = dest.size () * 2;
            dest.resize (to_size);
            converted = to_next - to_first;
            to_first = &dest.front ();
            to_last = to_first + to_size;
            to_next = to_first + converted;
            continue;
        } 
        else if (result == CodeCvt::ok && from_next == from_last)
            break;
        else
        {
            assert (0);
            break;
        }
    }
    converted = to_next - to_first;

    outstr.assign (dest.begin (), dest.begin () + converted);
    return outstr;
}

int main (int argc, char * argv[])
{
    if (argc < 2)
    {
        std::cerr << "codecvt_test string\n";
        return 1;
    }

    std::string str (argv[1]);
    std::wstring wstr = towstring (str);
    std::wcout << std::hex;
    for (std::wstring::const_iterator it = wstr.begin (); it != wstr.end ();
        ++it)
        std::wcout << static_cast<unsigned>(*it) << " ";
    std::wcout << "\n";

    std::wcout.imbue (std::locale (""));
    std::wcout << wstr << std::endl;
        return 0;
}

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to