Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4680 | right-hear | 1 | // File based streams -*- C++ -*- |
2 | |||
3 | // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
||
4 | // |
||
5 | // This file is part of the GNU ISO C++ Library. This library is free |
||
6 | // software; you can redistribute it and/or modify it under the |
||
7 | // terms of the GNU General Public License as published by the |
||
8 | // Free Software Foundation; either version 2, or (at your option) |
||
9 | // any later version. |
||
10 | |||
11 | // This library is distributed in the hope that it will be useful, |
||
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | // GNU General Public License for more details. |
||
15 | |||
16 | // You should have received a copy of the GNU General Public License along |
||
17 | // with this library; see the file COPYING. If not, write to the Free |
||
18 | // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
||
19 | // USA. |
||
20 | |||
21 | // As a special exception, you may use this file as part of a free software |
||
22 | // library without restriction. Specifically, if other files instantiate |
||
23 | // templates or use macros or inline functions from this file, or you compile |
||
24 | // this file and link it with other files to produce an executable, this |
||
25 | // file does not by itself cause the resulting executable to be covered by |
||
26 | // the GNU General Public License. This exception does not however |
||
27 | // invalidate any other reasons why the executable file might be covered by |
||
28 | // the GNU General Public License. |
||
29 | |||
30 | // |
||
31 | // ISO C++ 14882: 27.8 File-based streams |
||
32 | // |
||
33 | |||
34 | #ifndef _CPP_FSTREAM |
||
35 | #define _CPP_FSTREAM 1 |
||
36 | |||
37 | #pragma GCC system_header |
||
38 | |||
39 | #include |
||
40 | #include |
||
41 | #include |
||
42 | #include |
||
43 | #include |
||
44 | |||
45 | namespace std |
||
46 | { |
||
47 | template |
||
48 | class basic_filebuf : public basic_streambuf<_CharT, _Traits> |
||
49 | { |
||
50 | public: |
||
51 | // Types: |
||
52 | typedef _CharT char_type; |
||
53 | typedef _Traits traits_type; |
||
54 | typedef typename traits_type::int_type int_type; |
||
55 | typedef typename traits_type::pos_type pos_type; |
||
56 | typedef typename traits_type::off_type off_type; |
||
57 | |||
58 | // Non-standard Types: |
||
59 | typedef basic_streambuf |
||
60 | typedef basic_filebuf |
||
61 | typedef __basic_file |
||
62 | typedef typename traits_type::state_type __state_type; |
||
63 | typedef codecvt |
||
64 | typedef typename __codecvt_type::result __res_type; |
||
65 | typedef ctype |
||
66 | |||
67 | friend class ios_base; // For sync_with_stdio. |
||
68 | |||
69 | private: |
||
70 | // Data Members: |
||
71 | // External buffer. |
||
72 | __file_type* _M_file; |
||
73 | |||
74 | // Current and beginning state type for codecvt. |
||
75 | __state_type _M_state_cur; |
||
76 | __state_type _M_state_beg; |
||
77 | |||
78 | // MT lock inherited from libio or other low-level io library. |
||
79 | __c_lock _M_lock; |
||
80 | |||
81 | // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer.. |
||
82 | bool _M_buf_allocated; |
||
83 | |||
84 | // XXX Needed? |
||
85 | bool _M_last_overflowed; |
||
86 | |||
87 | public: |
||
88 | // Constructors/destructor: |
||
89 | basic_filebuf(); |
||
90 | |||
91 | // Non-standard ctor: |
||
92 | basic_filebuf(__c_file_type* __f, ios_base::openmode __mode, |
||
93 | int_type __s = static_cast |
||
94 | |||
95 | virtual |
||
96 | ~basic_filebuf() |
||
97 | { |
||
98 | this->close(); |
||
99 | _M_last_overflowed = false; |
||
100 | } |
||
101 | |||
102 | // Members: |
||
103 | bool |
||
104 | is_open(void) const { return _M_file ? _M_file->is_open() : false; } |
||
105 | |||
106 | __filebuf_type* |
||
107 | open(const char* __s, ios_base::openmode __mode); |
||
108 | |||
109 | __filebuf_type* |
||
110 | close(void); |
||
111 | |||
112 | protected: |
||
113 | void |
||
114 | _M_allocate_internal_buffer(); |
||
115 | |||
116 | void |
||
117 | _M_destroy_internal_buffer(); |
||
118 | |||
119 | void |
||
120 | _M_allocate_pback_buffer(); |
||
121 | |||
122 | // Create __file_type object and initialize it properly. |
||
123 | void |
||
124 | _M_allocate_file(); |
||
125 | |||
126 | // Overridden virtual functions: |
||
127 | virtual streamsize |
||
128 | showmanyc(void); |
||
129 | |||
130 | // Stroustrup, 1998, p. 628 |
||
131 | // underflow() and uflow() functions are called to get the next |
||
132 | // charater from the real input source when the buffer is empty. |
||
133 | // Buffered input uses underflow() |
||
134 | virtual int_type |
||
135 | underflow(void); |
||
136 | |||
137 | virtual int_type |
||
138 | pbackfail(int_type __c = _Traits::eof()); |
||
139 | |||
140 | // NB: For what the standard expects of the overflow function, |
||
141 | // see _M_really_overflow(), below. Because basic_streambuf's |
||
142 | // sputc/sputn call overflow directly, and the complications of |
||
143 | // this implementation's setting of the initial pointers all |
||
144 | // equal to _M_buf when initializing, it seems essential to have |
||
145 | // this in actuality be a helper function that checks for the |
||
146 | // eccentricities of this implementation, and then call |
||
147 | // overflow() if indeed the buffer is full. |
||
148 | virtual int_type |
||
149 | overflow(int_type __c = _Traits::eof()); |
||
150 | |||
151 | // Stroustrup, 1998, p 648 |
||
152 | // The overflow() function is called to transfer characters to the |
||
153 | // real output destination when the buffer is full. A call to |
||
154 | // overflow(c) outputs the contents of the buffer plus the |
||
155 | // character c. |
||
156 | // 27.5.2.4.5 |
||
157 | // Consume some sequence of the characters in the pending sequence. |
||
158 | int_type |
||
159 | _M_really_overflow(int_type __c = _Traits::eof()); |
||
160 | |||
161 | virtual __streambuf_type* |
||
162 | setbuf(char_type* __s, streamsize __n); |
||
163 | |||
164 | virtual pos_type |
||
165 | seekoff(off_type __off, ios_base::seekdir __way, |
||
166 | ios_base::openmode __mode = ios_base::in | ios_base::out); |
||
167 | |||
168 | virtual pos_type |
||
169 | seekpos(pos_type __pos, |
||
170 | ios_base::openmode __mode = ios_base::in | ios_base::out); |
||
171 | |||
172 | virtual int |
||
173 | sync(void) |
||
174 | { |
||
175 | bool __testput = _M_out_cur && _M_out_beg < _M_out_end; |
||
176 | if (__testput) |
||
177 | { |
||
178 | // Make sure that libio resyncs its idea of the file position |
||
179 | // with the external file. |
||
180 | _M_file->sync(); |
||
181 | |||
182 | // Need to restore current position. This interpreted as |
||
183 | // the position of the external byte sequence (_M_file) |
||
184 | // plus the offset in the current internal buffer |
||
185 | // (_M_out_beg - _M_out_cur) |
||
186 | streamoff __cur = _M_file->seekoff(0, ios_base::cur); |
||
187 | off_type __off = _M_out_cur - _M_out_beg; |
||
188 | _M_really_overflow(); |
||
189 | _M_file->seekpos(__cur + __off); |
||
190 | } |
||
191 | _M_last_overflowed = false; |
||
192 | return 0; |
||
193 | } |
||
194 | |||
195 | virtual void |
||
196 | imbue(const locale& __loc); |
||
197 | |||
198 | virtual streamsize |
||
199 | xsgetn(char_type* __s, streamsize __n) |
||
200 | { |
||
201 | streamsize __ret = 0; |
||
202 | // Clear out pback buffer before going on to the real deal... |
||
203 | if (_M_pback_init) |
||
204 | { |
||
205 | while (__ret < __n && _M_in_cur < _M_in_end) |
||
206 | { |
||
207 | *__s = *_M_in_cur; |
||
208 | ++__ret; |
||
209 | ++__s; |
||
210 | ++_M_in_cur; |
||
211 | } |
||
212 | _M_pback_destroy(); |
||
213 | } |
||
214 | if (__ret < __n) |
||
215 | __ret += __streambuf_type::xsgetn(__s, __n - __ret); |
||
216 | return __ret; |
||
217 | } |
||
218 | |||
219 | virtual streamsize |
||
220 | xsputn(const char_type* __s, streamsize __n) |
||
221 | { |
||
222 | _M_pback_destroy(); |
||
223 | return __streambuf_type::xsputn(__s, __n); |
||
224 | } |
||
225 | |||
226 | void |
||
227 | _M_output_unshift(); |
||
228 | }; |
||
229 | |||
230 | |||
231 | // 27.8.1.5 Template class basic_ifstream |
||
232 | template |
||
233 | class basic_ifstream : public basic_istream<_CharT, _Traits> |
||
234 | { |
||
235 | public: |
||
236 | // Types: |
||
237 | typedef _CharT char_type; |
||
238 | typedef _Traits traits_type; |
||
239 | typedef typename traits_type::int_type int_type; |
||
240 | typedef typename traits_type::pos_type pos_type; |
||
241 | typedef typename traits_type::off_type off_type; |
||
242 | |||
243 | // Non-standard types: |
||
244 | typedef basic_filebuf |
||
245 | typedef basic_istream |
||
246 | |||
247 | private: |
||
248 | __filebuf_type _M_filebuf; |
||
249 | |||
250 | public: |
||
251 | // Constructors/Destructors: |
||
252 | basic_ifstream() |
||
253 | : __istream_type(NULL), _M_filebuf() |
||
254 | { this->init(&_M_filebuf); } |
||
255 | |||
256 | explicit |
||
257 | basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in) |
||
258 | : __istream_type(NULL), _M_filebuf() |
||
259 | { |
||
260 | this->init(&_M_filebuf); |
||
261 | this->open(__s, __mode); |
||
262 | } |
||
263 | |||
264 | ~basic_ifstream() |
||
265 | { } |
||
266 | |||
267 | // Members: |
||
268 | __filebuf_type* |
||
269 | rdbuf() const |
||
270 | { return const_cast<__filebuf_type*>(&_M_filebuf); } |
||
271 | |||
272 | bool |
||
273 | is_open(void) { return _M_filebuf.is_open(); } |
||
274 | |||
275 | void |
||
276 | open(const char* __s, ios_base::openmode __mode = ios_base::in) |
||
277 | { |
||
278 | if (_M_filebuf.open(__s, __mode | ios_base::in) == NULL) |
||
279 | this->setstate(ios_base::failbit); |
||
280 | } |
||
281 | |||
282 | void |
||
283 | close(void) |
||
284 | { |
||
285 | if (!_M_filebuf.close()) |
||
286 | this->setstate(ios_base::failbit); |
||
287 | } |
||
288 | }; |
||
289 | |||
290 | |||
291 | // 27.8.1.8 Template class basic_ofstream |
||
292 | template |
||
293 | class basic_ofstream : public basic_ostream<_CharT,_Traits> |
||
294 | { |
||
295 | public: |
||
296 | // Types: |
||
297 | typedef _CharT char_type; |
||
298 | typedef _Traits traits_type; |
||
299 | typedef typename traits_type::int_type int_type; |
||
300 | typedef typename traits_type::pos_type pos_type; |
||
301 | typedef typename traits_type::off_type off_type; |
||
302 | |||
303 | // Non-standard types: |
||
304 | typedef basic_filebuf |
||
305 | typedef basic_ostream |
||
306 | |||
307 | private: |
||
308 | __filebuf_type _M_filebuf; |
||
309 | |||
310 | public: |
||
311 | // Constructors: |
||
312 | basic_ofstream() |
||
313 | : __ostream_type(NULL), _M_filebuf() |
||
314 | { this->init(&_M_filebuf); } |
||
315 | |||
316 | explicit |
||
317 | basic_ofstream(const char* __s, |
||
318 | ios_base::openmode __mode = ios_base::out|ios_base::trunc) |
||
319 | : __ostream_type(NULL), _M_filebuf() |
||
320 | { |
||
321 | this->init(&_M_filebuf); |
||
322 | this->open(__s, __mode); |
||
323 | } |
||
324 | |||
325 | ~basic_ofstream() |
||
326 | { } |
||
327 | |||
328 | // Members: |
||
329 | __filebuf_type* |
||
330 | rdbuf(void) const |
||
331 | { return const_cast<__filebuf_type*>(&_M_filebuf); } |
||
332 | |||
333 | bool |
||
334 | is_open(void) { return _M_filebuf.is_open(); } |
||
335 | |||
336 | void |
||
337 | open(const char* __s, |
||
338 | ios_base::openmode __mode = ios_base::out | ios_base::trunc) |
||
339 | { |
||
340 | if (!_M_filebuf.open(__s, __mode | ios_base::out)) |
||
341 | this->setstate(ios_base::failbit); |
||
342 | } |
||
343 | |||
344 | void |
||
345 | close(void) |
||
346 | { |
||
347 | if (!_M_filebuf.close()) |
||
348 | setstate(ios_base::failbit); |
||
349 | } |
||
350 | }; |
||
351 | |||
352 | |||
353 | // 27.8.1.11 Template class basic_fstream |
||
354 | template |
||
355 | class basic_fstream : public basic_iostream<_CharT, _Traits> |
||
356 | { |
||
357 | public: |
||
358 | // Types: |
||
359 | typedef _CharT char_type; |
||
360 | typedef _Traits traits_type; |
||
361 | typedef typename traits_type::int_type int_type; |
||
362 | typedef typename traits_type::pos_type pos_type; |
||
363 | typedef typename traits_type::off_type off_type; |
||
364 | |||
365 | // Non-standard types: |
||
366 | typedef basic_filebuf |
||
367 | typedef basic_ios |
||
368 | typedef basic_iostream |
||
369 | |||
370 | private: |
||
371 | __filebuf_type _M_filebuf; |
||
372 | |||
373 | public: |
||
374 | // Constructors/destructor: |
||
375 | basic_fstream() |
||
376 | : __iostream_type(NULL), _M_filebuf() |
||
377 | { this->init(&_M_filebuf); } |
||
378 | |||
379 | explicit |
||
380 | basic_fstream(const char* __s, |
||
381 | ios_base::openmode __mode = ios_base::in | ios_base::out) |
||
382 | : __iostream_type(NULL), _M_filebuf() |
||
383 | { |
||
384 | this->init(&_M_filebuf); |
||
385 | this->open(__s, __mode); |
||
386 | } |
||
387 | |||
388 | ~basic_fstream() |
||
389 | { } |
||
390 | |||
391 | // Members: |
||
392 | __filebuf_type* |
||
393 | rdbuf(void) const |
||
394 | { return const_cast<__filebuf_type*>(&_M_filebuf); } |
||
395 | |||
396 | bool |
||
397 | is_open(void) { return _M_filebuf.is_open(); } |
||
398 | |||
399 | void |
||
400 | open(const char* __s, |
||
401 | ios_base::openmode __mode = ios_base::in | ios_base::out) |
||
402 | { |
||
403 | if (!_M_filebuf.open(__s, __mode)) |
||
404 | setstate(ios_base::failbit); |
||
405 | } |
||
406 | |||
407 | void |
||
408 | close(void) |
||
409 | { |
||
410 | if (!_M_filebuf.close()) |
||
411 | setstate(ios_base::failbit); |
||
412 | } |
||
413 | }; |
||
414 | } // namespace std |
||
415 | |||
416 | |||
417 | #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT |
||
418 | # define export |
||
419 | #ifdef _GLIBCPP_FULLY_COMPLIANT_HEADERS |
||
420 | # include |
||
421 | #endif |
||
422 | #endif |
||
423 | |||
424 | #endif>>>> |
||
425 |