diff --git a/include/locale b/include/locale index 92a33928..f48a75ec 100644 --- a/include/locale +++ b/include/locale @@ -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 diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/ctor.pass.cpp b/test/localization/locales/locale.convenience/conversions/conversions.buffer/ctor.pass.cpp new file mode 100644 index 00000000..e1617a16 --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/ctor.pass.cpp @@ -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); +} diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/overflow.pass.cpp b/test/localization/locales/locale.convenience/conversions/conversions.buffer/overflow.pass.cpp new file mode 100644 index 00000000..891b759b --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/overflow.pass.cpp @@ -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"); +} diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/pbackfail.pass.cpp b/test/localization/locales/locale.convenience/conversions/conversions.buffer/pbackfail.pass.cpp new file mode 100644 index 00000000..37359d4f --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/pbackfail.pass.cpp @@ -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'); + } +} diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/rdbuf.pass.cpp b/test/localization/locales/locale.convenience/conversions/conversions.buffer/rdbuf.pass.cpp new file mode 100644 index 00000000..a51073aa --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/rdbuf.pass.cpp @@ -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()); + } +} diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp b/test/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp new file mode 100644 index 00000000..f447c0df --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp @@ -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"); +} diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/state.pass.cpp b/test/localization/locales/locale.convenience/conversions/conversions.buffer/state.pass.cpp new file mode 100644 index 00000000..c98aba9f --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/state.pass.cpp @@ -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(); + } +} diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/test.pass.cpp b/test/localization/locales/locale.convenience/conversions/conversions.buffer/test.pass.cpp new file mode 100644 index 00000000..9f536e43 --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/test.pass.cpp @@ -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"); +} diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.dat b/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.dat new file mode 100644 index 00000000..e2e107ac --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.dat @@ -0,0 +1 @@ +123456789 \ No newline at end of file diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.pass.cpp b/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.pass.cpp new file mode 100644 index 00000000..0e449730 --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.pass.cpp @@ -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); + } +} diff --git a/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow_utf8.dat b/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow_utf8.dat new file mode 100644 index 00000000..ee7063e1 --- /dev/null +++ b/test/localization/locales/locale.convenience/conversions/conversions.buffer/underflow_utf8.dat @@ -0,0 +1 @@ +乑乒乓 \ No newline at end of file