[conversions.buffer]

llvm-svn: 105286
This commit is contained in:
Howard Hinnant 2010-06-01 20:09:18 +00:00
parent b0c76394a3
commit 6508e9936c
11 changed files with 884 additions and 7 deletions

View File

@ -3795,16 +3795,27 @@ public:
typedef typename _Codecvt::state_type state_type;
private:
char* __extbuf_;
const char* __extbufnext_;
const char* __extbufend_;
char __extbuf_min_[8];
size_t __ebs_;
char_type* __intbuf_;
size_t __ibs_;
streambuf* __bufptr_;
_Codecvt* __cvtptr_;
state_type __cvtstate_;
_Codecvt* __cv_;
state_type __st_;
ios_base::openmode __cm_;
bool __owns_eb_;
bool __owns_ib_;
bool __always_noconv_;
wbuffer_convert(const wbuffer_convert&);
wbuffer_convert& operator=(const wbuffer_convert&);
public:
wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
state_type __state = state_type())
: __bufptr_(__bytebuf), __cvtptr_(__pcvt), __cvtstate_(__state) {}
~wbuffer_convert() {delete __cvtptr_;}
state_type __state = state_type());
~wbuffer_convert();
streambuf* rdbuf() const {return __bufptr_;}
streambuf* rdbuf(streambuf* __bytebuf)
@ -3814,16 +3825,417 @@ public:
return __r;
}
state_type state() const {return __cvtstate_;}
state_type state() const {return __st_;}
protected:
virtual int_type underflow();
virtual int_type pbackfail(int_type __c = traits_type::eof());
virtual int_type overflow (int_type __c = traits_type::eof());
virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
streamsize __n);
virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
ios_base::openmode __wch = ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type __sp,
ios_base::openmode __wch = ios_base::in | ios_base::out);
virtual int sync();
private:
bool __read_mode();
void __write_mode();
wbuffer_convert* __close();
};
template <class _Codecvt, class _Elem, class _Tr>
wbuffer_convert<_Codecvt, _Elem, _Tr>::
wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
: __extbuf_(0),
__extbufnext_(0),
__extbufend_(0),
__ebs_(0),
__intbuf_(0),
__ibs_(0),
__bufptr_(__bytebuf),
__cv_(__pcvt),
__st_(__state),
__cm_(0),
__owns_eb_(false),
__owns_ib_(false),
__always_noconv_(__cv_ ? __cv_->always_noconv() : false)
{
setbuf(0, 4096);
}
template <class _Codecvt, class _Elem, class _Tr>
wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
{
__close();
delete __cv_;
if (__owns_eb_)
delete [] __extbuf_;
if (__owns_ib_)
delete [] __intbuf_;
}
template <class _Codecvt, class _Elem, class _Tr>
typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
{
if (__cv_ == 0 || __bufptr_ == 0)
return traits_type::eof();
bool __initial = __read_mode();
char_type __1buf;
if (this->gptr() == 0)
this->setg(&__1buf, &__1buf+1, &__1buf+1);
const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
int_type __c = traits_type::eof();
if (this->gptr() == this->egptr())
{
memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
if (__always_noconv_)
{
streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
__nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
if (__nmemb != 0)
{
this->setg(this->eback(),
this->eback() + __unget_sz,
this->eback() + __unget_sz + __nmemb);
__c = *this->gptr();
}
}
else
{
memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
__extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
__extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
streamsize __nmemb = min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
static_cast<streamsize>(__extbufend_ - __extbufnext_));
codecvt_base::result __r;
state_type __svs = __st_;
streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
if (__nr != 0)
{
__extbufend_ = __extbufnext_ + __nr;
char_type* __inext;
__r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
this->eback() + __unget_sz,
this->egptr(), __inext);
if (__r == codecvt_base::noconv)
{
this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
__c = *this->gptr();
}
else if (__inext != this->eback() + __unget_sz)
{
this->setg(this->eback(), this->eback() + __unget_sz, __inext);
__c = *this->gptr();
}
}
}
}
else
__c = *this->gptr();
if (this->eback() == &__1buf)
this->setg(0, 0, 0);
return __c;
}
template <class _Codecvt, class _Elem, class _Tr>
typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
{
if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
{
if (traits_type::eq_int_type(__c, traits_type::eof()))
{
this->gbump(-1);
return traits_type::not_eof(__c);
}
if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
{
this->gbump(-1);
*this->gptr() = traits_type::to_char_type(__c);
return __c;
}
}
return traits_type::eof();
}
template <class _Codecvt, class _Elem, class _Tr>
typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
{
if (__cv_ == 0 || __bufptr_ == 0)
return traits_type::eof();
__write_mode();
char_type __1buf;
char_type* __pb_save = this->pbase();
char_type* __epb_save = this->epptr();
if (!traits_type::eq_int_type(__c, traits_type::eof()))
{
if (this->pptr() == 0)
this->setp(&__1buf, &__1buf+1);
*this->pptr() = traits_type::to_char_type(__c);
this->pbump(1);
}
if (this->pptr() != this->pbase())
{
if (__always_noconv_)
{
streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
return traits_type::eof();
}
else
{
char* __extbe = __extbuf_;
codecvt_base::result __r;
do
{
const char_type* __e;
__r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
__extbuf_, __extbuf_ + __ebs_, __extbe);
if (__e == this->pbase())
return traits_type::eof();
if (__r == codecvt_base::noconv)
{
streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
return traits_type::eof();
}
else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
{
streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
return traits_type::eof();
if (__r == codecvt_base::partial)
{
this->setp((char_type*)__e, this->pptr());
this->pbump(this->epptr() - this->pbase());
}
}
else
return traits_type::eof();
} while (__r == codecvt_base::partial);
}
this->setp(__pb_save, __epb_save);
}
return traits_type::not_eof(__c);
}
template <class _Codecvt, class _Elem, class _Tr>
basic_streambuf<_Elem, _Tr>*
wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
{
this->setg(0, 0, 0);
this->setp(0, 0);
if (__owns_eb_)
delete [] __extbuf_;
if (__owns_ib_)
delete [] __intbuf_;
__ebs_ = __n;
if (__ebs_ > sizeof(__extbuf_min_))
{
if (__always_noconv_ && __s)
{
__extbuf_ = (char*)__s;
__owns_eb_ = false;
}
else
{
__extbuf_ = new char[__ebs_];
__owns_eb_ = true;
}
}
else
{
__extbuf_ = __extbuf_min_;
__ebs_ = sizeof(__extbuf_min_);
__owns_eb_ = false;
}
if (!__always_noconv_)
{
__ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
if (__s && __ibs_ >= sizeof(__extbuf_min_))
{
__intbuf_ = __s;
__owns_ib_ = false;
}
else
{
__intbuf_ = new char_type[__ibs_];
__owns_ib_ = true;
}
}
else
{
__ibs_ = 0;
__intbuf_ = 0;
__owns_ib_ = false;
}
return this;
}
template <class _Codecvt, class _Elem, class _Tr>
typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
ios_base::openmode __om)
{
int __width = __cv_->encoding();
if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
return pos_type(off_type(-1));
// __width > 0 || __off == 0
switch (__way)
{
case ios_base::beg:
break;
case ios_base::cur:
break;
case ios_base::end:
break;
default:
return pos_type(off_type(-1));
}
pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
__r.state(__st_);
return __r;
}
template <class _Codecvt, class _Elem, class _Tr>
typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
{
if (__cv_ == 0 || __bufptr_ == 0 || sync())
return pos_type(off_type(-1));
if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
return pos_type(off_type(-1));
return __sp;
}
template <class _Codecvt, class _Elem, class _Tr>
int
wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
{
if (__cv_ == 0 || __bufptr_ == 0)
return 0;
if (__cm_ & ios_base::out)
{
if (this->pptr() != this->pbase())
if (overflow() == traits_type::eof())
return -1;
codecvt_base::result __r;
do
{
char* __extbe;
__r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
return -1;
} while (__r == codecvt_base::partial);
if (__r == codecvt_base::error)
return -1;
if (__bufptr_->pubsync())
return -1;
}
else if (__cm_ & ios_base::in)
{
off_type __c;
if (__always_noconv_)
__c = this->egptr() - this->gptr();
else
{
int __width = __cv_->encoding();
__c = __extbufend_ - __extbufnext_;
if (__width > 0)
__c += __width * (this->egptr() - this->gptr());
else
{
if (this->gptr() != this->egptr())
{
reverse(this->gptr(), this->egptr());
codecvt_base::result __r;
const char_type* __e = this->gptr();
char* __extbe;
do
{
__r = __cv_->out(__st_, __e, this->egptr(), __e,
__extbuf_, __extbuf_ + __ebs_, __extbe);
switch (__r)
{
case codecvt_base::noconv:
__c += this->egptr() - this->gptr();
break;
case codecvt_base::ok:
case codecvt_base::partial:
__c += __extbe - __extbuf_;
break;
default:
return -1;
}
} while (__r == codecvt_base::partial);
}
}
}
if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
return -1;
this->setg(0, 0, 0);
__cm_ = 0;
}
return 0;
}
template <class _Codecvt, class _Elem, class _Tr>
bool
wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
{
if (!(__cm_ & ios_base::in))
{
this->setp(0, 0);
if (__always_noconv_)
this->setg((char_type*)__extbuf_,
(char_type*)__extbuf_ + __ebs_,
(char_type*)__extbuf_ + __ebs_);
else
this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
__cm_ = ios_base::in;
return true;
}
return false;
}
template <class _Codecvt, class _Elem, class _Tr>
void
wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
{
if (!(__cm_ & ios_base::out))
{
this->setg(0, 0, 0);
if (__ebs_ > sizeof(__extbuf_min_))
{
if (__always_noconv_)
this->setp((char_type*)__extbuf_,
(char_type*)__extbuf_ + (__ebs_ - 1));
else
this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
}
else
this->setp(0, 0);
__cm_ = ios_base::out;
}
}
template <class _Codecvt, class _Elem, class _Tr>
wbuffer_convert<_Codecvt, _Elem, _Tr>*
wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
{
wbuffer_convert* __rt = 0;
if (__cv_ != 0 && __bufptr_ != 0)
{
__rt = this;
if ((__cm_ & ios_base::out) && sync())
__rt = 0;
}
return __rt;
}
_LIBCPP_END_NAMESPACE_STD

