// Copyright (c) Robin E.R. Davies // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #pragma once #include #include #include #include template class view_streambuf final: public std::basic_streambuf<__char_type, __traits_type > { private: typedef std::basic_streambuf<__char_type, __traits_type > super_type; typedef view_streambuf<__char_type, __traits_type> self_type; public: /** * These are standard types. They permit a standardized way of * referring to names of (or names dependent on) the template * parameters, which are specific to the implementation. */ typedef typename super_type::char_type char_type; typedef typename super_type::traits_type traits_type; typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; typedef typename std::basic_string_view source_view; view_streambuf(const source_view& src) noexcept: super_type(), src_( src ) { char_type *buff = const_cast( src_.data() ); this->setg( buff , buff, buff + src_.length() ); } virtual std::streamsize xsgetn(char_type* __s, std::streamsize __n) override { if(0 == __n) return 0; if( (this->gptr() + __n) >= this->egptr() ) { __n = this->egptr() - this->gptr(); if(0 == __n && !traits_type::not_eof( this->underflow() ) ) return -1; } std::memmove( static_cast(__s), this->gptr(), __n); this->gbump( static_cast(__n) ); return __n; } virtual int_type pbackfail(int_type __c) override { char_type *pos = this->gptr() - 1; *pos = traits_type::to_char_type( __c ); this->pbump(-1); return 1; } virtual int_type underflow() override { return traits_type::eof(); } virtual std::streamsize showmanyc() override { return static_cast( this->egptr() - this->gptr() ); } virtual ~view_streambuf() override {} private: const source_view& src_; }; template class view_istream final:public std::basic_istream<_char_type, std::char_traits<_char_type> > { view_istream(const view_istream&) = delete; view_istream& operator=(const view_istream&) = delete; private: typedef std::basic_istream<_char_type, std::char_traits<_char_type> > super_type; typedef view_streambuf<_char_type, std::char_traits<_char_type> > streambuf_type; public: typedef _char_type char_type; typedef typename super_type::int_type int_type; typedef typename super_type::pos_type pos_type; typedef typename super_type::off_type off_type; typedef typename super_type::traits_type traits_type; typedef typename streambuf_type::source_view source_view; view_istream(const source_view& src): super_type( nullptr ), sb_(nullptr) { sb_ = new streambuf_type(src); this->init( sb_ ); } view_istream(view_istream&& other) noexcept: super_type( std::forward(other) ), sb_( std::move( other.sb_ ) ) {} view_istream& operator=(view_istream&& rhs) noexcept { view_istream( std::forward(rhs) ).swap( *this ); return *this; } virtual ~view_istream() override { delete sb_; } private: streambuf_type *sb_; };