E-MailRelay
gimembuf.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gimembuf.h
19///
20
21#ifndef G_IMEMBUF_H
22#define G_IMEMBUF_H
23
24#include "gdef.h"
25#include "gstringview.h"
26#include <streambuf>
27#include <algorithm>
28
29namespace G
30{
31 template <typename Tchar> class basic_imembuf ;
32 using imembuf = basic_imembuf<char> ;
33 using wimembuf = basic_imembuf<wchar_t> ;
34}
35
36//| \class G::basic_imembuf
37/// An input streambuf that takes its data from a fixed-size const
38/// buffer.
39///
40/// Eg:
41/// \code
42/// std::array<char,10> buffer ;
43/// G::imembuf sb( &buffer[0] , buffer.size() ) ;
44/// std::istream in( &sb ) ;
45/// \endcode
46///
47/// An alternative approach is to use std::istringstream with
48/// pubsetbuf() but there is no guarantee that the std::stringbuf
49/// implementation has a useful override of setbuf() (ie. msvc).
50///
51template <typename Tchar>
52class G::basic_imembuf : public std::basic_streambuf<Tchar>
53{
54public:
55 basic_imembuf( const Tchar * p , std::size_t n ) ;
56 ///< Constructor.
57
59 ///< Constructor.
60
61protected:
62 std::streamsize xsgetn( Tchar * s , std::streamsize n ) override ;
63 std::streampos seekpos( std::streampos pos , std::ios_base::openmode which ) override ;
64 std::streampos seekoff( std::streamoff off , std::ios_base::seekdir way , std::ios_base::openmode which ) override ;
65
66public:
67 ~basic_imembuf() override = default ;
68 basic_imembuf( const basic_imembuf<Tchar> & ) = delete ;
69 basic_imembuf( basic_imembuf<Tchar> && ) = delete ;
70 void operator=( const basic_imembuf<Tchar> & ) = delete ;
71 void operator=( basic_imembuf<Tchar> && ) = delete ;
72
73private:
74 template <typename Tint> static std::streamsize min( Tint a , std::streamsize b ) ;
75
76private:
77 const Tchar * m_p ;
78 std::size_t m_n ;
79} ;
80
81template <typename Tchar>
82template <typename Tint> std::streamsize G::basic_imembuf<Tchar>::min( Tint a , std::streamsize b )
83{
84 return std::min( static_cast<std::streamsize>(a) , b ) ;
85}
86
87template <typename Tchar>
89 m_p(s.data()) ,
90 m_n(s.size())
91{
92 using base_t = std::basic_streambuf<Tchar> ;
93 Tchar * mp = const_cast<Tchar*>(m_p) ;
94 base_t::setg( mp , mp , mp+m_n ) ;
95}
96
97template <typename Tchar>
98G::basic_imembuf<Tchar>::basic_imembuf( const Tchar * p_in , std::size_t n ) :
99 m_p(p_in) ,
100 m_n(n)
101{
102 using base_t = std::basic_streambuf<Tchar> ;
103 Tchar * mp = const_cast<Tchar*>(m_p) ;
104 base_t::setg( mp , mp , mp+m_n ) ;
105}
106
107template <typename Tchar>
108std::streamsize G::basic_imembuf<Tchar>::xsgetn( Tchar * s , std::streamsize n_in )
109{
110 using base_t = std::basic_streambuf<Tchar> ;
111 Tchar * gp = base_t::gptr() ;
112 std::streamsize n = min( m_p+m_n-gp , n_in ) ;
113 if( n > 0 )
114 {
115 std::copy( gp , gp+n , s ) ;
116 base_t::gbump( static_cast<int>(n) ) ;
117 }
118 return n ;
119}
120
121template <typename Tchar>
122std::streampos G::basic_imembuf<Tchar>::seekpos( std::streampos pos_in , std::ios_base::openmode which )
123{
124 using base_t = std::basic_streambuf<Tchar> ;
125 if( ( which & std::ios_base::in ) && pos_in > 0 )
126 {
127 Tchar * mp = const_cast<Tchar*>(m_p) ;
128 int pos = static_cast<int>(pos_in) ;
129 Tchar * p = std::min( mp+pos , mp+m_n ) ;
130 base_t::setg( mp , p , mp+m_n ) ;
131 return p - mp ;
132 }
133 else
134 {
135 return -1 ;
136 }
137}
138
139template <typename Tchar>
140std::streampos G::basic_imembuf<Tchar>::seekoff( std::streamoff off , std::ios_base::seekdir way , std::ios_base::openmode which )
141{
142 using base_t = std::basic_streambuf<Tchar> ;
143 if( which & std::ios_base::in )
144 {
145 Tchar * gp = base_t::gptr() ;
146 Tchar * mp = const_cast<Tchar*>(m_p) ;
147 if( way == std::ios_base::beg )
148 gp = std::max( mp , std::min(mp+off,mp+m_n) ) ;
149 else if( way == std::ios_base::cur )
150 gp = std::max( mp , std::min(gp+off,mp+m_n) ) ;
151 else // end
152 gp = std::max( mp , std::min(mp+m_n+off,mp+m_n) ) ;
153 base_t::setg( mp , gp , mp+m_n ) ;
154 return std::streamoff(gp-mp) ;
155 }
156 else
157 {
158 return -1 ;
159 }
160}
161
162#endif
An input streambuf that takes its data from a fixed-size const buffer.
Definition: gimembuf.h:53
basic_imembuf(const Tchar *p, std::size_t n)
Constructor.
Definition: gimembuf.h:98
A class template like c++17's std::basic_string_view.
Definition: gstringview.h:73
Low-level classes.
Definition: galign.h:28