View File

@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <locale>
// wbuffer_convert<Codecvt, Elem, Tr>
// wbuffer_convert(streambuf *bytebuf = 0, Codecvt *pcvt = new Codecvt,
// state_type state = state_type());
#include <locale>
#include <codecvt>
#include <sstream>
#include <cassert>
#include <new>
int new_called = 0;
void* operator new(std::size_t s) throw(std::bad_alloc)
{
++new_called;
return std::malloc(s);
}
void operator delete(void* p) throw()
{
--new_called;
std::free(p);
}
int main()
{
typedef std::wbuffer_convert<std::codecvt_utf8<wchar_t> > B;
{
B b;
assert(b.rdbuf() == nullptr);
assert(new_called != 0);
}
assert(new_called == 0);
{
std::stringstream s;
B b(s.rdbuf());
assert(b.rdbuf() == s.rdbuf());
assert(new_called != 0);
}
assert(new_called == 0);
{
std::stringstream s;
B b(s.rdbuf(), new std::codecvt_utf8<wchar_t>);
assert(b.rdbuf() == s.rdbuf());
assert(new_called != 0);
}
assert(new_called == 0);
{
std::stringstream s;
B b(s.rdbuf(), new std::codecvt_utf8<wchar_t>, std::mbstate_t());
assert(b.rdbuf() == s.rdbuf());
assert(new_called != 0);
}
assert(new_called == 0);
}

