I'm writing my own codecvt but can't find out when (or if) cout is calling codecvt.unshift().
I've vacuum cleaned the net and also tried to Google www.open-std.org without any result.
Is there anyone that knows where to find documentation whether cout is using codecvt.unshift() or if I can leave that method unimplemented in my custom codecvt?
On 7 Nov, 15:21, DeMarcus <use_my_alias_h...@hotmail.com> wrote:
> I'm writing my own codecvt but can't find out when (or if) cout is > calling codecvt.unshift().
Unsurprising, there isn't any response so far. So let me give a quick one: the C++ standard doesn't require 'std::cout' to be implemented in terms of 'std::filebuf'. 'std::filebuf' (or, to be more precise, the class template 'std::basic_filbuf') is the only class which makes use of the facet 'std::codecvt'. Hence, whether 'std::cout' uses 'std::codecvt' or not is already up in the air and I can see reasonable implementations either way with some bias of implementing the standard stream objects using specialized stream buffers (at least, this is the way I did it).
That said, you need to understand what the 'unshift()' does and when it used to determine whether you'll need to implement a non-default behavior for it. The purpose of 'unshift()' is to return the stream to some sort of initial shift state. This can mean multiple things but typically it inserts a set of bytes which undo any kind of earlier change setting the byte stream up to interpret bytes different than in the initial state. For example, in an encoding the initial state may represent Latin characters and a shift state may shift the interpretation to use German characters instead. The current state would be stored in some form in the 'mbstate_t' and 'unshift()' would produce whatever byte sequence is needed to return the interpretation of bytes back to Latin characters. This function is essentially used in two situations:
1. When seeking on a stream, the current shift state is undone before actually seeking (and seeking into a byte sequence after the bytes moving it into a shift state is likely to cause havoc to the byte's interpretation). 2. When terminating a stream the shift state is undone to cleanly terminate the sequence.
> Is there anyone that knows where to find documentation whether cout is > using codecvt.unshift() or if I can leave that method unimplemented in > my custom codecvt?
The answer to this question is as above: I know that 'std::cout' is not required to use 'std::codecvt' at all and hence isn't required to use 'unshift()' at all. What this means for the standard C++ library implementation you are using, nobody but the implementer of this particular library can tell.
>> I'm writing my own codecvt but can't find out when (or if) cout is >> calling codecvt.unshift().
> Unsurprising, there isn't any response so far. So let me give a quick > one: the C++ standard doesn't require 'std::cout' to be implemented in > terms of 'std::filebuf'. 'std::filebuf' (or, to be more precise, the > class template 'std::basic_filbuf') is the only class which makes use > of the facet 'std::codecvt'. Hence, whether 'std::cout' uses > 'std::codecvt' or not is already up in the air and I can see > reasonable implementations either way with some bias of implementing > the standard stream objects using specialized stream buffers (at > least, this is the way I did it).
That doesn't sound too comfortable. May I just double check? If I write code like this:
std::ios::sync_with_stdio( false );
std::locale myLocale( std::locale::classic(), new MyCodeCvt() ); std::cout.imbue( myLocale );
then does this still mean I cannot be sure MyCodeCvt will be used??
If the answer is; I still cannot be sure, then what's the simplest solution? Is it to implement my own cout built on std::filebuf?
> >> I'm writing my own codecvt but can't find out when (or if) cout is > >> calling codecvt.unshift().
> > Unsurprising, there isn't any response so far. So let me give a quick > > one: the C++ standard doesn't require 'std::cout' to be implemented in > > terms of 'std::filebuf'. 'std::filebuf' (or, to be more precise, the > > class template 'std::basic_filbuf') is the only class which makes use > > of the facet 'std::codecvt'. Hence, whether 'std::cout' uses > > 'std::codecvt' or not is already up in the air and I can see > > reasonable implementations either way with some bias of implementing > > the standard stream objects using specialized stream buffers (at > > least, this is the way I did it).
> That doesn't sound too comfortable. May I just double check? If I write > code like this:
> then does this still mean I cannot be sure MyCodeCvt will be used??
Yes, this accurate: there is no guarantee that 'std::cout' uses a 'std::filebuf'. It may or it may not. It may use your code conversion facet or it may not.
> If the answer is; I still cannot be sure, then what's the simplest > solution? Is it to implement my own cout built on std::filebuf?
If you want to create a 'std::filebuf' which writes to the same destination as 'std::cout' you will need to resort to platform specific approaches. ... and even this can be interesting! For example, if the 'std::filebuf' class doesn't have a constructor taking a file descriptor and you are actually writing to pipe on a UNIX system, you are pretty much out of luck. Once you have a 'std::streambuf' writing to the same destination as 'std::cout' you can redirect 'std::cout' to write to this stream buffer instead. Even this isn't entirely trivial, however, as you will either need to make sure that your stream buffer lives long enough or the stream buffer used originally by 'std::cout' is restored. A simple but non-portable approach which may work could look like this:
std::cout.rdbuf(new std::filebuf(1));
This would cause one file buffer not being reclaimed at the end of the program but should otherwise work - assuming '1' is the file descriptor referring to the standard output destination and 'std::filebuf' has a non-standard constructor.