1// -*- C++ -*-
2// Testing streambuf/filebuf/stringbuf for the C++ library testsuite.
3//
4// Copyright (C) 2003-2015 Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11//
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING3.  If not see
19// <http://www.gnu.org/licenses/>.
20//
21
22#ifndef _GLIBCXX_TESTSUITE_IO_H
23#define _GLIBCXX_TESTSUITE_IO_H
24
25#include <ios>
26
27namespace __gnu_test
28{
29  // Used to verify the constraints/requirements on get and put areas
30  // as defined in
31  // 27.5.1 - Stream buffer requirements: get and put areas
32  // 27.8.1.1 - Template class basic_filebuf p 3
33  //   If the file is not open (ios_base::in) -> input seq. cannot be read
34  //   If the file is not open (ios_base::out) -> output seq. cannot be written
35  //   Joint file position
36  // 27.8.1.4 - Overridden virtual functions p9
37  //   If unbuffered, pbase == pptr == NULL
38  // 27.7.1.1 - Basic_stringbuf constructors p 1
39  // 27.8.1.2 - Basic_filebuf constructors p 1
40  //   ... , initializing the base class with basic_streambuf() 27.5.2.1
41  template<typename T>
42    class constraint_buf
43    : public T
44    {
45    public:
46      bool
47      write_position()
48      {
49	bool one = this->pptr() != 0;
50	bool two = this->pptr() < this->epptr();
51	return one && two;
52      }
53
54      bool
55      read_position()
56      {
57	bool one = this->gptr() != 0;
58	bool two = this->gptr() < this->egptr();
59	return one && two;
60      }
61
62      bool
63      unbuffered()
64      {
65	bool one = this->pbase() == 0;
66	bool two = this->pptr() == 0;
67	return one && two;
68      }
69
70      bool
71      check_pointers()
72      {
73	bool one   = this->eback() == 0;
74	bool two   = this->gptr() == 0;
75	bool three = this->egptr() == 0;
76
77	bool four  = this->pbase() == 0;
78	bool five  = this->pptr() == 0;
79	bool six   = this->epptr() == 0;
80	return one && two && three && four && five && six;
81      }
82    };
83
84  typedef  constraint_buf<std::streambuf>   constraint_streambuf;
85  typedef  constraint_buf<std::filebuf>     constraint_filebuf;
86  typedef  constraint_buf<std::stringbuf>   constraint_stringbuf;
87#ifdef _GLIBCXX_USE_WCHAR_T
88  typedef  constraint_buf<std::wstreambuf>  constraint_wstreambuf;
89  typedef  constraint_buf<std::wfilebuf>    constraint_wfilebuf;
90  typedef  constraint_buf<std::wstringbuf>  constraint_wstringbuf;
91#endif
92
93  // Used to check if basic_streambuf::pubsync() has been called.
94  // This is useful for checking if a function creates [io]stream::sentry
95  // objects, since the sentry constructors call tie()->flush().
96  template<typename T>
97    class sync_buf
98    : public T
99    {
100    private:
101      bool m_sync_called;
102
103    public:
104      sync_buf()
105      : m_sync_called(false)
106      { }
107
108      bool sync_called() const
109      { return m_sync_called; }
110
111    protected:
112      int sync()
113      {
114	m_sync_called = true;
115	return 0;
116      }
117    };
118
119  typedef  sync_buf<std::streambuf>   sync_streambuf;
120#ifdef _GLIBCXX_USE_WCHAR_T
121  typedef  sync_buf<std::wstreambuf>  sync_wstreambuf;
122#endif
123
124  // Throws on all overflow and underflow calls.
125  struct underflow_error: std::exception { };
126  struct overflow_error: std::exception { };
127  struct positioning_error: std::exception { };
128
129  template<typename T>
130    struct fail_buf
131    : public T
132    {
133      typedef typename T::char_type   char_type;
134      typedef typename T::int_type    int_type;
135      typedef typename T::off_type    off_type;
136      typedef typename T::pos_type    pos_type;
137
138    private:
139      char_type p[2];
140
141    public:
142      fail_buf()
143      {
144	p[0] = char_type('s');
145	p[1] = char_type();
146	this->setg(p, p, p + 1);
147      }
148
149      virtual int_type underflow()
150      {
151	throw underflow_error();
152	return int_type();
153      }
154
155      virtual int_type uflow()
156      {
157	throw underflow_error();
158	return int_type();
159      }
160
161      virtual int_type
162      overflow(int_type)
163      {
164	throw overflow_error();
165	return int_type();
166      }
167
168      virtual pos_type
169      seekoff(off_type, std::ios_base::seekdir, std::ios_base::openmode)
170      {
171	throw positioning_error();
172	return pos_type(off_type(-1));
173      }
174
175      virtual pos_type
176      seekpos(pos_type, std::ios_base::openmode)
177      {
178	throw positioning_error();
179	return pos_type(off_type(-1));
180      }
181
182      virtual int
183      sync()
184      {
185	throw positioning_error();
186	return 0;
187      }
188    };
189
190  typedef  fail_buf<std::streambuf>   fail_streambuf;
191#ifdef _GLIBCXX_USE_WCHAR_T
192  typedef  fail_buf<std::wstreambuf>  fail_wstreambuf;
193#endif
194
195  // Facets that throw an exception for every virtual function.
196  struct facet_error: std::exception { };
197
198  template<typename T>
199    class fail_num_get
200    : public std::num_get<T>
201    {
202      typedef std::ios_base ios_base;
203      typedef typename std::num_get<T>::iter_type iter_type;
204
205    protected:
206      iter_type
207      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, bool&) const
208      { throw facet_error(); return iter_type(); }
209
210      virtual iter_type
211      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, long&) const
212      { throw facet_error(); return iter_type(); }
213
214      virtual iter_type
215      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
216	     unsigned short&) const
217      { throw facet_error(); return iter_type(); }
218
219      virtual iter_type
220      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
221	     unsigned int&) const
222      { throw facet_error(); return iter_type(); }
223
224      virtual iter_type
225      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
226	     unsigned long&) const
227      { throw facet_error(); return iter_type(); }
228
229#ifdef _GLIBCXX_USE_LONG_LONG
230      virtual iter_type
231      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
232	     long long&) const
233      { throw facet_error(); return iter_type(); }
234
235      virtual iter_type
236      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
237	     unsigned long long&) const
238      { throw facet_error(); return iter_type(); }
239#endif
240
241      virtual iter_type
242      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
243	     float&) const
244      { throw facet_error(); return iter_type(); }
245
246      virtual iter_type
247      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
248	     double&) const
249      { throw facet_error(); return iter_type(); }
250
251      virtual iter_type
252      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
253	     long double&) const
254      { throw facet_error(); return iter_type(); }
255
256      virtual iter_type
257      do_get(iter_type, iter_type, ios_base&, ios_base::iostate&,
258	     void*&) const
259      { throw facet_error(); return iter_type(); }
260    };
261
262  typedef  fail_num_get<char>     fail_num_get_char;
263#ifdef _GLIBCXX_USE_WCHAR_T
264  typedef  fail_num_get<wchar_t>  fail_num_get_wchar_t;
265#endif
266
267  template<typename T>
268    class fail_num_put
269    : public std::num_put<T>
270    {
271      typedef std::ios_base ios_base;
272      typedef typename std::num_put<T>::iter_type iter_type;
273      typedef typename std::num_put<T>::char_type char_type;
274
275    protected:
276      iter_type
277      do_put(iter_type, ios_base&, char_type, bool) const
278      { throw facet_error(); return iter_type(0); }
279
280      virtual iter_type
281      do_put(iter_type, ios_base&, char_type, long) const
282      { throw facet_error(); return iter_type(0); }
283
284      virtual iter_type
285      do_put(iter_type, ios_base&, char_type, unsigned long) const
286      { throw facet_error(); return iter_type(0); }
287
288#ifdef _GLIBCXX_USE_LONG_LONG
289      virtual iter_type
290      do_put(iter_type, ios_base&, char_type, long long) const
291      { throw facet_error(); return iter_type(0); }
292
293      virtual iter_type
294      do_put(iter_type, ios_base&, char_type, unsigned long long) const
295      { throw facet_error(); return iter_type(0); }
296#endif
297
298      virtual iter_type
299      do_put(iter_type, ios_base&, char_type, double) const
300      { throw facet_error(); return iter_type(0); }
301
302      virtual iter_type
303      do_put(iter_type, ios_base&, char_type, long double) const
304      { throw facet_error(); return iter_type(0); }
305
306      virtual iter_type
307      do_put(iter_type, ios_base&, char_type, const void*) const
308      { throw facet_error(); return iter_type(0); }
309    };
310
311  typedef  fail_num_put<char>     fail_num_put_char;
312#ifdef _GLIBCXX_USE_WCHAR_T
313  typedef  fail_num_put<wchar_t>  fail_num_put_wchar_t;
314#endif
315} // namespace __gnu_test
316
317#endif // _GLIBCXX_TESTSUITE_IO_H
318
319