1 /* Copyright (C) 1993,1995,1997-2001,2002 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Ulrich Drepper <drepper@cygnus.com>.
4 Based on the single byte version by Per Bothner <bothner@cygnus.com>.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C 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 GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 As a special exception, if you link the code in this file with
22 files compiled with a GNU compiler to produce an executable,
23 that does not cause the resulting executable to be covered by
24 the GNU Lesser General Public License. This exception does not
25 however invalidate any other reasons why the executable file
26 might be covered by the GNU Lesser General Public License.
27 This exception applies to code released by its copyright holders
28 in files containing the exception. */
30 /* Generic or default I/O operations. */
41 # define __wmemcpy(dst, src, n) wmemcpy (dst, src, n)
45 static int save_for_wbackup
__P ((_IO_FILE
*fp
, wchar_t *end_p
))
51 /* Return minimum _pos markers
52 Assumes the current get area is the main get area. */
53 _IO_ssize_t _IO_least_wmarker
__P ((_IO_FILE
*fp
, wchar_t *end_p
));
56 _IO_least_wmarker (fp
, end_p
)
60 _IO_ssize_t least_so_far
= end_p
- fp
->_wide_data
->_IO_read_base
;
61 struct _IO_marker
*mark
;
62 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
63 if (mark
->_pos
< least_so_far
)
64 least_so_far
= mark
->_pos
;
67 INTDEF(_IO_least_wmarker
)
69 /* Switch current get area from backup buffer to (start of) main get area. */
71 _IO_switch_to_main_wget_area (fp
)
75 fp
->_flags
&= ~_IO_IN_BACKUP
;
76 /* Swap _IO_read_end and _IO_save_end. */
77 tmp
= fp
->_wide_data
->_IO_read_end
;
78 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
79 fp
->_wide_data
->_IO_save_end
= tmp
;
80 /* Swap _IO_read_base and _IO_save_base. */
81 tmp
= fp
->_wide_data
->_IO_read_base
;
82 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
83 fp
->_wide_data
->_IO_save_base
= tmp
;
84 /* Set _IO_read_ptr. */
85 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_base
;
87 INTDEF(_IO_switch_to_main_wget_area
)
90 /* Switch current get area from main get area to (end of) backup area. */
92 _IO_switch_to_wbackup_area (fp
)
96 fp
->_flags
|= _IO_IN_BACKUP
;
97 /* Swap _IO_read_end and _IO_save_end. */
98 tmp
= fp
->_wide_data
->_IO_read_end
;
99 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
100 fp
->_wide_data
->_IO_save_end
= tmp
;
101 /* Swap _IO_read_base and _IO_save_base. */
102 tmp
= fp
->_wide_data
->_IO_read_base
;
103 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
104 fp
->_wide_data
->_IO_save_base
= tmp
;
105 /* Set _IO_read_ptr. */
106 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
108 INTDEF(_IO_switch_to_wbackup_area
)
112 _IO_wsetb (f
, b
, eb
, a
)
118 if (f
->_wide_data
->_IO_buf_base
&& !(f
->_flags
& _IO_USER_BUF
))
119 FREE_BUF (f
->_wide_data
->_IO_buf_base
, _IO_wblen (f
));
120 f
->_wide_data
->_IO_buf_base
= b
;
121 f
->_wide_data
->_IO_buf_end
= eb
;
123 f
->_flags
&= ~_IO_USER_BUF
;
125 f
->_flags
|= _IO_USER_BUF
;
131 _IO_wdefault_pbackfail (fp
, c
)
135 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
136 && !_IO_in_backup (fp
)
137 && (wint_t) fp
->_IO_read_ptr
[-1] == c
)
141 /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
142 if (!_IO_in_backup (fp
))
144 /* We need to keep the invariant that the main get area
145 logically follows the backup area. */
146 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
147 && _IO_have_wbackup (fp
))
149 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_ptr
))
152 else if (!_IO_have_wbackup (fp
))
154 /* No backup buffer: allocate one. */
155 /* Use nshort buffer, if unused? (probably not) FIXME */
156 int backup_size
= 128;
157 wchar_t *bbuf
= (wchar_t *) malloc (backup_size
161 fp
->_wide_data
->_IO_save_base
= bbuf
;
162 fp
->_wide_data
->_IO_save_end
= (fp
->_wide_data
->_IO_save_base
164 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_end
;
166 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
;
167 INTUSE(_IO_switch_to_wbackup_area
) (fp
);
169 else if (fp
->_wide_data
->_IO_read_ptr
<= fp
->_wide_data
->_IO_read_base
)
171 /* Increase size of existing backup buffer. */
173 _IO_size_t old_size
= (fp
->_wide_data
->_IO_read_end
174 - fp
->_wide_data
->_IO_read_base
);
176 new_size
= 2 * old_size
;
177 new_buf
= (wchar_t *) malloc (new_size
* sizeof (wchar_t));
180 __wmemcpy (new_buf
+ (new_size
- old_size
),
181 fp
->_wide_data
->_IO_read_base
, old_size
);
182 free (fp
->_wide_data
->_IO_read_base
);
183 _IO_wsetg (fp
, new_buf
, new_buf
+ (new_size
- old_size
),
185 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_read_ptr
;
188 *--fp
->_wide_data
->_IO_read_ptr
= c
;
192 INTDEF(_IO_wdefault_pbackfail
)
196 _IO_wdefault_finish (fp
, dummy
)
200 struct _IO_marker
*mark
;
201 if (fp
->_wide_data
->_IO_buf_base
&& !(fp
->_flags
& _IO_USER_BUF
))
203 FREE_BUF (fp
->_wide_data
->_IO_buf_base
,
204 _IO_wblen (fp
) * sizeof (wchar_t));
205 fp
->_wide_data
->_IO_buf_base
= fp
->_wide_data
->_IO_buf_end
= NULL
;
208 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
211 if (fp
->_IO_save_base
)
213 free (fp
->_wide_data
->_IO_save_base
);
214 fp
->_IO_save_base
= NULL
;
218 if (fp
->_lock
!= NULL
)
219 _IO_lock_fini (*fp
->_lock
);
222 INTUSE(_IO_un_link
) ((struct _IO_FILE_plus
*) fp
);
224 INTDEF(_IO_wdefault_finish
)
228 _IO_wdefault_uflow (fp
)
232 wch
= _IO_UNDERFLOW (fp
);
235 return *fp
->_wide_data
->_IO_read_ptr
++;
237 INTDEF(_IO_wdefault_uflow
)
247 return _IO_OVERFLOW (f
, wch
);
255 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
260 if (_IO_in_put_mode (fp
))
261 if (INTUSE(_IO_switch_to_wget_mode
) (fp
) == EOF
)
263 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
264 return *fp
->_wide_data
->_IO_read_ptr
++;
265 if (_IO_in_backup (fp
))
267 INTUSE(_IO_switch_to_main_wget_area
) (fp
);
268 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
269 return *fp
->_wide_data
->_IO_read_ptr
++;
271 if (_IO_have_markers (fp
))
273 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
276 else if (_IO_have_wbackup (fp
))
277 INTUSE(_IO_free_wbackup_area
) (fp
);
278 return _IO_UFLOW (fp
);
286 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
291 if (_IO_in_put_mode (fp
))
292 if (INTUSE(_IO_switch_to_wget_mode
) (fp
) == EOF
)
294 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
295 return *fp
->_wide_data
->_IO_read_ptr
;
296 if (_IO_in_backup (fp
))
298 INTUSE(_IO_switch_to_main_wget_area
) (fp
);
299 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
300 return *fp
->_wide_data
->_IO_read_ptr
;
302 if (_IO_have_markers (fp
))
304 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
307 else if (_IO_have_backup (fp
))
308 INTUSE(_IO_free_wbackup_area
) (fp
);
309 return _IO_UNDERFLOW (fp
);
314 _IO_wdefault_xsputn (f
, data
, n
)
319 const wchar_t *s
= (const wchar_t *) data
;
325 /* Space available. */
326 _IO_ssize_t count
= (f
->_wide_data
->_IO_write_end
327 - f
->_wide_data
->_IO_write_ptr
);
330 if ((_IO_size_t
) count
> more
)
335 f
->_wide_data
->_IO_write_ptr
=
336 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
338 memcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
339 f
->_wide_data
->_IO_write_ptr
+= count
;
347 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
349 for (i
= count
; --i
>= 0; )
351 f
->_wide_data
->_IO_write_ptr
= p
;
355 if (more
== 0 || __woverflow (f
, *s
++) == WEOF
)
361 INTDEF(_IO_wdefault_xsputn
)
365 _IO_wdefault_xsgetn (fp
, data
, n
)
371 wchar_t *s
= (wchar_t*) data
;
374 /* Data available. */
375 _IO_ssize_t count
= (fp
->_wide_data
->_IO_read_end
376 - fp
->_wide_data
->_IO_read_ptr
);
379 if ((_IO_size_t
) count
> more
)
384 s
= __wmempcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
386 memcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
389 fp
->_wide_data
->_IO_read_ptr
+= count
;
395 wchar_t *p
= fp
->_wide_data
->_IO_read_ptr
;
399 fp
->_wide_data
->_IO_read_ptr
= p
;
403 if (more
== 0 || __wunderflow (fp
) == WEOF
)
408 INTDEF(_IO_wdefault_xsgetn
)
415 if (fp
->_wide_data
->_IO_buf_base
)
417 if (!(fp
->_flags
& _IO_UNBUFFERED
))
418 if ((wint_t)_IO_WDOALLOCATE (fp
) != WEOF
)
420 INTUSE(_IO_wsetb
) (fp
, fp
->_wide_data
->_shortbuf
,
421 fp
->_wide_data
->_shortbuf
+ 1, 0);
423 INTDEF(_IO_wdoallocbuf
)
427 _IO_wdefault_setbuf (fp
, p
, len
)
432 if (_IO_SYNC (fp
) == EOF
)
434 if (p
== NULL
|| len
== 0)
436 fp
->_flags
|= _IO_UNBUFFERED
;
437 INTUSE(_IO_wsetb
) (fp
, fp
->_wide_data
->_shortbuf
,
438 fp
->_wide_data
->_shortbuf
+ 1, 0);
442 fp
->_flags
&= ~_IO_UNBUFFERED
;
443 INTUSE(_IO_wsetb
) (fp
, p
, p
+ len
, 0);
445 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
446 = fp
->_wide_data
->_IO_write_end
= 0;
447 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
448 = fp
->_wide_data
->_IO_read_end
= 0;
451 INTDEF(_IO_wdefault_setbuf
)
455 _IO_wdefault_doallocate (fp
)
460 ALLOC_WBUF (buf
, _IO_BUFSIZ
, EOF
);
461 INTUSE(_IO_wsetb
) (fp
, buf
, buf
+ _IO_BUFSIZ
, 1);
464 INTDEF(_IO_wdefault_doallocate
)
468 _IO_switch_to_wget_mode (fp
)
471 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
472 if ((wint_t)_IO_WOVERFLOW (fp
, WEOF
) == WEOF
)
474 if (_IO_in_backup (fp
))
475 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_backup_base
;
478 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_buf_base
;
479 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_read_end
)
480 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
482 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_write_ptr
;
484 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
485 = fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_read_ptr
;
487 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
490 INTDEF(_IO_switch_to_wget_mode
)
493 _IO_free_wbackup_area (fp
)
496 if (_IO_in_backup (fp
))
497 INTUSE(_IO_switch_to_main_wget_area
) (fp
); /* Just in case. */
498 free (fp
->_wide_data
->_IO_save_base
);
499 fp
->_wide_data
->_IO_save_base
= NULL
;
500 fp
->_wide_data
->_IO_save_end
= NULL
;
501 fp
->_wide_data
->_IO_backup_base
= NULL
;
503 INTDEF(_IO_free_wbackup_area
)
507 _IO_switch_to_wput_mode (fp
)
510 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_read_ptr
;
511 fp
->_wide_data
->_IO_write_ptr
= fp
->_wide_data
->_IO_read_ptr
;
512 /* Following is wrong if line- or un-buffered? */
513 fp
->_wide_data
->_IO_write_end
= (fp
->_flags
& _IO_IN_BACKUP
514 ? fp
->_wide_data
->_IO_read_end
515 : fp
->_wide_data
->_IO_buf_end
);
517 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
518 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_end
;
520 fp
->_flags
|= _IO_CURRENTLY_PUTTING
;
530 save_for_wbackup (fp
, end_p
)
534 /* Append [_IO_read_base..end_p] to backup area. */
535 _IO_ssize_t least_mark
= INTUSE(_IO_least_wmarker
) (fp
, end_p
);
536 /* needed_size is how much space we need in the backup area. */
537 _IO_size_t needed_size
= ((end_p
- fp
->_wide_data
->_IO_read_base
)
539 /* FIXME: Dubious arithmetic if pointers are NULL */
540 _IO_size_t current_Bsize
= (fp
->_wide_data
->_IO_save_end
541 - fp
->_wide_data
->_IO_save_base
);
542 _IO_size_t avail
; /* Extra space available for future expansion. */
544 struct _IO_marker
*mark
;
545 if (needed_size
> current_Bsize
)
549 new_buffer
= (wchar_t *) malloc ((avail
+ needed_size
)
551 if (new_buffer
== NULL
)
552 return EOF
; /* FIXME */
556 __wmempcpy (__wmempcpy (new_buffer
+ avail
,
557 fp
->_wide_data
->_IO_save_end
+ least_mark
,
559 fp
->_wide_data
->_IO_read_base
,
560 end_p
- fp
->_wide_data
->_IO_read_base
);
562 memcpy (new_buffer
+ avail
,
563 fp
->_wide_data
->_IO_save_end
+ least_mark
,
564 -least_mark
* sizeof (wchar_t));
565 memcpy (new_buffer
+ avail
- least_mark
,
566 fp
->_wide_data
->_IO_read_base
,
567 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
573 __wmemcpy (new_buffer
+ avail
,
574 fp
->_wide_data
->_IO_read_base
+ least_mark
,
577 memcpy (new_buffer
+ avail
,
578 fp
->_wide_data
->_IO_read_base
+ least_mark
,
579 needed_size
* sizeof (wchar_t));
582 if (fp
->_wide_data
->_IO_save_base
)
583 free (fp
->_wide_data
->_IO_save_base
);
584 fp
->_wide_data
->_IO_save_base
= new_buffer
;
585 fp
->_wide_data
->_IO_save_end
= new_buffer
+ avail
+ needed_size
;
589 avail
= current_Bsize
- needed_size
;
593 __wmemmove (fp
->_wide_data
->_IO_save_base
+ avail
,
594 fp
->_wide_data
->_IO_save_end
+ least_mark
,
596 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
597 fp
->_wide_data
->_IO_read_base
,
598 end_p
- fp
->_wide_data
->_IO_read_base
);
600 memmove (fp
->_wide_data
->_IO_save_base
+ avail
,
601 fp
->_wide_data
->_IO_save_end
+ least_mark
,
602 -least_mark
* sizeof (wchar_t));
603 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
604 fp
->_wide_data
->_IO_read_base
,
605 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
608 else if (needed_size
> 0)
610 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
611 fp
->_wide_data
->_IO_read_base
+ least_mark
,
614 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
615 fp
->_wide_data
->_IO_read_base
+ least_mark
,
616 needed_size
* sizeof (wchar_t));
619 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_base
+ avail
;
620 /* Adjust all the streammarkers. */
621 delta
= end_p
- fp
->_wide_data
->_IO_read_base
;
622 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
628 _IO_sputbackwc (fp
, c
)
634 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
635 && (wchar_t)fp
->_wide_data
->_IO_read_ptr
[-1] == (wchar_t) c
)
637 fp
->_wide_data
->_IO_read_ptr
--;
641 result
= _IO_PBACKFAIL (fp
, c
);
644 fp
->_flags
&= ~_IO_EOF_SEEN
;
648 INTDEF(_IO_sputbackwc
)
656 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
)
658 fp
->_wide_data
->_IO_read_ptr
--;
659 result
= *fp
->_wide_data
->_IO_read_ptr
;
662 result
= _IO_PBACKFAIL (fp
, EOF
);
665 fp
->_flags
&= ~_IO_EOF_SEEN
;
672 _IO_adjust_wcolumn (start
, line
, count
)
677 const wchar_t *ptr
= line
+ count
;
680 return line
+ count
- ptr
- 1;
681 return start
+ count
;
685 _IO_init_wmarker (marker
, fp
)
686 struct _IO_marker
*marker
;
690 if (_IO_in_put_mode (fp
))
691 INTUSE(_IO_switch_to_wget_mode
) (fp
);
692 if (_IO_in_backup (fp
))
693 marker
->_pos
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
695 marker
->_pos
= (fp
->_wide_data
->_IO_read_ptr
696 - fp
->_wide_data
->_IO_read_base
);
698 /* Should perhaps sort the chain? */
699 marker
->_next
= fp
->_markers
;
700 fp
->_markers
= marker
;
703 #define BAD_DELTA EOF
705 /* Return difference between MARK and current position of MARK's stream. */
707 _IO_wmarker_delta (mark
)
708 struct _IO_marker
*mark
;
711 if (mark
->_sbuf
== NULL
)
713 if (_IO_in_backup (mark
->_sbuf
))
714 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
715 - mark
->_sbuf
->_wide_data
->_IO_read_end
);
717 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
718 - mark
->_sbuf
->_wide_data
->_IO_read_base
);
719 return mark
->_pos
- cur_pos
;
723 _IO_seekwmark (fp
, mark
, delta
)
725 struct _IO_marker
*mark
;
728 if (mark
->_sbuf
!= fp
)
732 if (_IO_in_backup (fp
))
733 INTUSE(_IO_switch_to_main_wget_area
) (fp
);
734 fp
->_wide_data
->_IO_read_ptr
= (fp
->_wide_data
->_IO_read_base
739 if (!_IO_in_backup (fp
))
740 INTUSE(_IO_switch_to_wbackup_area
) (fp
);
741 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
+ mark
->_pos
;
747 _IO_unsave_wmarkers (fp
)
750 struct _IO_marker
*mark
= fp
->_markers
;
754 streampos offset
= seekoff (0, ios::cur
, ios::in
);
757 offset
+= eGptr () - Gbase ();
758 for ( ; mark
!= NULL
; mark
= mark
->_next
)
759 mark
->set_streampos (mark
->_pos
+ offset
);
763 for ( ; mark
!= NULL
; mark
= mark
->_next
)
764 mark
->set_streampos (EOF
);
770 if (_IO_have_backup (fp
))
771 INTUSE(_IO_free_wbackup_area
) (fp
);