View File

@ -0,0 +1,100 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <locale>
// wbuffer_convert<Codecvt, Elem, Tr>
// int_type overflow(int_type c = traits::eof());
// This test is not entirely portable
#include <locale>
#include <codecvt>
#include <fstream>
#include <cassert>
struct test_buf
: public std::wbuffer_convert<std::codecvt_utf8<wchar_t> >
{
typedef std::wbuffer_convert<std::codecvt_utf8<wchar_t> > base;
typedef base::char_type char_type;
typedef base::int_type int_type;
typedef base::traits_type traits_type;
explicit test_buf(std::streambuf* sb) : base(sb) {}
char_type* pbase() const {return base::pbase();}
char_type* pptr() const {return base::pptr();}
char_type* epptr() const {return base::epptr();}
void gbump(int n) {base::gbump(n);}
virtual int_type overflow(int_type c = traits_type::eof()) {return base::overflow(c);}
};
int main()
{
{
std::ofstream bs("overflow.dat");
test_buf f(bs.rdbuf());
assert(f.pbase() == 0);
assert(f.pptr() == 0);
assert(f.epptr() == 0);
assert(f.overflow(L'a') == L'a');
assert(f.pbase() != 0);
assert(f.pptr() == f.pbase());
assert(f.epptr() - f.pbase() == 4095);
}
{
std::ifstream bs("overflow.dat");
test_buf f(bs.rdbuf());
assert(f.sgetc() == L'a');
}
std::remove("overflow.dat");
{
std::ofstream bs("overflow.dat");
test_buf f(bs.rdbuf());
f.pubsetbuf(0, 0);
assert(f.pbase() == 0);
assert(f.pptr() == 0);
assert(f.epptr() == 0);
assert(f.overflow('a') == 'a');
assert(f.pbase() == 0);
assert(f.pptr() == 0);
assert(f.epptr() == 0);
}
{
std::ifstream bs("overflow.dat");
test_buf f(bs.rdbuf());
assert(f.sgetc() == L'a');
}
std::remove("overflow.dat");
{
std::ofstream bs("overflow.dat");
test_buf f(bs.rdbuf());
assert(f.sputc(0x4E51) == 0x4E51);
assert(f.sputc(0x4E52) == 0x4E52);
assert(f.sputc(0x4E53) == 0x4E53);
}
{
std::ifstream f("overflow.dat");
assert(f.is_open());
assert(f.get() == 0xE4);
assert(f.get() == 0xB9);
assert(f.get() == 0x91);
assert(f.get() == 0xE4);
assert(f.get() == 0xB9);
assert(f.get() == 0x92);
assert(f.get() == 0xE4);
assert(f.get() == 0xB9);
assert(f.get() == 0x93);
assert(f.get() == -1);
}
std::remove("overflow.dat");
}

