stringpool.c (stringpool_statistics): Also report number and percentage of entries...
[gcc.git] / libio / streambuf.cc
1 /* This is part of libio/iostream, providing -*- C++ -*- input/output.
2 Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation
3
4 This file is part of the GNU IO Library. This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
24
25 /* Written by Per Bothner (bothner@cygnus.com). */
26
27 #define _STREAM_COMPAT
28 #ifdef __GNUG__
29 #pragma implementation
30 #endif
31 #include "iostreamP.h"
32 #include <string.h>
33 #include <stdarg.h>
34 #include <errno.h>
35 #ifndef errno
36 extern int errno;
37 #endif
38
39 void streambuf::_un_link() { _IO_un_link(this); }
40
41 void streambuf::_link_in() { _IO_link_in(this); }
42
43 int streambuf::switch_to_get_mode()
44 { return _IO_switch_to_get_mode(this); }
45
46 void streambuf::free_backup_area()
47 { _IO_free_backup_area(this); }
48
49 #if 0
50 int streambuf::switch_to_put_mode()
51 { return _IO_:switch_to_put_mode(this); }
52 #endif
53
54 int __overflow(streambuf* sb, int c)
55 {
56 return sb->overflow(c);
57 }
58
59 int streambuf::underflow()
60 { return EOF; }
61
62 int streambuf::uflow()
63 { return _IO_default_uflow (this); }
64
65 int streambuf::overflow(int /* = EOF */)
66 { return EOF; }
67
68 streamsize streambuf::xsputn(register const char* s, streamsize n)
69 { return _IO_default_xsputn(this, s, n); }
70
71 streamsize streambuf::xsgetn(char* s, streamsize n)
72 { return _IO_default_xsgetn(this, s, n); }
73
74 int streambuf::ignore(int n)
75 {
76 register int more = n;
77 for (;;) {
78 int count = _IO_read_end - _IO_read_ptr; // Data available.
79 if (count > 0) {
80 if (count > more)
81 count = more;
82 _IO_read_ptr += count;
83 more -= count;
84 }
85 if (more == 0 || __underflow(this) == EOF)
86 break;
87 }
88 return n - more;
89 }
90
91 int streambuf::sync()
92 {
93 return 0;
94 }
95
96 int streambuf::pbackfail(int c)
97 {
98 return _IO_default_pbackfail(this, c);
99 }
100
101 streambuf* streambuf::setbuf(char* p, int len)
102 {
103 if (sync() == EOF)
104 return NULL;
105 if (p == NULL || len == 0) {
106 unbuffered(1);
107 setb(_shortbuf, _shortbuf+1, 0);
108 }
109 else {
110 unbuffered(0);
111 setb(p, p+len, 0);
112 }
113 setp(0, 0);
114 setg(0, 0, 0);
115 return this;
116 }
117
118 streampos streambuf::seekpos(streampos pos, int mode)
119 {
120 return seekoff(pos, ios::beg, mode);
121 }
122
123 streampos streambuf::sseekpos(streampos pos, int mode)
124 {
125 return _IO_seekpos (this, pos, mode);
126 }
127
128 void streambuf::setb(char* b, char* eb, int a)
129 { _IO_setb(this, b, eb, a); }
130
131 int streambuf::doallocate() { return _IO_default_doallocate(this); }
132
133 void streambuf::doallocbuf() { _IO_doallocbuf(this); }
134
135 #if !_IO_UNIFIED_JUMPTABLES
136 /* The following are jump table entries that just call the virtual method */
137
138 static int _IO_sb_overflow(_IO_FILE *fp, int c)
139 { return ((streambuf*)fp)->overflow(c); }
140 static int _IO_sb_underflow(_IO_FILE *fp)
141 { return ((streambuf*)fp)->underflow(); }
142 static _IO_size_t _IO_sb_xsputn(_IO_FILE *fp, const void *s, _IO_size_t n)
143 { return ((streambuf*)fp)->xsputn((const char*)s, n); }
144 static _IO_size_t _IO_sb_xsgetn(_IO_FILE *fp, void *s, _IO_size_t n)
145 { return ((streambuf*)fp)->xsgetn((char*)s, n); }
146 static int _IO_sb_close(_IO_FILE *fp)
147 { return ((streambuf*)fp)->sys_close(); }
148 static int _IO_sb_stat(_IO_FILE *fp, void *b)
149 { return ((streambuf*)fp)->sys_stat(b); }
150 static int _IO_sb_doallocate(_IO_FILE *fp)
151 { return ((streambuf*)fp)->doallocate(); }
152
153 static _IO_pos_t _IO_sb_seekoff(_IO_FILE *fp, _IO_off_t pos, int dir, int mode)
154 {
155 return ((streambuf*)fp)->seekoff(pos, (ios::seek_dir)dir, mode);
156 }
157
158 static _IO_pos_t _IO_sb_seekpos(_IO_FILE *fp, _IO_pos_t pos, int mode)
159 {
160 return ((streambuf*)fp)->seekpos(pos, mode);
161 }
162
163 static int _IO_sb_pbackfail(_IO_FILE *fp, int ch)
164 { return ((streambuf*)fp)->pbackfail(ch); }
165 static void _IO_sb_finish(_IO_FILE *fp, int)
166 { ((streambuf*)fp)->~streambuf(); }
167 static _IO_ssize_t _IO_sb_read(_IO_FILE *fp, void *buf, _IO_ssize_t n)
168 { return ((streambuf*)fp)->sys_read((char*)buf, n); }
169 static _IO_ssize_t _IO_sb_write(_IO_FILE *fp, const void *buf, _IO_ssize_t n)
170 { return ((streambuf*)fp)->sys_write((const char*)buf, n); }
171 static int _IO_sb_sync(_IO_FILE *fp)
172 { return ((streambuf*)fp)->sync(); }
173 static _IO_pos_t _IO_sb_seek(_IO_FILE *fp, _IO_off_t off, int dir)
174 { return ((streambuf*)fp)->sys_seek(off, (_seek_dir)dir); }
175 static _IO_FILE* _IO_sb_setbuf(_IO_FILE *fp, char *buf, _IO_ssize_t n)
176 { return ((streambuf*)fp)->setbuf(buf, n); }
177
178 /* This callbacks in this jumptable just call the corresponding
179 virtual function, so that C functions can access (potentially user-defined)
180 streambuf-derived objects.
181 Contrast the builtinbuf class, which does the converse: Allow
182 C++ virtual calls to be used on _IO_FILE objects that are builtin
183 (or defined by C code). */
184
185
186 struct _IO_jump_t _IO_streambuf_jumps = {
187 JUMP_INIT_DUMMY,
188 JUMP_INIT(finish, _IO_sb_finish),
189 JUMP_INIT(overflow, _IO_sb_overflow),
190 JUMP_INIT(underflow, _IO_sb_underflow),
191 JUMP_INIT(uflow, _IO_default_uflow),
192 JUMP_INIT(pbackfail, _IO_sb_pbackfail),
193 JUMP_INIT(xsputn, _IO_sb_xsputn),
194 JUMP_INIT(xsgetn, _IO_sb_xsgetn),
195 JUMP_INIT(seekoff, _IO_sb_seekoff),
196 JUMP_INIT(seekpos, _IO_sb_seekpos),
197 JUMP_INIT(setbuf, _IO_sb_setbuf),
198 JUMP_INIT(sync, _IO_sb_sync),
199 JUMP_INIT(doallocate, _IO_sb_doallocate),
200 JUMP_INIT(read, _IO_sb_read),
201 JUMP_INIT(write, _IO_sb_write),
202 JUMP_INIT(seek, _IO_sb_seek),
203 JUMP_INIT(close, _IO_sb_close),
204 JUMP_INIT(stat, _IO_sb_stat)
205 };
206 #endif
207
208 streambuf::streambuf(int flags)
209 {
210 #ifdef _IO_MTSAFE_IO
211 _lock = new _IO_lock_t;
212 #endif
213 _IO_init(this, flags);
214 #if !_IO_UNIFIED_JUMPTABLES
215 _jumps = &_IO_streambuf_jumps;
216 #endif
217 }
218
219 streambuf::~streambuf()
220 {
221 _IO_default_finish(this,0);
222 #ifdef _IO_MTSAFE_IO
223 if (this != _IO_stdin && this != _IO_stdout && this != _IO_stderr)
224 delete _lock;
225 #endif
226 }
227
228 streampos
229 streambuf::seekoff(streamoff, _seek_dir, int /*=ios::in|ios::out*/)
230 {
231 return EOF;
232 }
233
234 streampos
235 streambuf::sseekoff(streamoff o , _seek_dir d, int m /*=ios::in|ios::out*/)
236 {
237 return _IO_seekoff (this, o, d, m);
238 }
239
240 int streambuf::sputbackc(char c)
241 {
242 return _IO_sputbackc(this, c);
243 }
244
245 int streambuf::sungetc()
246 {
247 return _IO_sungetc(this);
248 }
249
250 #if 0 /* Work in progress */
251 void streambuf::collumn(int c)
252 {
253 if (c == -1)
254 _collumn = -1;
255 else
256 _collumn = c - (_IO_write_ptr - _IO_write_base);
257 }
258 #endif
259
260
261 int streambuf::get_column()
262 {
263 if (_cur_column)
264 return _IO_adjust_column(_cur_column - 1, pbase(), pptr() - pbase());
265 return -1;
266 }
267
268 int streambuf::set_column(int i)
269 {
270 _cur_column = i+1;
271 return 0;
272 }
273
274 int streambuf::flush_all() { return _IO_flush_all (); }
275
276 void streambuf::flush_all_linebuffered()
277 { _IO_flush_all_linebuffered(); }
278
279 int streambuf::sys_stat(void *)
280 {
281 #ifdef EIO
282 errno = EIO;
283 #endif
284 return -1;
285 }
286
287 streamsize streambuf::sys_read(char* /*buf*/, streamsize /*size*/)
288 {
289 return 0;
290 }
291
292 streamsize streambuf::sys_write(const char* /*buf*/, streamsize /*size*/)
293 {
294 return 0;
295 }
296
297 streampos streambuf::sys_seek(streamoff, _seek_dir)
298 {
299 return EOF;
300 }
301
302 int streambuf::sys_close() { return 0; /* Suceess; do nothing */ }
303
304 #if _G_IO_IO_FILE_VERSION == 0x20001
305 int streambuf::showmanyc()
306 {
307 return -1;
308 }
309
310 void streambuf::imbue(void *)
311 {
312 }
313 #endif
314
315 streammarker::streammarker(streambuf *sb)
316 {
317 _IO_init_marker(this, sb);
318 }
319
320 streammarker::~streammarker()
321 {
322 _IO_remove_marker(this);
323 }
324
325 #define BAD_DELTA EOF
326
327 int streammarker::delta(streammarker& other_mark)
328 {
329 return _IO_marker_difference(this, &other_mark);
330 }
331
332 int streammarker::delta()
333 {
334 return _IO_marker_delta(this);
335 }
336
337 int streambuf::seekmark(streammarker& mark, int delta /* = 0 */)
338 {
339 return _IO_seekmark(this, &mark, delta);
340 }
341
342 void streambuf::unsave_markers()
343 {
344 _IO_unsave_markers(this);
345 }
346
347 int ios::readable() { return !(rdbuf()->_flags & _IO_NO_READS); }
348 int ios::writable() { return !(rdbuf()->_flags & _IO_NO_WRITES); }
349 int ios::is_open() { return rdbuf()
350 && (rdbuf()->_flags & _IO_NO_READS+_IO_NO_WRITES)
351 != _IO_NO_READS+_IO_NO_WRITES; }
352
353 #if defined(linux)
354 #define IO_CLEANUP
355 #endif
356
357 #ifdef IO_CLEANUP
358 IO_CLEANUP
359 #else
360 struct __io_defs {
361 ~__io_defs() { _IO_cleanup (); }
362 };
363 __io_defs io_defs__;
364 #endif