]>
Commit | Line | Data |
---|---|---|
6599da04 | 1 | /* This is part of libio/iostream, providing -*- C++ -*- input/output. |
e693cc28 UD |
2 | Copyright (C) 1993, 1997 Free Software Foundation, Inc. |
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, | |
18 | USA. | |
19 | ||
20 | As a special exception, if you link this library with files | |
21 | compiled with a GNU compiler to produce an executable, this does not cause | |
22 | the resulting executable to be covered by the GNU General Public License. | |
23 | This exception does not however invalidate any other reasons why | |
24 | the executable file might be covered by the GNU General Public License. */ | |
6599da04 JM |
25 | |
26 | /* Written by Per Bothner (bothner@cygnus.com). */ | |
27 | ||
28 | #ifdef __GNUC__ | |
29 | #pragma implementation | |
30 | #endif | |
31 | #define _STREAM_COMPAT | |
32 | #include <iostream.h> | |
33 | #include "libioP.h" | |
34 | #include <stdio.h> /* Needed for sprintf */ | |
35 | #include <ctype.h> | |
36 | #include <string.h> | |
37 | #include <limits.h> | |
e693cc28 UD |
38 | |
39 | #if _G_HAVE_PRINTF_FP | |
40 | #include <printf.h> | |
41 | extern "C" int __printf_fp (_IO_FILE *, const struct printf_info *, | |
42 | const void *const *); | |
43 | #else | |
6599da04 | 44 | #include "floatio.h" |
6c1d5706 UD |
45 | # ifndef _IO_USE_DTOA |
46 | int __cvt_double(double number, register int prec, int flags, int *signp, | |
d604f4c6 | 47 | int fmtch, char *startp, char *endp); |
6c1d5706 | 48 | # endif |
e693cc28 | 49 | #endif |
6599da04 JM |
50 | |
51 | #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ | |
52 | ||
53 | //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n') | |
54 | ||
55 | istream::istream(streambuf *sb, ostream* tied) | |
56 | { | |
57 | init (sb, tied); | |
58 | _gcount = 0; | |
59 | } | |
60 | ||
61 | int skip_ws(streambuf* sb) | |
62 | { | |
63 | int ch; | |
64 | for (;;) { | |
65 | ch = sb->sbumpc(); | |
66 | if (ch == EOF || !isspace(ch)) | |
67 | return ch; | |
68 | } | |
69 | } | |
70 | ||
71 | istream& istream::get(char& c) | |
72 | { | |
73 | if (ipfx1()) { | |
74 | int ch = _strbuf->sbumpc(); | |
75 | if (ch == EOF) { | |
76 | set(ios::eofbit|ios::failbit); | |
77 | _gcount = 0; | |
78 | } | |
79 | else { | |
80 | c = (char)ch; | |
81 | _gcount = 1; | |
82 | } | |
83 | } | |
84 | else | |
85 | _gcount = 0; | |
86 | return *this; | |
87 | } | |
88 | ||
89 | int istream::peek() | |
90 | { | |
91 | if (!good()) | |
92 | return EOF; | |
93 | if (_tie && rdbuf()->in_avail() == 0) | |
94 | _tie->flush(); | |
95 | int ch = _strbuf->sgetc(); | |
96 | if (ch == EOF) | |
97 | set(ios::eofbit); | |
98 | return ch; | |
99 | } | |
100 | ||
101 | istream& istream::ignore(int n /* = 1 */, int delim /* = EOF */) | |
102 | { | |
103 | _gcount = 0; | |
104 | if (ipfx1()) { | |
105 | register streambuf* sb = _strbuf; | |
106 | if (delim == EOF) { | |
107 | _gcount = sb->ignore(n); | |
108 | return *this; | |
109 | } | |
110 | for (;;) { | |
111 | #if 0 | |
112 | if (n != MAXINT) // FIXME | |
113 | #endif | |
114 | if (--n < 0) | |
115 | break; | |
116 | int ch = sb->sbumpc(); | |
117 | if (ch == EOF) { | |
118 | set(ios::eofbit|ios::failbit); | |
119 | break; | |
120 | } | |
121 | _gcount++; | |
122 | if (ch == delim) | |
123 | break; | |
124 | } | |
125 | } | |
126 | return *this; | |
127 | } | |
128 | ||
129 | istream& istream::read(char *s, streamsize n) | |
130 | { | |
131 | if (ipfx1()) { | |
132 | _gcount = _strbuf->sgetn(s, n); | |
133 | if (_gcount != n) | |
134 | set(ios::failbit|ios::eofbit); | |
135 | } | |
136 | else | |
137 | _gcount = 0; | |
138 | return *this; | |
139 | } | |
140 | ||
141 | int | |
142 | istream::sync () | |
143 | { | |
144 | streambuf *sb = rdbuf (); | |
145 | if (sb == NULL) | |
146 | return EOF; | |
147 | if (sb->sync ()) // Later: pubsync | |
e693cc28 | 148 | { |
6599da04 JM |
149 | setstate (ios::badbit); |
150 | return EOF; | |
151 | } | |
152 | else | |
153 | return 0; | |
154 | } | |
155 | ||
156 | istream& istream::seekg(streampos pos) | |
157 | { | |
158 | pos = _strbuf->pubseekpos(pos, ios::in); | |
159 | if (pos == streampos(EOF)) | |
160 | set(ios::badbit); | |
161 | return *this; | |
162 | } | |
163 | ||
164 | istream& istream::seekg(streamoff off, _seek_dir dir) | |
165 | { | |
166 | streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_INPUT); | |
167 | if (pos == streampos(EOF)) | |
168 | set(ios::badbit); | |
169 | return *this; | |
170 | } | |
171 | ||
172 | streampos istream::tellg() | |
173 | { | |
174 | #if 0 | |
175 | streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::in); | |
176 | #else | |
177 | streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_INPUT); | |
178 | #endif | |
179 | if (pos == streampos(EOF)) | |
180 | set(ios::badbit); | |
181 | return pos; | |
182 | } | |
183 | ||
184 | istream& istream::operator>>(char& c) | |
185 | { | |
186 | if (ipfx0()) { | |
187 | int ch = _strbuf->sbumpc(); | |
188 | if (ch == EOF) | |
189 | set(ios::eofbit|ios::failbit); | |
190 | else | |
191 | c = (char)ch; | |
192 | } | |
193 | return *this; | |
194 | } | |
195 | ||
196 | istream& | |
197 | istream::operator>> (char* ptr) | |
198 | { | |
199 | register char *p = ptr; | |
200 | int w = width(0); | |
201 | if (ipfx0()) | |
202 | { | |
203 | register streambuf* sb = _strbuf; | |
204 | for (;;) | |
205 | { | |
206 | int ch = sb->sbumpc(); | |
207 | if (ch == EOF) | |
208 | { | |
209 | set(ios::eofbit); | |
210 | break; | |
211 | } | |
212 | else if (isspace(ch) || w == 1) | |
213 | { | |
214 | sb->sputbackc(ch); | |
215 | break; | |
216 | } | |
217 | else *p++ = ch; | |
218 | w--; | |
219 | } | |
220 | if (p == ptr) | |
221 | set(ios::failbit); | |
222 | } | |
223 | *p = '\0'; | |
224 | return *this; | |
225 | } | |
226 | ||
227 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | |
228 | #define LONGEST long long | |
229 | #else | |
230 | #define LONGEST long | |
231 | #endif | |
232 | ||
233 | static int read_int(istream& stream, unsigned LONGEST& val, int& neg) | |
234 | { | |
235 | if (!stream.ipfx0()) | |
236 | return 0; | |
237 | register streambuf* sb = stream.rdbuf(); | |
238 | int base = 10; | |
239 | int ndigits = 0; | |
240 | register int ch = skip_ws(sb); | |
241 | if (ch == EOF) | |
242 | goto eof_fail; | |
243 | neg = 0; | |
244 | if (ch == '+') { | |
245 | ch = skip_ws(sb); | |
246 | } | |
247 | else if (ch == '-') { | |
248 | neg = 1; | |
249 | ch = skip_ws(sb); | |
250 | } | |
251 | if (ch == EOF) goto eof_fail; | |
252 | if (!(stream.flags() & ios::basefield)) { | |
253 | if (ch == '0') { | |
254 | ch = sb->sbumpc(); | |
255 | if (ch == EOF) { | |
256 | val = 0; | |
257 | return 1; | |
258 | } | |
259 | if (ch == 'x' || ch == 'X') { | |
260 | base = 16; | |
261 | ch = sb->sbumpc(); | |
262 | if (ch == EOF) goto eof_fail; | |
263 | } | |
264 | else { | |
265 | sb->sputbackc(ch); | |
266 | base = 8; | |
267 | ch = '0'; | |
268 | } | |
269 | } | |
270 | } | |
271 | else if ((stream.flags() & ios::basefield) == ios::hex) | |
272 | base = 16; | |
273 | else if ((stream.flags() & ios::basefield) == ios::oct) | |
274 | base = 8; | |
275 | val = 0; | |
276 | for (;;) { | |
277 | if (ch == EOF) | |
278 | break; | |
279 | int digit; | |
280 | if (ch >= '0' && ch <= '9') | |
281 | digit = ch - '0'; | |
282 | else if (ch >= 'A' && ch <= 'F') | |
283 | digit = ch - 'A' + 10; | |
284 | else if (ch >= 'a' && ch <= 'f') | |
285 | digit = ch - 'a' + 10; | |
286 | else | |
287 | digit = 999; | |
288 | if (digit >= base) { | |
289 | sb->sputbackc(ch); | |
290 | if (ndigits == 0) | |
291 | goto fail; | |
292 | else | |
293 | return 1; | |
294 | } | |
295 | ndigits++; | |
296 | val = base * val + digit; | |
297 | ch = sb->sbumpc(); | |
298 | } | |
299 | return 1; | |
300 | fail: | |
301 | stream.set(ios::failbit); | |
302 | return 0; | |
303 | eof_fail: | |
304 | stream.set(ios::failbit|ios::eofbit); | |
305 | return 0; | |
306 | } | |
307 | ||
308 | #define READ_INT(TYPE) \ | |
309 | istream& istream::operator>>(TYPE& i)\ | |
310 | {\ | |
311 | unsigned LONGEST val; int neg;\ | |
312 | if (read_int(*this, val, neg)) {\ | |
313 | if (neg) val = -val;\ | |
314 | i = (TYPE)val;\ | |
315 | }\ | |
316 | return *this;\ | |
317 | } | |
318 | ||
319 | READ_INT(short) | |
320 | READ_INT(unsigned short) | |
321 | READ_INT(int) | |
322 | READ_INT(unsigned int) | |
323 | READ_INT(long) | |
324 | READ_INT(unsigned long) | |
325 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | |
326 | READ_INT(long long) | |
327 | READ_INT(unsigned long long) | |
328 | #endif | |
329 | #if _G_HAVE_BOOL | |
330 | READ_INT(bool) | |
331 | #endif | |
332 | ||
333 | istream& istream::operator>>(long double& x) | |
334 | { | |
335 | if (ipfx0()) | |
e693cc28 UD |
336 | #if _G_HAVE_LONG_DOUBLE_IO |
337 | scan("%Lg", &x); | |
338 | #else | |
6599da04 | 339 | scan("%lg", &x); |
e693cc28 | 340 | #endif |
6599da04 JM |
341 | return *this; |
342 | } | |
343 | ||
344 | istream& istream::operator>>(double& x) | |
345 | { | |
346 | if (ipfx0()) | |
347 | scan("%lg", &x); | |
348 | return *this; | |
349 | } | |
350 | ||
351 | istream& istream::operator>>(float& x) | |
352 | { | |
353 | if (ipfx0()) | |
354 | scan("%g", &x); | |
355 | return *this; | |
356 | } | |
357 | ||
358 | istream& istream::operator>>(register streambuf* sbuf) | |
359 | { | |
360 | if (ipfx0()) { | |
361 | register streambuf* inbuf = rdbuf(); | |
362 | // FIXME: Should optimize! | |
363 | for (;;) { | |
364 | register int ch = inbuf->sbumpc(); | |
365 | if (ch == EOF) { | |
366 | set(ios::eofbit); | |
367 | break; | |
368 | } | |
369 | if (sbuf->sputc(ch) == EOF) { | |
370 | set(ios::failbit); | |
371 | break; | |
372 | } | |
373 | } | |
374 | } | |
375 | return *this; | |
376 | } | |
377 | ||
378 | ostream& ostream::operator<<(char c) | |
379 | { | |
380 | if (opfx()) { | |
e693cc28 UD |
381 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
382 | _strbuf); | |
6599da04 JM |
383 | #if 1 |
384 | // This is what the cfront implementation does. | |
e693cc28 UD |
385 | if (_strbuf->sputc(c) == EOF) { |
386 | set(ios::badbit); | |
387 | goto failed; | |
388 | } | |
6599da04 JM |
389 | #else |
390 | // This is what cfront documentation and current ANSI drafts say. | |
391 | int w = width(0); | |
392 | char fill_char = fill(); | |
393 | register int padding = w > 0 ? w - 1 : 0; | |
394 | register streambuf *sb = _strbuf; | |
395 | if (!(flags() & ios::left) && padding) // Default adjustment. | |
e693cc28 UD |
396 | if (_IO_padn(sb, fill_char, padding) < padding) { |
397 | set(ios::badbit); | |
6599da04 | 398 | goto failed; |
e693cc28 UD |
399 | } |
400 | if (sb->sputc(c) == EOF) { | |
401 | set(ios::badbit); | |
6599da04 | 402 | goto failed; |
e693cc28 | 403 | } |
6599da04 JM |
404 | if (flags() & ios::left && padding) // Left adjustment. |
405 | if (_IO_padn(sb, fill_char, padding) < padding) | |
e693cc28 | 406 | set(ios::badbit); |
6599da04 | 407 | #endif |
e693cc28 | 408 | failed: |
6599da04 | 409 | osfx(); |
e693cc28 | 410 | _IO_cleanup_region_end (0); |
6599da04 JM |
411 | } |
412 | return *this; | |
6599da04 JM |
413 | } |
414 | ||
415 | /* Write VAL on STREAM. | |
416 | If SIGN<0, val is the absolute value of a negative number. | |
417 | If SIGN>0, val is a signed non-negative number. | |
418 | If SIGN==0, val is unsigned. */ | |
419 | ||
420 | static void write_int(ostream& stream, unsigned LONGEST val, int sign) | |
421 | { | |
422 | #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3) | |
423 | char buf[WRITE_BUF_SIZE]; | |
424 | register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf. | |
425 | const char *show_base = ""; | |
426 | int show_base_len = 0; | |
427 | int show_pos = 0; // If 1, print a '+'. | |
428 | ||
429 | // Now do the actual conversion, placing the result at the *end* of buf. | |
430 | // Note that we use separate code for decimal, octal, and hex, | |
431 | // so we can divide by optimizable constants. | |
432 | if ((stream.flags() & ios::basefield) == ios::oct) { // Octal | |
433 | do { | |
434 | *--buf_ptr = (val & 7) + '0'; | |
435 | val = val >> 3; | |
436 | } while (val != 0); | |
437 | if ((stream.flags() & ios::showbase) && (*buf_ptr != '0')) | |
438 | *--buf_ptr = '0'; | |
439 | } | |
440 | else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex | |
441 | const char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X" | |
442 | : "0123456789abcdef0x"; | |
443 | do { | |
444 | *--buf_ptr = xdigs[val & 15]; | |
445 | val = val >> 4; | |
446 | } while (val != 0); | |
447 | if ((stream.flags() & ios::showbase)) { | |
448 | show_base = xdigs + 16; // Either "0X" or "0x". | |
449 | show_base_len = 2; | |
450 | } | |
451 | } | |
452 | else { // Decimal | |
453 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | |
454 | // Optimization: Only use long long when we need to. | |
455 | while (val > UINT_MAX) { | |
456 | *--buf_ptr = (val % 10) + '0'; | |
457 | val /= 10; | |
458 | } | |
459 | // Use more efficient (int) arithmetic for the rest. | |
460 | register unsigned int ival = (unsigned int)val; | |
461 | #else | |
462 | register unsigned LONGEST ival = val; | |
463 | #endif | |
464 | do { | |
465 | *--buf_ptr = (ival % 10) + '0'; | |
466 | ival /= 10; | |
467 | } while (ival != 0); | |
468 | if (sign > 0 && (stream.flags() & ios::showpos)) | |
469 | show_pos=1; | |
470 | } | |
471 | ||
472 | int buf_len = buf+WRITE_BUF_SIZE - buf_ptr; | |
473 | int w = stream.width(0); | |
474 | ||
475 | // Calculate padding. | |
476 | int len = buf_len+show_pos; | |
477 | if (sign < 0) len++; | |
478 | len += show_base_len; | |
479 | int padding = len > w ? 0 : w - len; | |
480 | ||
481 | // Do actual output. | |
482 | register streambuf* sbuf = stream.rdbuf(); | |
483 | ios::fmtflags pad_kind = | |
484 | stream.flags() & (ios::left|ios::right|ios::internal); | |
485 | char fill_char = stream.fill(); | |
486 | if (padding > 0 | |
487 | && pad_kind != (ios::fmtflags)ios::left | |
488 | && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust. | |
489 | if (_IO_padn(sbuf, fill_char, padding) < padding) | |
490 | goto failed; | |
491 | if (sign < 0 || show_pos) | |
492 | { | |
493 | char ch = sign < 0 ? '-' : '+'; | |
494 | if (sbuf->sputc(ch) < 0) | |
495 | goto failed; | |
496 | } | |
497 | if (show_base_len) | |
498 | if (_IO_sputn(sbuf, show_base, show_base_len) <= 0) | |
499 | goto failed; | |
500 | if (pad_kind == (ios::fmtflags)ios::internal && padding > 0) | |
501 | if (_IO_padn(sbuf, fill_char, padding) < padding) | |
502 | goto failed; | |
503 | if (_IO_sputn (sbuf, buf_ptr, buf_len) != buf_len) | |
504 | goto failed; | |
505 | if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment | |
506 | if (_IO_padn(sbuf, fill_char, padding) < padding) | |
507 | goto failed; | |
508 | stream.osfx(); | |
509 | return; | |
510 | failed: | |
511 | stream.set(ios::badbit); | |
512 | stream.osfx(); | |
513 | } | |
514 | ||
515 | ostream& ostream::operator<<(int n) | |
516 | { | |
517 | if (opfx()) { | |
e693cc28 UD |
518 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
519 | _strbuf); | |
6599da04 JM |
520 | int sign = 1; |
521 | unsigned int abs_n = (unsigned)n; | |
522 | if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) | |
523 | abs_n = -((unsigned)n), sign = -1; | |
524 | write_int(*this, abs_n, sign); | |
e693cc28 | 525 | _IO_cleanup_region_end (0); |
6599da04 JM |
526 | } |
527 | return *this; | |
528 | } | |
529 | ||
530 | ostream& ostream::operator<<(unsigned int n) | |
531 | { | |
e693cc28 UD |
532 | if (opfx()) { |
533 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, | |
534 | _strbuf); | |
6599da04 | 535 | write_int(*this, n, 0); |
e693cc28 UD |
536 | _IO_cleanup_region_end (0); |
537 | } | |
6599da04 JM |
538 | return *this; |
539 | } | |
540 | ||
541 | ||
542 | ostream& ostream::operator<<(long n) | |
543 | { | |
544 | if (opfx()) { | |
e693cc28 UD |
545 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
546 | _strbuf); | |
6599da04 JM |
547 | int sign = 1; |
548 | unsigned long abs_n = (unsigned long)n; | |
549 | if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) | |
550 | abs_n = -((unsigned long)n), sign = -1; | |
551 | write_int(*this, abs_n, sign); | |
e693cc28 | 552 | _IO_cleanup_region_end (0); |
6599da04 JM |
553 | } |
554 | return *this; | |
555 | } | |
556 | ||
557 | ostream& ostream::operator<<(unsigned long n) | |
558 | { | |
e693cc28 UD |
559 | if (opfx()) { |
560 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, | |
561 | _strbuf); | |
6599da04 | 562 | write_int(*this, n, 0); |
e693cc28 UD |
563 | _IO_cleanup_region_end (0); |
564 | } | |
6599da04 JM |
565 | return *this; |
566 | } | |
567 | ||
568 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | |
569 | ostream& ostream::operator<<(long long n) | |
570 | { | |
571 | if (opfx()) { | |
e693cc28 UD |
572 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
573 | _strbuf); | |
6599da04 JM |
574 | int sign = 1; |
575 | unsigned long long abs_n = (unsigned long long)n; | |
576 | if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) | |
577 | abs_n = -((unsigned long long)n), sign = -1; | |
578 | write_int(*this, abs_n, sign); | |
e693cc28 | 579 | _IO_cleanup_region_end (0); |
6599da04 JM |
580 | } |
581 | return *this; | |
582 | } | |
583 | ||
584 | ||
585 | ostream& ostream::operator<<(unsigned long long n) | |
586 | { | |
e693cc28 UD |
587 | if (opfx()) { |
588 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, | |
589 | _strbuf); | |
6599da04 | 590 | write_int(*this, n, 0); |
e693cc28 UD |
591 | _IO_cleanup_region_end (0); |
592 | } | |
6599da04 JM |
593 | return *this; |
594 | } | |
595 | #endif /*__GNUC__*/ | |
596 | ||
597 | ostream& ostream::operator<<(double n) | |
598 | { | |
599 | if (opfx()) { | |
e693cc28 UD |
600 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
601 | _strbuf); | |
6599da04 JM |
602 | // Uses __cvt_double (renamed from static cvt), in Chris Torek's |
603 | // stdio implementation. The setup code uses the same logic | |
604 | // as in __vsbprintf.C (also based on Torek's code). | |
605 | int format_char; | |
606 | if ((flags() & ios::floatfield) == ios::fixed) | |
607 | format_char = 'f'; | |
608 | else if ((flags() & ios::floatfield) == ios::scientific) | |
609 | format_char = flags() & ios::uppercase ? 'E' : 'e'; | |
610 | else | |
611 | format_char = flags() & ios::uppercase ? 'G' : 'g'; | |
612 | ||
613 | int prec = precision(); | |
614 | if (prec <= 0 && !(flags() & ios::fixed)) | |
615 | prec = 6; /* default */ | |
616 | ||
617 | // Do actual conversion. | |
808d0b10 | 618 | #if _G_HAVE_PRINTF_FP |
e693cc28 UD |
619 | { |
620 | struct printf_info info = { prec: prec, | |
621 | width: width(0), | |
622 | spec: format_char, | |
623 | is_long_double: 0, | |
624 | is_short: 0, | |
625 | is_long: 0, | |
d604f4c6 | 626 | alt: (flags() & ios::showpoint) != 0, |
e693cc28 | 627 | space: 0, |
d604f4c6 UD |
628 | left: (flags() & ios::left) != 0, |
629 | showsign: (flags() & ios::showpos) != 0, | |
e693cc28 | 630 | group: 0, |
d604f4c6 UD |
631 | pad: fill() |
632 | #if defined __GLIBC__ && __GLIBC__ >= 2 | |
633 | , extra: 0 | |
634 | #endif | |
635 | }; | |
636 | const void *ptr = (const void *) &n; | |
e693cc28 UD |
637 | if (__printf_fp (rdbuf(), &info, &ptr) < 0) |
638 | set(ios::badbit|ios::failbit); | |
639 | } | |
640 | #elif defined _IO_USE_DTOA | |
6599da04 JM |
641 | if (_IO_outfloat(n, rdbuf(), format_char, width(0), |
642 | prec, flags(), | |
643 | flags() & ios::showpos ? '+' : 0, | |
644 | fill()) < 0) | |
645 | set(ios::badbit|ios::failbit); // ?? | |
646 | #else | |
647 | int fpprec = 0; // 'Extra' (suppressed) floating precision. | |
648 | if (prec > MAXFRACT) { | |
649 | if (flags() & (ios::fixed|ios::scientific) & ios::showpos) | |
650 | fpprec = prec - MAXFRACT; | |
651 | prec = MAXFRACT; | |
652 | } | |
653 | int negative; | |
654 | char buf[BUF]; | |
655 | int sign = '\0'; | |
656 | char *cp = buf; | |
657 | *cp = 0; | |
658 | int size = __cvt_double(n, prec, | |
659 | flags() & ios::showpoint ? 0x80 : 0, | |
660 | &negative, | |
661 | format_char, cp, buf + sizeof(buf)); | |
662 | if (negative) sign = '-'; | |
663 | else if (flags() & ios::showpos) sign = '+'; | |
664 | if (*cp == 0) | |
665 | cp++; | |
666 | ||
667 | // Calculate padding. | |
668 | int fieldsize = size + fpprec; | |
669 | if (sign) fieldsize++; | |
670 | int padding = 0; | |
671 | int w = width(0); | |
672 | if (fieldsize < w) | |
673 | padding = w - fieldsize; | |
674 | ||
675 | // Do actual output. | |
676 | register streambuf* sbuf = rdbuf(); | |
677 | register i; | |
678 | char fill_char = fill(); | |
679 | ios::fmtflags pad_kind = | |
680 | flags() & (ios::left|ios::right|ios::internal); | |
681 | if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust. | |
682 | && pad_kind != (ios::fmtflags)ios::internal) | |
683 | for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); | |
684 | if (sign) | |
685 | sbuf->sputc(sign); | |
686 | if (pad_kind == (ios::fmtflags)ios::internal) | |
687 | for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); | |
e693cc28 | 688 | |
6599da04 JM |
689 | // Emit the actual concented field, followed by extra zeros. |
690 | _IO_sputn (sbuf, cp, size); | |
691 | for (i = fpprec; --i >= 0; ) sbuf->sputc('0'); | |
692 | ||
693 | if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment | |
694 | for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); | |
695 | #endif | |
696 | osfx(); | |
e693cc28 | 697 | _IO_cleanup_region_end (0); |
6599da04 JM |
698 | } |
699 | return *this; | |
700 | } | |
701 | ||
e693cc28 UD |
702 | #if _G_HAVE_LONG_DOUBLE_IO |
703 | ostream& ostream::operator<<(long double n) | |
704 | { | |
705 | if (opfx()) | |
706 | { | |
707 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, | |
708 | _strbuf); | |
709 | int format_char; | |
710 | if ((flags() & ios::floatfield) == ios::fixed) | |
711 | format_char = 'f'; | |
712 | else if ((flags() & ios::floatfield) == ios::scientific) | |
713 | format_char = flags() & ios::uppercase ? 'E' : 'e'; | |
714 | else | |
715 | format_char = flags() & ios::uppercase ? 'G' : 'g'; | |
716 | ||
717 | int prec = precision(); | |
718 | if (prec <= 0 && !(flags() & ios::fixed)) | |
719 | prec = 6; /* default */ | |
720 | ||
c44e099f | 721 | #if _G_HAVE_PRINTF_FP |
e693cc28 UD |
722 | // Do actual conversion. |
723 | struct printf_info info = { prec: prec, | |
724 | width: width(0), | |
725 | spec: format_char, | |
726 | is_long_double: 1, | |
727 | is_short: 0, | |
728 | is_long: 0, | |
d604f4c6 | 729 | alt: (flags() & ios::showpoint) != 0, |
e693cc28 | 730 | space: 0, |
d604f4c6 UD |
731 | left: (flags() & ios::left) != 0, |
732 | showsign: (flags() & ios::showpos) != 0, | |
e693cc28 | 733 | group: 0, |
d604f4c6 UD |
734 | pad: fill() |
735 | #if defined __GLIBC__ && __GLIBC__ >= 2 | |
736 | , extra: 0 | |
737 | #endif | |
738 | }; | |
e693cc28 | 739 | |
d604f4c6 | 740 | const void *ptr = (const void *) &n; |
e693cc28 UD |
741 | |
742 | if (__printf_fp (rdbuf(), &info, &ptr) < 0) | |
743 | set (ios::badbit|ios::failbit); | |
744 | #else | |
745 | # error "long double I/O using dtoa or cvt_double is not implemented" | |
746 | #endif | |
747 | osfx(); | |
748 | _IO_cleanup_region_end (0); | |
749 | } | |
750 | return *this; | |
751 | } | |
752 | #endif | |
753 | ||
6599da04 JM |
754 | ostream& ostream::operator<<(const char *s) |
755 | { | |
756 | if (opfx()) | |
757 | { | |
e693cc28 UD |
758 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
759 | _strbuf); | |
6599da04 JM |
760 | if (s == NULL) |
761 | s = "(null)"; | |
762 | int len = strlen(s); | |
763 | int w = width(0); | |
764 | // FIXME: Should we: if (w && len>w) len = w; | |
765 | char fill_char = fill(); | |
766 | register streambuf *sbuf = rdbuf(); | |
767 | register int padding = w > len ? w - len : 0; | |
768 | if (!(flags() & ios::left) && padding > 0) // Default adjustment. | |
769 | if (_IO_padn(sbuf, fill_char, padding) != padding) | |
e693cc28 UD |
770 | { |
771 | set(ios::badbit); | |
772 | goto failed; | |
773 | } | |
6599da04 | 774 | if (_IO_sputn (sbuf, s, len) != len) |
e693cc28 UD |
775 | { |
776 | set(ios::badbit); | |
777 | goto failed; | |
778 | } | |
6599da04 JM |
779 | if (flags() & ios::left && padding > 0) // Left adjustment. |
780 | if (_IO_padn(sbuf, fill_char, padding) != padding) | |
e693cc28 | 781 | set(ios::badbit); |
6599da04 | 782 | osfx(); |
e693cc28 UD |
783 | failed: |
784 | _IO_cleanup_region_end (0); | |
6599da04 JM |
785 | } |
786 | return *this; | |
6599da04 JM |
787 | } |
788 | ||
789 | #if 0 | |
790 | ostream& ostream::operator<<(const void *p) | |
791 | { Is in osform.cc, to avoid pulling in all of _IO_vfprintf by this file. */ } | |
792 | #endif | |
793 | ||
794 | ostream& ostream::operator<<(register streambuf* sbuf) | |
795 | { | |
796 | if (opfx()) | |
797 | { | |
e693cc28 UD |
798 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
799 | _strbuf); | |
6599da04 JM |
800 | char buffer[_IO_BUFSIZ]; |
801 | register streambuf* outbuf = _strbuf; | |
802 | for (;;) | |
803 | { | |
804 | _IO_size_t count = _IO_sgetn(sbuf, buffer, _IO_BUFSIZ); | |
805 | if (count <= 0) | |
806 | break; | |
807 | if (_IO_sputn(outbuf, buffer, count) != count) | |
808 | { | |
809 | set(ios::badbit); | |
810 | break; | |
811 | } | |
812 | } | |
813 | osfx(); | |
e693cc28 | 814 | _IO_cleanup_region_end (0); |
6599da04 JM |
815 | } |
816 | return *this; | |
817 | } | |
818 | ||
819 | ostream::ostream(streambuf* sb, ostream* tied) | |
820 | { | |
821 | init (sb, tied); | |
822 | } | |
823 | ||
824 | ostream& ostream::seekp(streampos pos) | |
825 | { | |
826 | pos = _strbuf->pubseekpos(pos, ios::out); | |
827 | if (pos == streampos(EOF)) | |
828 | set(ios::badbit); | |
829 | return *this; | |
830 | } | |
831 | ||
832 | ostream& ostream::seekp(streamoff off, _seek_dir dir) | |
833 | { | |
834 | streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_OUTPUT); | |
835 | if (pos == streampos(EOF)) | |
836 | set(ios::badbit); | |
837 | return *this; | |
838 | } | |
839 | ||
840 | streampos ostream::tellp() | |
841 | { | |
842 | #if 1 | |
843 | streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_OUTPUT); | |
844 | #else | |
845 | streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::out); | |
846 | #endif | |
847 | if (pos == streampos(EOF)) | |
848 | set(ios::badbit); | |
849 | return pos; | |
850 | } | |
851 | ||
852 | ostream& ostream::flush() | |
853 | { | |
854 | if (_strbuf->sync()) | |
855 | set(ios::badbit); | |
856 | return *this; | |
857 | } | |
858 | ||
859 | ostream& flush(ostream& outs) | |
860 | { | |
861 | return outs.flush(); | |
862 | } | |
863 | ||
864 | istream& ws(istream& ins) | |
865 | { | |
866 | if (ins.ipfx1()) { | |
e693cc28 UD |
867 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
868 | ins._strbuf); | |
6599da04 JM |
869 | int ch = skip_ws(ins._strbuf); |
870 | if (ch == EOF) | |
871 | ins.set(ios::eofbit); | |
872 | else | |
873 | ins._strbuf->sputbackc(ch); | |
e693cc28 UD |
874 | ins.isfx(); |
875 | _IO_cleanup_region_end (0); | |
6599da04 JM |
876 | } |
877 | return ins; | |
878 | } | |
879 | ||
880 | // Skip white-space. Return 0 on failure (EOF), or 1 on success. | |
881 | // Differs from ws() manipulator in that failbit is set on EOF. | |
882 | // Called by ipfx() and ipfx0() if needed. | |
883 | ||
884 | int istream::_skip_ws() | |
885 | { | |
886 | int ch = skip_ws(_strbuf); | |
887 | if (ch == EOF) { | |
888 | set(ios::eofbit|ios::failbit); | |
889 | return 0; | |
890 | } | |
891 | else { | |
892 | _strbuf->sputbackc(ch); | |
893 | return 1; | |
894 | } | |
895 | } | |
896 | ||
897 | ostream& ends(ostream& outs) | |
898 | { | |
899 | outs.put('\0'); | |
900 | return outs; | |
901 | } | |
902 | ||
903 | ostream& endl(ostream& outs) | |
904 | { | |
905 | return flush(outs.put('\n')); | |
906 | } | |
907 | ||
e693cc28 UD |
908 | istream& lock(istream& ins) |
909 | { | |
910 | _IO_flockfile (ins._strbuf); | |
911 | return ins; | |
912 | } | |
913 | istream& unlock(istream& ins) | |
914 | { | |
915 | _IO_funlockfile (ins._strbuf); | |
916 | return ins; | |
917 | } | |
918 | ostream& lock(ostream& outs) | |
919 | { | |
920 | _IO_flockfile (outs._strbuf); | |
921 | return outs; | |
922 | } | |
923 | ostream& unlock(ostream& outs) | |
924 | { | |
925 | _IO_funlockfile (outs._strbuf); | |
926 | return outs; | |
927 | } | |
928 | ||
929 | ||
6599da04 JM |
930 | ostream& ostream::write(const char *s, streamsize n) |
931 | { | |
932 | if (opfx()) { | |
e693cc28 UD |
933 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
934 | _strbuf); | |
6599da04 JM |
935 | if (_IO_sputn(_strbuf, s, n) != n) |
936 | set(ios::failbit); | |
e693cc28 UD |
937 | osfx(); |
938 | _IO_cleanup_region_end (0); | |
6599da04 JM |
939 | } |
940 | return *this; | |
941 | } | |
942 | ||
943 | void ostream::do_osfx() | |
944 | { | |
945 | if (flags() & ios::unitbuf) | |
946 | flush(); | |
947 | if (flags() & ios::stdio) { | |
948 | fflush(stdout); | |
949 | fflush(stderr); | |
950 | } | |
951 | } | |
952 | ||
953 | iostream::iostream(streambuf* sb, ostream* tied) | |
954 | { | |
955 | init (sb, tied); | |
956 | } | |
957 | ||
958 | // NOTE: extension for compatibility with old libg++. | |
959 | // Not really compatible with fistream::close(). | |
960 | #ifdef _STREAM_COMPAT | |
961 | void ios::close() | |
962 | { | |
963 | if (_strbuf->_flags & _IO_IS_FILEBUF) | |
964 | ((struct filebuf*)rdbuf())->close(); | |
965 | else if (_strbuf != NULL) | |
966 | rdbuf()->sync(); | |
967 | _strbuf = NULL; | |
968 | _state = badbit; | |
969 | } | |
970 | ||
971 | int istream::skip(int i) | |
972 | { | |
973 | int old = (_flags & ios::skipws) != 0; | |
974 | if (i) | |
975 | _flags |= ios::skipws; | |
976 | else | |
977 | _flags &= ~ios::skipws; | |
978 | return old; | |
979 | } | |
980 | #endif |