View File

@ -0,0 +1,59 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <locale>
// wbuffer_convert<Codecvt, Elem, Tr>
// int_type pbackfail(int_type c = traits::eof());
// This test is not entirely portable
#include <locale>
#include <codecvt>
#include <fstream>
#include <cassert>
struct test_buf
: public std::wbuffer_convert<std::codecvt_utf8<wchar_t> >
{
typedef std::wbuffer_convert<std::codecvt_utf8<wchar_t> > base;
typedef base::char_type char_type;
typedef base::int_type int_type;
typedef base::traits_type traits_type;
explicit test_buf(std::streambuf* sb) : base(sb) {}
char_type* eback() const {return base::eback();}
char_type* gptr() const {return base::gptr();}
char_type* egptr() const {return base::egptr();}
void gbump(int n) {base::gbump(n);}
virtual int_type pbackfail(int_type c = traits_type::eof()) {return base::pbackfail(c);}
};
int main()
{
{
std::ifstream bs("underflow.dat");
test_buf f(bs.rdbuf());
assert(f.sbumpc() == L'1');
assert(f.sgetc() == L'2');
assert(f.pbackfail(L'a') == -1);
}
{
std::fstream bs("underflow.dat");
test_buf f(bs.rdbuf());
assert(f.sbumpc() == L'1');
assert(f.sgetc() == L'2');
assert(f.pbackfail(L'a') == -1);
assert(f.sbumpc() == L'2');
assert(f.sgetc() == L'3');
}
}

View File

@ -0,0 +1,31 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <locale>
// wbuffer_convert<Codecvt, Elem, Tr>
// streambuf *rdbuf(streambuf *bytebuf);
#include <locale>
#include <codecvt>
#include <sstream>
#include <cassert>
int main()
{
typedef std::wbuffer_convert<std::codecvt_utf8<wchar_t> > B;
{
std::stringstream s;
B b;
assert(b.rdbuf() == nullptr);
b.rdbuf(s.rdbuf());
assert(b.rdbuf() == s.rdbuf());
}
}

View File

