mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-22 05:16:21 +00:00
Avoid encoding changes of open streams if possible
Changing the codecvt_facet of a file stream after the file has been opened does not work with clang on OS X. Therefore we avoid it if possible (i. e. the new encoding is the same as the old one).
This commit is contained in:
parent
250b058192
commit
92d0835e14
@ -88,6 +88,7 @@ public:
|
||||
} else
|
||||
out_cd_ = (iconv_t)(-1);
|
||||
}
|
||||
string const & encoding() const { return encoding_; }
|
||||
protected:
|
||||
virtual ~iconv_codecvt_facet()
|
||||
{
|
||||
@ -375,37 +376,51 @@ odocstream & operator<<(odocstream & os, SetEnc e)
|
||||
if (has_facet<iconv_codecvt_facet>(os.rdbuf()->getloc())) {
|
||||
// This stream must be a file stream, since we never imbue
|
||||
// any other stream with a locale having a iconv_codecvt_facet.
|
||||
iconv_codecvt_facet const & facet =
|
||||
use_facet<iconv_codecvt_facet>(os.rdbuf()->getloc());
|
||||
|
||||
// FIXME Changing the codecvt facet of an open file is allowed,
|
||||
// but unsafe for facets that use internal state (see the thread
|
||||
// "iostreams: Does imbue() need to be called before open()?"
|
||||
// in comp.std.c++.
|
||||
// Currently it seems to work with gcc and MSVC, but not with
|
||||
// clang on OS X.
|
||||
// Avoid imbueing with the same encoding again if possible.
|
||||
if (facet.encoding() == e.encoding)
|
||||
return os;
|
||||
|
||||
// Flush the stream so that all pending output is written
|
||||
// with the old encoding.
|
||||
os.flush();
|
||||
|
||||
locale locale(os.rdbuf()->getloc(),
|
||||
new iconv_codecvt_facet(e.encoding, ios_base::out));
|
||||
// FIXME Does changing the codecvt facet of an open file
|
||||
// stream always work? It does with gcc 4.1, but I have read
|
||||
// somewhere that it does not with MSVC.
|
||||
// What does the standard say?
|
||||
os.imbue(locale);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
//CHECKME: I just copied the code above, and have no idea whether it
|
||||
//is correct... (JMarc)
|
||||
idocstream & operator<<(idocstream & is, SetEnc e)
|
||||
{
|
||||
if (has_facet<iconv_codecvt_facet>(is.rdbuf()->getloc())) {
|
||||
// This stream must be a file stream, since we never imbue
|
||||
// any other stream with a locale having a iconv_codecvt_facet.
|
||||
// Flush the stream so that all pending output is written
|
||||
// with the old encoding.
|
||||
//is.flush();
|
||||
iconv_codecvt_facet const & facet =
|
||||
use_facet<iconv_codecvt_facet>(is.rdbuf()->getloc());
|
||||
|
||||
// FIXME Changing the codecvt facet of an open file is allowed,
|
||||
// but unsafe for facets that use internal state (see the thread
|
||||
// "iostreams: Does imbue() need to be called before open()?"
|
||||
// in comp.std.c++.
|
||||
// Currently it seems to work with gcc and MSVC, but not with
|
||||
// clang on OS X.
|
||||
// Avoid imbueing with the same encoding again if possible.
|
||||
if (facet.encoding() == e.encoding)
|
||||
return is;
|
||||
|
||||
locale locale(is.rdbuf()->getloc(),
|
||||
new iconv_codecvt_facet(e.encoding, ios_base::in));
|
||||
// FIXME Does changing the codecvt facet of an open file
|
||||
// stream always work? It does with gcc 4.1, but I have read
|
||||
// somewhere that it does not with MSVC.
|
||||
// What does the standard say?
|
||||
is.imbue(locale);
|
||||
}
|
||||
return is;
|
||||
|
@ -42,6 +42,8 @@ typedef std::basic_ostream<char_type> odocstream;
|
||||
|
||||
/// File stream for reading UTF8-encoded files with automatic conversion to
|
||||
/// UCS4.
|
||||
/// Buffering must be switched off if the encoding is changed after
|
||||
/// construction by calling rdbuf()->pubsetbuf(0, 0).
|
||||
class ifdocstream : public std::basic_ifstream<char_type> {
|
||||
typedef std::basic_ifstream<char_type> base;
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user