E-MailRelay
gimembuf.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 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 <streambuf>
26#include <algorithm>
27
28namespace G
29{
30 template <typename Tchar> class basic_imembuf ;
31 using imembuf = basic_imembuf<char> ;
32 using wimembuf = basic_imembuf<wchar_t> ;
33}
34
35//| \class G::basic_imembuf
36/// An input streambuf that takes its data from a fixed-size const
37/// buffer.
38///
39/// Eg:
40/// \code
41/// std::array<char,10> buffer ;
42/// G::basic_imembuf<char> sb( buffer.data() , buffer.size() ) ;
43/// std::istream in( &sb ) ;
44/// \endcode
45///
46/// An alternative approach is to use std::istringstream with
47/// pubsetbuf() but there is no guarantee that the std::stringbuf
48/// implementation has a useful override of setbuf() (ie. msvc).
49///
50template <typename Tchar>
51class G::basic_imembuf : public std::basic_streambuf<Tchar>
52{
53public:
54 basic_imembuf( const Tchar * p , std::size_t n ) ;
55 ///< Constructor.
56
57protected:
58 std::streamsize xsgetn( Tchar * s , std::streamsize n ) override ;
59 std::streampos seekpos( std::streampos pos , std::ios_base::openmode which ) override ;
60 std::streampos seekoff( std::streamoff off , std::ios_base::seekdir way , std::ios_base::openmode which ) override ;
61
62public:
63 ~basic_imembuf() override = default ;
64 basic_imembuf( const basic_imembuf<Tchar> & ) = delete ;
65 basic_imembuf( basic_imembuf<Tchar> && ) = delete ;
66 basic_imembuf<Tchar> & operator=( const basic_imembuf<Tchar> & ) = delete ;
67 basic_imembuf<Tchar> & operator=( basic_imembuf<Tchar> && ) = delete ;
68
69private:
70 template <typename Tint> static std::streamsize min( Tint a , std::streamsize b ) ;
71
72private:
73 const Tchar * m_p ;
74 std::size_t m_n ;
75} ;
76
77template <typename Tchar>
78template <typename Tint> std::streamsize G::basic_imembuf<Tchar>::min( Tint a , std::streamsize b )
79{
80 return std::min( static_cast<std::streamsize>(a) , b ) ;
81}
82
83template <typename Tchar>
84G::basic_imembuf<Tchar>::basic_imembuf( const Tchar * p_in , std::size_t n ) :
85 m_p(p_in) ,
86 m_n(n)
87{
88 using base_t = std::basic_streambuf<Tchar> ;
89 Tchar * mp = const_cast<Tchar*>(m_p) ;
90 base_t::setg( mp , mp , mp+m_n ) ;
91}
92
93template <typename Tchar>
94std::streamsize G::basic_imembuf<Tchar>::xsgetn( Tchar * s , std::streamsize n_in )
95{
96 using base_t = std::basic_streambuf<Tchar> ;
97 Tchar * gp = base_t::gptr() ;
98 std::streamsize n = min( m_p+m_n-gp , n_in ) ;
99 if( n > 0 )
100 {
101 std::copy( gp , gp+n , s ) ;
102 base_t::gbump( static_cast<int>(n) ) ;
103 }
104 return n ;
105}
106
107template <typename Tchar>
108std::streampos G::basic_imembuf<Tchar>::seekpos( std::streampos pos_in , std::ios_base::openmode which )
109{
110 using base_t = std::basic_streambuf<Tchar> ;
111 if( ( which & std::ios_base::in ) && pos_in > 0 ) // NOLINT
112 {
113 Tchar * mp = const_cast<Tchar*>(m_p) ;
114 int pos = static_cast<int>(pos_in) ;
115 Tchar * p = std::min( mp+pos , mp+m_n ) ;
116 base_t::setg( mp , p , mp+m_n ) ;
117 return p - mp ;
118 }
119 else
120 {
121 return -1 ;
122 }
123}
124
125template <typename Tchar>
126std::streampos G::basic_imembuf<Tchar>::seekoff( std::streamoff off , std::ios_base::seekdir way , std::ios_base::openmode which )
127{
128 using base_t = std::basic_streambuf<Tchar> ;
129 if( which & std::ios_base::in )
130 {
131 Tchar * gp = base_t::gptr() ;
132 Tchar * mp = const_cast<Tchar*>(m_p) ;
133 if( way == std::ios_base::beg )
134 gp = std::max( mp , std::min(mp+off,mp+m_n) ) ;
135 else if( way == std::ios_base::cur )
136 gp = std::max( mp , std::min(gp+off,mp+m_n) ) ;
137 else // end
138 gp = std::max( mp , std::min(mp+m_n+off,mp+m_n) ) ;
139 base_t::setg( mp , gp , mp+m_n ) ;
140 return std::streamoff(gp-mp) ;
141 }
142 else
143 {
144 return -1 ;
145 }
146}
147
148#endif
An input streambuf that takes its data from a fixed-size const buffer.
Definition: gimembuf.h:52
basic_imembuf(const Tchar *p, std::size_t n)
Constructor.
Definition: gimembuf.h:84
Low-level classes.
Definition: garg.h:36