@ -0,0 +1,58 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <locale>
// wbuffer_convert<Codecvt, Elem, Tr>
// pos_type seekoff(off_type off, ios_base::seekdir way,
// ios_base::openmode which = ios_base::in | ios_base::out);
// pos_type seekpos(pos_type sp,
// ios_base::openmode which = ios_base::in | ios_base::out);
// This test is not entirely portable
#include <locale>
#include <codecvt>
#include <fstream>
#include <cassert>
class test_codecvt
: public std::codecvt<wchar_t, char, std::mbstate_t>
{
typedef std::codecvt<wchar_t, char, std::mbstate_t> base;
public:
explicit test_codecvt(std::size_t refs = 0) : base(refs) {}
~test_codecvt() {}
};
int main()
{
{
wchar_t buf[10];
typedef std::wbuffer_convert<test_codecvt> test_buf;
typedef test_buf::pos_type pos_type;
std::fstream bs("seekoff.dat", std::ios::trunc | std::ios::in
| std::ios::out);
test_buf f(bs.rdbuf());
f.pubsetbuf(buf, sizeof(buf)/sizeof(buf[0]));
f.sputn(L"abcdefghijklmnopqrstuvwxyz", 26);
assert(buf[0] == L'v');
pos_type p = f.pubseekoff(-15, std::ios_base::cur);
assert(p == 11);
assert(f.sgetc() == L'l');
f.pubseekoff(0, std::ios_base::beg);
assert(f.sgetc() == L'a');
f.pubseekoff(-1, std::ios_base::end);
assert(f.sgetc() == L'z');
assert(f.pubseekpos(p) == p);
assert(f.sgetc() == L'l');
}
std::remove("seekoff.dat");
}

View File

@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <locale>
// wbuffer_convert<Codecvt, Elem, Tr>
// state_type state() const;
#include <locale>
#include <codecvt>
#include <sstream>
#include <cassert>
int main()
{
typedef std::wbuffer_convert<std::codecvt_utf8<wchar_t> > B;
{
B b;
std::mbstate_t s = b.state();
}
}

View File

@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <locale>
// wbuffer_convert<Codecvt, Elem, Tr>
#include <fstream>
#include <locale>
#include <codecvt>
#include <cassert>
int main()
{
{
std::ofstream bytestream("myfile.txt");
std::wbuffer_convert<std::codecvt_utf8<wchar_t> > mybuf(bytestream.rdbuf());
std::wostream mystr(&mybuf);
mystr << L"Hello" << std::endl;
}
{
std::ifstream bytestream("myfile.txt");
std::wbuffer_convert<std::codecvt_utf8<wchar_t> > mybuf(bytestream.rdbuf());
std::wistream mystr(&mybuf);
std::wstring ws;
mystr >> ws;
assert(ws == L"Hello");
}
std::remove("myfile.txt");
}

View File

@ -0,0 +1,84 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <locale>
// wbuffer_convert<Codecvt, Elem, Tr>
// int_type underflow();
// This test is not entirely portable
#include <locale>
#include <codecvt>
#include <fstream>
#include <cassert>
struct test_buf
: public std::wbuffer_convert<std::codecvt_utf8<wchar_t> >
{
typedef std::wbuffer_convert<std::codecvt_utf8<wchar_t> > base;
typedef base::char_type char_type;
typedef base::int_type int_type;
typedef base::traits_type traits_type;
explicit test_buf(std::streambuf* sb) : base(sb) {}
char_type* eback() const {return base::eback();}
char_type* gptr() const {return base::gptr();}
char_type* egptr() const {return base::egptr();}
void gbump(int n) {base::gbump(n);}
virtual int_type underflow() {return base::underflow();}
};
int main()
{
{
std::ifstream bs("underflow.dat");
test_buf f(bs.rdbuf());
assert(f.eback() == 0);
assert(f.gptr() == 0);
assert(f.egptr() == 0);
assert(f.underflow() == L'1');
assert(f.eback() != 0);
assert(f.eback() == f.gptr());
assert(*f.gptr() == L'1');
assert(f.egptr() - f.eback() == 9);
}
{
std::ifstream bs("underflow.dat");
test_buf f(bs.rdbuf());
assert(f.eback() == 0);
assert(f.gptr() == 0);
assert(f.egptr() == 0);
assert(f.underflow() == L'1');
assert(f.eback() != 0);
assert(f.eback() == f.gptr());
assert(*f.gptr() == L'1');
assert(f.egptr() - f.eback() == 9);
f.gbump(8);
assert(f.sgetc() == L'9');
assert(f.eback()[0] == L'1');
assert(f.eback()[1] == L'2');
assert(f.eback()[2] == L'3');
assert(f.eback()[3] == L'4');
assert(f.gptr() - f.eback() == 8);
assert(*f.gptr() == L'9');
assert(f.egptr() - f.gptr() == 1);
}
{
std::ifstream bs("underflow_utf8.dat");
test_buf f(bs.rdbuf());
assert(f.sbumpc() == 0x4E51);
assert(f.sbumpc() == 0x4E52);
assert(f.sbumpc() == 0x4E53);
assert(f.sbumpc() == -1);
}
}