[RFC] A stream buffer for wcin

Pétur Runólfsson peturr02@ru.is
Sun Feb 16 17:52:00 GMT 2003


Hi,

It is currently possible to mix use of cin with use of stdin. Should
this also apply to wcin? That is, should the following work?

	wint_t c = wcin.rdbuf()->sgetc();
	assert(c == getwchar());
	ungetwc(0x20ac, stdin);
	assert(wcin.rdbuf()->sgetc() == 0x20ac);
	assert(wcin.rdbuf()->sbumpc() == 0x20ac);
	getwchar();
	wcin.rdbuf()->sputbackc(0x800);
	assert(getwchar() == 0x800);

It seems clear that if this is supposed to work, then
* wcin calls should succeed if fwide(stdin, 0) > 0, and should not
  set fwide(stdin, -1)
* wcin and stdin need to share a conversion state
I don't see how either of these can hold if wfilebuf is used as the
stream buffer for wcin (at least not without something like libio).

Here is a streambuf that I think gives the expected behaviour for
wcin (at least the above example works)

class wcinbuf : public std::wstreambuf
{
protected:
  virtual int_type underflow();
  virtual int_type uflow();
  virtual std::streamsize xsgetn(char_type* s, std::streamsize n);
  virtual int_type pbackfail(int_type c = traits_type::eof());
};

wcinbuf::int_type
wcinbuf::underflow()
{
  int_type c = std::getwchar();
  if (c == WEOF || std::ungetwc(c, stdin) == WEOF)
    return WEOF;
  return c;
}

wcinbuf::int_type
wcinbuf::uflow()
{
  return getwchar();
}

std::streamsize
wcinbuf::xsgetn(char_type* s, std::streamsize n)
{
  std::streamsize ret = 0;
  for (; ret < n; ++ret)
    {
      int_type c = getwchar();
      if (c == WEOF)
	break;
      s[ret] = traits_type::to_char_type(c);
    }
  return ret;
}

wcinbuf::int_type
wcinbuf::pbackfail(int_type c)
{
  if (c == WEOF)
    return WEOF;
  return ungetwc(c, stdin);
}

Does this make sense?
Is anybody else working on wcin?

If nobody objects, I'll send in a patch soon.

Regards,
Petur



More information about the Libstdc++ mailing list