reporting of errors in codecvt through istream
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi!
Suppose while doing std::getline on an ifstream the codecvt is invoked
an returns error from its in function. On various platforms the getline
behaves as if eof was reached. I expected the stream to set its fail or
badbit. Now I wonder how one shall detect conversion errors while
reading a file? How can I distinguish conversion errors from eof?
Frank
#include <ostream>
#include <iostream>
#include <fstream>
#include <locale>
#include <string>
#include <cassert>
bool first = true;
class error_codecvt
: public std::codecvt <wchar_t , char , mbstate_t>
{
public:
explicit error_codecvt(size_t r =0u)
: std::codecvt <wchar_t , char , mbstate_t>(r)
{}
protected:
virtual result do_in(state_type&,
const extern_type*,
const extern_type*,
const extern_type*&,
intern_type* putAreaFirst,
intern_type* putAreaLast,
intern_type*& putAreaCurrent) const
{
if(first) {
first=false;
assert(putAreaFirst != putAreaLast);
putAreaCurrent = putAreaFirst;
*putAreaCurrent++ = 'c';
}
std::wcerr << "conversion failed\n";
return std::codecvt_base::error;
}
virtual result do_out(state_type&,
const intern_type*,
const intern_type*,
const intern_type*&,
extern_type*,
extern_type*,
extern_type*&) const
{
return std::codecvt_base::error;
}
virtual result do_unshift(state_type&,
extern_type* const to,
extern_type*,
extern_type*& to_next) const
{
to_next = to;
return noconv;
}
virtual int do_length(const state_type&,
const extern_type* const from,
const extern_type* const end,
size_t const mx) const
{
return static_cast<int>((mx < (size_t)(end - from)) ? mx : end - from);
}
virtual bool do_always_noconv() const throw()
{ return false; }
virtual int do_max_length() const throw()
{ return 2; }
virtual int do_encoding() const throw()
{ return 2; }
};
std::locale createLocale()
{
return std::locale(std::locale::classic(), new error_codecvt);
}
int run(char const* const filename)
{
std::wifstream file;
file.imbue(createLocale());
file.open(filename);
if(!file)
{
std::wcerr << "could not open file " << filename << '\n';
return -2;
}
std::wstring line;
std::getline(file, line); // will not fail, but read to eof
std::wcout << line << '\n';
std::wcout.flush();
if(file.bad()) std::wcerr << "file is bad\n";
if(file.fail()) std::wcerr << "file failed\n";
if(file.eof()) std::wcerr << "file at eof\n";
if(file.good()) std::wcerr << "file is good\n";
return file.fail() ? 0 : 1;
}
int main(int argc, char* argv[])
{
if(argc<2)
{
std::wcerr << "no filename given\n";
return -1;
}
const int result = run(argv[1]);
if(result < 0) std::wcerr << "Test had an error\n";
if(result > 0) std::wcerr << "Test discovered a failure\n";
if(result == 0) std::wcerr << "Test passed\n";
return result;
}
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.12 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk6VN1wACgkQhAOUmAZhnmq1GQCggFNPvnaglW3zupr/7nTpqcut
Jb8AnA8aQ5+WET+iR/aGJUbnlfBCr62M
=fH63
-----END PGP SIGNATURE-----
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]