1 /* Copyright (C) 1993, 1995, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
2 This file is part of the GNU IO Library.
3 Written by Ulrich Drepper <drepper@cygnus.com>.
4 Based on the single byte version by Per Bothner <bothner@cygnus.com>.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2, or (at
9 your option) any later version.
11 This library is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this library; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
21 As a special exception, if you link this library with files
22 compiled with a GNU compiler to produce an executable, this does
23 not cause the resulting executable to be covered by the GNU General
24 Public License. This exception does not however invalidate any
25 other reasons why the executable file might be covered by the GNU
26 General Public License. */
28 /* Generic or default I/O operations. */
39 # define __wmemcpy(dst, src, n) wmemcpy (dst, src, n)
43 static int save_for_wbackup
__P ((_IO_FILE
*fp
, wchar_t *end_p
))
49 /* Return minimum _pos markers
50 Assumes the current get area is the main get area. */
51 _IO_ssize_t _IO_least_wmarker
__P ((_IO_FILE
*fp
, wchar_t *end_p
));
54 _IO_least_wmarker (fp
, end_p
)
58 _IO_ssize_t least_so_far
= end_p
- fp
->_wide_data
->_IO_read_base
;
59 struct _IO_marker
*mark
;
60 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
61 if (mark
->_pos
< least_so_far
)
62 least_so_far
= mark
->_pos
;
66 /* Switch current get area from backup buffer to (start of) main get area. */
68 _IO_switch_to_main_wget_area (fp
)
72 fp
->_flags
&= ~_IO_IN_BACKUP
;
73 /* Swap _IO_read_end and _IO_save_end. */
74 tmp
= fp
->_wide_data
->_IO_read_end
;
75 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
76 fp
->_wide_data
->_IO_save_end
= tmp
;
77 /* Swap _IO_read_base and _IO_save_base. */
78 tmp
= fp
->_wide_data
->_IO_read_base
;
79 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
80 fp
->_wide_data
->_IO_save_base
= tmp
;
81 /* Set _IO_read_ptr. */
82 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_base
;
86 /* Switch current get area from main get area to (end of) backup area. */
88 _IO_switch_to_wbackup_area (fp
)
92 fp
->_flags
|= _IO_IN_BACKUP
;
93 /* Swap _IO_read_end and _IO_save_end. */
94 tmp
= fp
->_wide_data
->_IO_read_end
;
95 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
96 fp
->_wide_data
->_IO_save_end
= tmp
;
97 /* Swap _IO_read_base and _IO_save_base. */
98 tmp
= fp
->_wide_data
->_IO_read_base
;
99 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
100 fp
->_wide_data
->_IO_save_base
= tmp
;
101 /* Set _IO_read_ptr. */
102 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
107 _IO_wsetb (f
, b
, eb
, a
)
113 if (f
->_wide_data
->_IO_buf_base
&& !(f
->_flags
& _IO_USER_BUF
))
114 FREE_BUF (f
->_wide_data
->_IO_buf_base
, _IO_wblen (f
));
115 f
->_wide_data
->_IO_buf_base
= b
;
116 f
->_wide_data
->_IO_buf_end
= eb
;
118 f
->_flags
&= ~_IO_USER_BUF
;
120 f
->_flags
|= _IO_USER_BUF
;
125 _IO_wdefault_pbackfail (fp
, c
)
129 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
130 && !_IO_in_backup (fp
)
131 && (wint_t) fp
->_IO_read_ptr
[-1] == c
)
135 /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
136 if (!_IO_in_backup (fp
))
138 /* We need to keep the invariant that the main get area
139 logically follows the backup area. */
140 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
141 && _IO_have_wbackup (fp
))
143 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_ptr
))
146 else if (!_IO_have_wbackup (fp
))
148 /* No backup buffer: allocate one. */
149 /* Use nshort buffer, if unused? (probably not) FIXME */
150 int backup_size
= 128;
151 wchar_t *bbuf
= (wchar_t *) malloc (backup_size
155 fp
->_wide_data
->_IO_save_base
= bbuf
;
156 fp
->_wide_data
->_IO_save_end
= (fp
->_wide_data
->_IO_save_base
158 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_end
;
160 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
;
161 _IO_switch_to_wbackup_area (fp
);
163 else if (fp
->_wide_data
->_IO_read_ptr
<= fp
->_wide_data
->_IO_read_base
)
165 /* Increase size of existing backup buffer. */
167 _IO_size_t old_size
= (fp
->_wide_data
->_IO_read_end
168 - fp
->_wide_data
->_IO_read_base
);
170 new_size
= 2 * old_size
;
171 new_buf
= (wchar_t *) malloc (new_size
* sizeof (wchar_t));
174 __wmemcpy (new_buf
+ (new_size
- old_size
),
175 fp
->_wide_data
->_IO_read_base
, old_size
);
176 free (fp
->_wide_data
->_IO_read_base
);
177 _IO_wsetg (fp
, new_buf
, new_buf
+ (new_size
- old_size
),
179 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_read_ptr
;
182 *--fp
->_wide_data
->_IO_read_ptr
= c
;
189 _IO_wdefault_finish (fp
, dummy
)
193 struct _IO_marker
*mark
;
194 if (fp
->_wide_data
->_IO_buf_base
&& !(fp
->_flags
& _IO_USER_BUF
))
196 FREE_BUF (fp
->_wide_data
->_IO_buf_base
,
197 _IO_wblen (fp
) * sizeof (wchar_t));
198 fp
->_wide_data
->_IO_buf_base
= fp
->_wide_data
->_IO_buf_end
= NULL
;
201 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
204 if (fp
->_IO_save_base
)
206 free (fp
->_wide_data
->_IO_save_base
);
207 fp
->_IO_save_base
= NULL
;
211 _IO_lock_fini (*fp
->_lock
);
214 _IO_un_link ((struct _IO_FILE_plus
*) fp
);
219 _IO_wdefault_uflow (fp
)
223 wch
= _IO_UNDERFLOW (fp
);
226 return *fp
->_wide_data
->_IO_read_ptr
++;
237 return _IO_OVERFLOW (f
, wch
);
245 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
250 if (_IO_in_put_mode (fp
))
251 if (_IO_switch_to_wget_mode (fp
) == EOF
)
253 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
254 return *fp
->_wide_data
->_IO_read_ptr
++;
255 if (_IO_in_backup (fp
))
257 _IO_switch_to_main_wget_area (fp
);
258 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
259 return *fp
->_wide_data
->_IO_read_ptr
++;
261 if (_IO_have_markers (fp
))
263 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
266 else if (_IO_have_wbackup (fp
))
267 _IO_free_wbackup_area (fp
);
268 return _IO_UFLOW (fp
);
276 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
281 if (_IO_in_put_mode (fp
))
282 if (_IO_switch_to_wget_mode (fp
) == EOF
)
284 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
285 return *fp
->_wide_data
->_IO_read_ptr
;
286 if (_IO_in_backup (fp
))
288 _IO_switch_to_main_wget_area (fp
);
289 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
290 return *fp
->_wide_data
->_IO_read_ptr
;
292 if (_IO_have_markers (fp
))
294 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
297 else if (_IO_have_backup (fp
))
298 _IO_free_wbackup_area (fp
);
299 return _IO_UNDERFLOW (fp
);
304 _IO_wdefault_xsputn (f
, data
, n
)
309 const wchar_t *s
= (const wchar_t *) data
;
315 /* Space available. */
316 _IO_ssize_t count
= (f
->_wide_data
->_IO_write_end
317 - f
->_wide_data
->_IO_write_ptr
);
320 if ((_IO_size_t
) count
> more
)
325 f
->_wide_data
->_IO_write_ptr
=
326 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
328 memcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
329 f
->_wide_data
->_IO_write_ptr
+= count
;
337 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
339 for (i
= count
; --i
>= 0; )
341 f
->_wide_data
->_IO_write_ptr
= p
;
345 if (more
== 0 || __woverflow (f
, *s
++) == WEOF
)
354 _IO_wdefault_xsgetn (fp
, data
, n
)
360 wchar_t *s
= (wchar_t*) data
;
363 /* Data available. */
364 _IO_ssize_t count
= (fp
->_wide_data
->_IO_read_end
365 - fp
->_wide_data
->_IO_read_ptr
);
368 if ((_IO_size_t
) count
> more
)
373 s
= __wmempcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
375 memcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
378 fp
->_wide_data
->_IO_read_ptr
+= count
;
384 wchar_t *p
= fp
->_wide_data
->_IO_read_ptr
;
388 fp
->_wide_data
->_IO_read_ptr
= p
;
392 if (more
== 0 || __wunderflow (fp
) == WEOF
)
403 if (fp
->_wide_data
->_IO_buf_base
)
405 if (!(fp
->_flags
& _IO_UNBUFFERED
))
406 if (_IO_DOALLOCATE (fp
) != WEOF
)
408 _IO_wsetb (fp
, fp
->_wide_data
->_shortbuf
, fp
->_wide_data
->_shortbuf
+ 1, 0);
413 _IO_wdefault_setbuf (fp
, p
, len
)
418 if (_IO_SYNC (fp
) == EOF
)
420 if (p
== NULL
|| len
== 0)
422 fp
->_flags
|= _IO_UNBUFFERED
;
423 _IO_wsetb (fp
, fp
->_wide_data
->_shortbuf
, fp
->_wide_data
->_shortbuf
+ 1,
428 fp
->_flags
&= ~_IO_UNBUFFERED
;
429 _IO_wsetb (fp
, p
, p
+ len
, 0);
431 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
432 = fp
->_wide_data
->_IO_write_end
= 0;
433 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
434 = fp
->_wide_data
->_IO_read_end
= 0;
440 _IO_wdefault_doallocate (fp
)
445 ALLOC_WBUF (buf
, _IO_BUFSIZ
, EOF
);
446 _IO_wsetb (fp
, buf
, buf
+ _IO_BUFSIZ
, 1);
452 _IO_switch_to_wget_mode (fp
)
455 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
456 if (_IO_OVERFLOW (fp
, WEOF
) == WEOF
)
458 if (_IO_in_backup (fp
))
459 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_backup_base
;
462 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_buf_base
;
463 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_read_end
)
464 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
466 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_write_ptr
;
468 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
469 = fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_read_ptr
;
471 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
476 _IO_free_wbackup_area (fp
)
479 if (_IO_in_backup (fp
))
480 _IO_switch_to_main_wget_area (fp
); /* Just in case. */
481 free (fp
->_wide_data
->_IO_save_base
);
482 fp
->_wide_data
->_IO_save_base
= NULL
;
483 fp
->_wide_data
->_IO_save_end
= NULL
;
484 fp
->_wide_data
->_IO_backup_base
= NULL
;
489 _IO_switch_to_wput_mode (fp
)
492 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_read_ptr
;
493 fp
->_wide_data
->_IO_write_ptr
= fp
->_wide_data
->_IO_read_ptr
;
494 /* Following is wrong if line- or un-buffered? */
495 fp
->_wide_data
->_IO_write_end
= (fp
->_flags
& _IO_IN_BACKUP
496 ? fp
->_wide_data
->_IO_read_end
497 : fp
->_wide_data
->_IO_buf_end
);
499 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
500 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_end
;
502 fp
->_flags
|= _IO_CURRENTLY_PUTTING
;
512 save_for_wbackup (fp
, end_p
)
516 /* Append [_IO_read_base..end_p] to backup area. */
517 _IO_ssize_t least_mark
= _IO_least_wmarker (fp
, end_p
);
518 /* needed_size is how much space we need in the backup area. */
519 _IO_size_t needed_size
= ((end_p
- fp
->_wide_data
->_IO_read_base
)
521 /* FIXME: Dubious arithmetic if pointers are NULL */
522 _IO_size_t current_Bsize
= (fp
->_wide_data
->_IO_save_end
523 - fp
->_wide_data
->_IO_save_base
);
524 _IO_size_t avail
; /* Extra space available for future expansion. */
526 struct _IO_marker
*mark
;
527 if (needed_size
> current_Bsize
)
531 new_buffer
= (wchar_t *) malloc ((avail
+ needed_size
)
533 if (new_buffer
== NULL
)
534 return EOF
; /* FIXME */
538 __wmempcpy (__wmempcpy (new_buffer
+ avail
,
539 fp
->_wide_data
->_IO_save_end
+ least_mark
,
541 fp
->_wide_data
->_IO_read_base
,
542 end_p
- fp
->_wide_data
->_IO_read_base
);
544 memcpy (new_buffer
+ avail
,
545 fp
->_wide_data
->_IO_save_end
+ least_mark
,
546 -least_mark
* sizeof (wchar_t));
547 memcpy (new_buffer
+ avail
- least_mark
,
548 fp
->_wide_data
->_IO_read_base
,
549 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
555 __wmemcpy (new_buffer
+ avail
,
556 fp
->_wide_data
->_IO_read_base
+ least_mark
,
559 memcpy (new_buffer
+ avail
,
560 fp
->_wide_data
->_IO_read_base
+ least_mark
,
561 needed_size
* sizeof (wchar_t));
564 if (fp
->_wide_data
->_IO_save_base
)
565 free (fp
->_wide_data
->_IO_save_base
);
566 fp
->_wide_data
->_IO_save_base
= new_buffer
;
567 fp
->_wide_data
->_IO_save_end
= new_buffer
+ avail
+ needed_size
;
571 avail
= current_Bsize
- needed_size
;
575 __wmemmove (fp
->_wide_data
->_IO_save_base
+ avail
,
576 fp
->_wide_data
->_IO_save_end
+ least_mark
,
578 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
579 fp
->_wide_data
->_IO_read_base
,
580 end_p
- fp
->_wide_data
->_IO_read_base
);
582 memmove (fp
->_wide_data
->_IO_save_base
+ avail
,
583 fp
->_wide_data
->_IO_save_end
+ least_mark
,
584 -least_mark
* sizeof (wchar_t));
585 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
586 fp
->_wide_data
->_IO_read_base
,
587 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
590 else if (needed_size
> 0)
592 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
593 fp
->_wide_data
->_IO_read_base
+ least_mark
,
596 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
597 fp
->_wide_data
->_IO_read_base
+ least_mark
,
598 needed_size
* sizeof (wchar_t));
601 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_base
+ avail
;
602 /* Adjust all the streammarkers. */
603 delta
= end_p
- fp
->_wide_data
->_IO_read_base
;
604 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
610 _IO_sputbackwc (fp
, c
)
616 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
617 && (wchar_t)fp
->_wide_data
->_IO_read_ptr
[-1] == (wchar_t) c
)
619 fp
->_wide_data
->_IO_read_ptr
--;
623 result
= _IO_PBACKFAIL (fp
, c
);
626 fp
->_flags
&= ~_IO_EOF_SEEN
;
637 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
)
639 fp
->_wide_data
->_IO_read_ptr
--;
640 result
= *fp
->_wide_data
->_IO_read_ptr
;
643 result
= _IO_PBACKFAIL (fp
, EOF
);
646 fp
->_flags
&= ~_IO_EOF_SEEN
;
653 _IO_adjust_wcolumn (start
, line
, count
)
658 const wchar_t *ptr
= line
+ count
;
661 return line
+ count
- ptr
- 1;
662 return start
+ count
;
666 _IO_init_wmarker (marker
, fp
)
667 struct _IO_marker
*marker
;
671 if (_IO_in_put_mode (fp
))
672 _IO_switch_to_wget_mode (fp
);
673 if (_IO_in_backup (fp
))
674 marker
->_pos
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
676 marker
->_pos
= (fp
->_wide_data
->_IO_read_ptr
677 - fp
->_wide_data
->_IO_read_base
);
679 /* Should perhaps sort the chain? */
680 marker
->_next
= fp
->_markers
;
681 fp
->_markers
= marker
;
684 #define BAD_DELTA EOF
686 /* Return difference between MARK and current position of MARK's stream. */
688 _IO_wmarker_delta (mark
)
689 struct _IO_marker
*mark
;
692 if (mark
->_sbuf
== NULL
)
694 if (_IO_in_backup (mark
->_sbuf
))
695 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
696 - mark
->_sbuf
->_wide_data
->_IO_read_end
);
698 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
699 - mark
->_sbuf
->_wide_data
->_IO_read_base
);
700 return mark
->_pos
- cur_pos
;
704 _IO_seekwmark (fp
, mark
, delta
)
706 struct _IO_marker
*mark
;
709 if (mark
->_sbuf
!= fp
)
713 if (_IO_in_backup (fp
))
714 _IO_switch_to_main_wget_area (fp
);
715 fp
->_wide_data
->_IO_read_ptr
= (fp
->_wide_data
->_IO_read_base
720 if (!_IO_in_backup (fp
))
721 _IO_switch_to_wbackup_area (fp
);
722 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
+ mark
->_pos
;
728 _IO_unsave_wmarkers (fp
)
731 struct _IO_marker
*mark
= fp
->_markers
;
735 streampos offset
= seekoff (0, ios::cur
, ios::in
);
738 offset
+= eGptr () - Gbase ();
739 for ( ; mark
!= NULL
; mark
= mark
->_next
)
740 mark
->set_streampos (mark
->_pos
+ offset
);
744 for ( ; mark
!= NULL
; mark
= mark
->_next
)
745 mark
->set_streampos (EOF
);
751 if (_IO_have_backup (fp
))
752 _IO_free_wbackup_area (fp
);