From: dietmar_kuehl@this.is.invalid   
      
   { Please limit your text to fit within 80 columns, preferably around 70,   
    so that readers don't have to scroll horizontally to read each line.   
    This article has been reformatted manually by the moderator. -mod }   
      
      
   On Wednesday, April 2, 2014 1:16:07 AM UTC+1, Jim Michaels wrote:   
   > typedef std::vector Vu16S;   
   >   
   > namespace std { //should go to iosfwd along with u32 versions   
   >   
   > typedef std::basic_streambuf >   
   > u16streambuf;   
   > typedef std::basic_stringbuf >   
   > u16stringbuf;   
   > typedef std::basic_ostringstream >   
   > u16ostringstream;   
   > typedef std::basic_ostream >   
   > u16ostream;   
   > }   
      
   Note that *this* is the easy stuff which won't really get you anywhere at   
   all! Fine you got a couple of types but that's not the interesting bit.   
      
   The moment you try to use any of stream operations these will try to use   
   various facets, e.g., std::ctype, std::numpunct,   
   std::num_put, std::num_get, etc. None of these   
   facets is required to have a useful implementation of any of the   
   character types other than char and wchar_t. ... and some of these   
   facets won't have default implementations.   
      
   Even if all facets have a default implementation, the std::locale is   
   likely not to contain a suitable instance. Without these facets in the   
   std::locale object, you won't get operational streams off the ground.   
   Setting all that up is certainly doable but it isn't entirely trivial.   
   I recall that I wrote all the steps needed to put together a std::locale   
   to provide usable IOStreams for a new character type (including the code   
   needed). Don't know where, though, and it is, at least, 10 years ago   
   (probably more). Roughly you need   
      
   - a suitable specialization of std::char_traits   
    (that is required to exist, actually)   
   - the moment you try to use formatted I/O you'll need   
    std::ctype. It isn't hard to implement but probably   
    doesn't have a default implementation.   
   - when you attempt to use numeric formatting, you'll need   
    std::numpunct. This facet probably doesn't have a   
    default implementation but is fairly straight forward to implement.   
   - you should get an operational default implementation of   
    std::num_put needed when formatting numeric values.   
    It won't be present in the std::locale by default.   
   - similar, you should get a default implementation of   
    std::num_get needed to parse numeric values.   
    It won't be present in the std::locale by default   
   - it seems std::codecvt actually has   
    an implementation and is part of the default std::locale. It is needed   
    if you try to use file streams to convert between the character type   
    (char16_t) and bytes (char). You may be able to use that to interact   
    with the standard stream objects (see below).   
      
   > Vu16S vu16blockss={u"\u00a0",u"\u2591",u"\u2592",u"\u2593",u"\u2588"};   
   >   
   > int main(void) {   
   > std::u16streambuf* sbf;   
   > std::u16stringbuf strbuf;   
   > std::u16ostringstream u16ograph(std::ios_base::out);   
   > std::u16ostream u16cout(sbf);   
   > //u16cout.rdbuf(std::cout::rdbuf());//error   
      
   Clearly that doesn't work: the character types are entirely different   
   and don't have anything to do with each other. Given that there is no   
   guarantee at all what encoding the standard stream objects (std::cout,   
   std::cin, std::cerr, and std::clog and their wchar_t counterparts) use,   
   it is quite questionable if you can use the standard stream objects to   
   send characters (assuming you want to deal with characters outside the   
   ASCII range)! You can only use them because you know their encoding   
   (e.g., because they use UTF-8 or no encoding, i.e., std::codecvt::always_noconv() is true for the corresponding   
   code conversion facet; well, that might not even help as there is no   
   requirement that they even use this facet) which is clearly non-portable.   
      
   To use the standard stream objects, you'd probably create a converting   
   stream buffer which internally uses the corresponding standard stream   
   object and use std::codecvt to convert   
   the characters into bytes and std::codecvt   
   to convert the bytes into narrow characters (i.e., characters of type   
   char) which are then filled into the standard stream object (the   
   conversion back to narrow characters actually assumes that the narrow   
   "characters" really are bytes). Well, that's for output. For input you'd   
   go the other way.   
      
   It may be easier to create a stream buffer directly interacting with the   
   underlying standard stream facilities, e.g., on UNIX-like systems with   
   the file descriptors 0 (for input), 1 (for output), and 2 (for error).   
   At least, that is predictable and wouldn't use any further encoding,   
   i.e., you'd down to only converting from char16_t to bytes. I recall   
   discussions in the committee about creating a converting stream buffer   
   as std::basic_filebuf pretty much uses that anyway and it would be   
   fairly easy to expose that conversion while it is fairly hard to   
   implement (efficiently; well, it isn't trivial to implement without   
   paying attention to efficiency already). However, I don't think that   
   was proposed and, thus, didn't emerge.   
      
   > //uostringstream o16graph;   
   > u16ograph< u16cout< u16cout< return 0;   
   > }   
   >   
   > I get no output. I was told I could expect this. but I don't know   
   > a workaround without modifying the STL.   
      
   There is no need to modify the standard library to create a working set   
   of streams for a suitable character type. ... and modifying the standard   
   library wouldn't get you far anyway as you'd need to pretty much do work   
   above as part of the modification. Not to mention, that the IOStreams   
   and locales parts don't need to sit in headers and you may not even have   
   the sources (or sufficient privileges allowing you to change them). The   
   only part which can't be done in a portable fashion is creating standard   
   stream objects but that is sort of expected: who knows where that input   
   is coming from and where it is going to! You may get away writing suitably   
   encoded bytes there but it also may not work and in either case you'll   
      
   [continued in next message]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|