1 /* Copyright (C) 1993,1995,1997,1998,1999,2000,2001 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
;
68 /* Switch current get area from backup buffer to (start of) main get area. */
70 _IO_switch_to_main_wget_area (fp
)
74 fp
->_flags
&= ~_IO_IN_BACKUP
;
75 /* Swap _IO_read_end and _IO_save_end. */
76 tmp
= fp
->_wide_data
->_IO_read_end
;
77 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
78 fp
->_wide_data
->_IO_save_end
= tmp
;
79 /* Swap _IO_read_base and _IO_save_base. */
80 tmp
= fp
->_wide_data
->_IO_read_base
;
81 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
82 fp
->_wide_data
->_IO_save_base
= tmp
;
83 /* Set _IO_read_ptr. */
84 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_base
;
88 /* Switch current get area from main get area to (end of) backup area. */
90 _IO_switch_to_wbackup_area (fp
)
94 fp
->_flags
|= _IO_IN_BACKUP
;
95 /* Swap _IO_read_end and _IO_save_end. */
96 tmp
= fp
->_wide_data
->_IO_read_end
;
97 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
98 fp
->_wide_data
->_IO_save_end
= tmp
;
99 /* Swap _IO_read_base and _IO_save_base. */
100 tmp
= fp
->_wide_data
->_IO_read_base
;
101 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
102 fp
->_wide_data
->_IO_save_base
= tmp
;
103 /* Set _IO_read_ptr. */
104 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
109 _IO_wsetb (f
, b
, eb
, a
)
115 if (f
->_wide_data
->_IO_buf_base
&& !(f
->_flags
& _IO_USER_BUF
))
116 FREE_BUF (f
->_wide_data
->_IO_buf_base
, _IO_wblen (f
));
117 f
->_wide_data
->_IO_buf_base
= b
;
118 f
->_wide_data
->_IO_buf_end
= eb
;
120 f
->_flags
&= ~_IO_USER_BUF
;
122 f
->_flags
|= _IO_USER_BUF
;
127 _IO_wdefault_pbackfail (fp
, c
)
131 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
132 && !_IO_in_backup (fp
)
133 && (wint_t) fp
->_IO_read_ptr
[-1] == c
)
137 /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
138 if (!_IO_in_backup (fp
))
140 /* We need to keep the invariant that the main get area
141 logically follows the backup area. */
142 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
143 && _IO_have_wbackup (fp
))
145 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_ptr
))
148 else if (!_IO_have_wbackup (fp
))
150 /* No backup buffer: allocate one. */
151 /* Use nshort buffer, if unused? (probably not) FIXME */
152 int backup_size
= 128;
153 wchar_t *bbuf
= (wchar_t *) malloc (backup_size
157 fp
->_wide_data
->_IO_save_base
= bbuf
;
158 fp
->_wide_data
->_IO_save_end
= (fp
->_wide_data
->_IO_save_base
160 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_end
;
162 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
;
163 _IO_switch_to_wbackup_area (fp
);
165 else if (fp
->_wide_data
->_IO_read_ptr
<= fp
->_wide_data
->_IO_read_base
)
167 /* Increase size of existing backup buffer. */
169 _IO_size_t old_size
= (fp
->_wide_data
->_IO_read_end
170 - fp
->_wide_data
->_IO_read_base
);
172 new_size
= 2 * old_size
;
173 new_buf
= (wchar_t *) malloc (new_size
* sizeof (wchar_t));
176 __wmemcpy (new_buf
+ (new_size
- old_size
),
177 fp
->_wide_data
->_IO_read_base
, old_size
);
178 free (fp
->_wide_data
->_IO_read_base
);
179 _IO_wsetg (fp
, new_buf
, new_buf
+ (new_size
- old_size
),
181 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_read_ptr
;
184 *--fp
->_wide_data
->_IO_read_ptr
= c
;
191 _IO_wdefault_finish (fp
, dummy
)
195 struct _IO_marker
*mark
;
196 if (fp
->_wide_data
->_IO_buf_base
&& !(fp
->_flags
& _IO_USER_BUF
))
198 FREE_BUF (fp
->_wide_data
->_IO_buf_base
,
199 _IO_wblen (fp
) * sizeof (wchar_t));
200 fp
->_wide_data
->_IO_buf_base
= fp
->_wide_data
->_IO_buf_end
= NULL
;
203 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
206 if (fp
->_IO_save_base
)
208 free (fp
->_wide_data
->_IO_save_base
);
209 fp
->_IO_save_base
= NULL
;
213 if (fp
->_lock
!= NULL
)
214 _IO_lock_fini (*fp
->_lock
);
217 _IO_un_link ((struct _IO_FILE_plus
*) fp
);
222 _IO_wdefault_uflow (fp
)
226 wch
= _IO_UNDERFLOW (fp
);
229 return *fp
->_wide_data
->_IO_read_ptr
++;
240 return _IO_OVERFLOW (f
, wch
);
248 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
253 if (_IO_in_put_mode (fp
))
254 if (_IO_switch_to_wget_mode (fp
) == EOF
)
256 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
257 return *fp
->_wide_data
->_IO_read_ptr
++;
258 if (_IO_in_backup (fp
))
260 _IO_switch_to_main_wget_area (fp
);
261 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
262 return *fp
->_wide_data
->_IO_read_ptr
++;
264 if (_IO_have_markers (fp
))
266 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
269 else if (_IO_have_wbackup (fp
))
270 _IO_free_wbackup_area (fp
);
271 return _IO_UFLOW (fp
);
279 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
284 if (_IO_in_put_mode (fp
))
285 if (_IO_switch_to_wget_mode (fp
) == EOF
)
287 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
288 return *fp
->_wide_data
->_IO_read_ptr
;
289 if (_IO_in_backup (fp
))
291 _IO_switch_to_main_wget_area (fp
);
292 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
293 return *fp
->_wide_data
->_IO_read_ptr
;
295 if (_IO_have_markers (fp
))
297 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
300 else if (_IO_have_backup (fp
))
301 _IO_free_wbackup_area (fp
);
302 return _IO_UNDERFLOW (fp
);
307 _IO_wdefault_xsputn (f
, data
, n
)
312 const wchar_t *s
= (const wchar_t *) data
;
318 /* Space available. */
319 _IO_ssize_t count
= (f
->_wide_data
->_IO_write_end
320 - f
->_wide_data
->_IO_write_ptr
);
323 if ((_IO_size_t
) count
> more
)
328 f
->_wide_data
->_IO_write_ptr
=
329 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
331 memcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
332 f
->_wide_data
->_IO_write_ptr
+= count
;
340 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
342 for (i
= count
; --i
>= 0; )
344 f
->_wide_data
->_IO_write_ptr
= p
;
348 if (more
== 0 || __woverflow (f
, *s
++) == WEOF
)
357 _IO_wdefault_xsgetn (fp
, data
, n
)
363 wchar_t *s
= (wchar_t*) data
;
366 /* Data available. */
367 _IO_ssize_t count
= (fp
->_wide_data
->_IO_read_end
368 - fp
->_wide_data
->_IO_read_ptr
);
371 if ((_IO_size_t
) count
> more
)
376 s
= __wmempcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
378 memcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
381 fp
->_wide_data
->_IO_read_ptr
+= count
;
387 wchar_t *p
= fp
->_wide_data
->_IO_read_ptr
;
391 fp
->_wide_data
->_IO_read_ptr
= p
;
395 if (more
== 0 || __wunderflow (fp
) == WEOF
)
406 if (fp
->_wide_data
->_IO_buf_base
)
408 if (!(fp
->_flags
& _IO_UNBUFFERED
))
409 if ((wint_t)_IO_WDOALLOCATE (fp
) != WEOF
)
411 _IO_wsetb (fp
, fp
->_wide_data
->_shortbuf
, fp
->_wide_data
->_shortbuf
+ 1, 0);
416 _IO_wdefault_setbuf (fp
, p
, len
)
421 if (_IO_SYNC (fp
) == EOF
)
423 if (p
== NULL
|| len
== 0)
425 fp
->_flags
|= _IO_UNBUFFERED
;
426 _IO_wsetb (fp
, fp
->_wide_data
->_shortbuf
, fp
->_wide_data
->_shortbuf
+ 1,
431 fp
->_flags
&= ~_IO_UNBUFFERED
;
432 _IO_wsetb (fp
, p
, p
+ len
, 0);
434 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
435 = fp
->_wide_data
->_IO_write_end
= 0;
436 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
437 = fp
->_wide_data
->_IO_read_end
= 0;
443 _IO_wdefault_doallocate (fp
)
448 ALLOC_WBUF (buf
, _IO_BUFSIZ
, EOF
);
449 _IO_wsetb (fp
, buf
, buf
+ _IO_BUFSIZ
, 1);
455 _IO_switch_to_wget_mode (fp
)
458 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
459 if ((wint_t)_IO_WOVERFLOW (fp
, WEOF
) == WEOF
)
461 if (_IO_in_backup (fp
))
462 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_backup_base
;
465 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_buf_base
;
466 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_read_end
)
467 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
469 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_write_ptr
;
471 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
472 = fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_read_ptr
;
474 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
479 _IO_free_wbackup_area (fp
)
482 if (_IO_in_backup (fp
))
483 _IO_switch_to_main_wget_area (fp
); /* Just in case. */
484 free (fp
->_wide_data
->_IO_save_base
);
485 fp
->_wide_data
->_IO_save_base
= NULL
;
486 fp
->_wide_data
->_IO_save_end
= NULL
;
487 fp
->_wide_data
->_IO_backup_base
= NULL
;
492 _IO_switch_to_wput_mode (fp
)
495 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_read_ptr
;
496 fp
->_wide_data
->_IO_write_ptr
= fp
->_wide_data
->_IO_read_ptr
;
497 /* Following is wrong if line- or un-buffered? */
498 fp
->_wide_data
->_IO_write_end
= (fp
->_flags
& _IO_IN_BACKUP
499 ? fp
->_wide_data
->_IO_read_end
500 : fp
->_wide_data
->_IO_buf_end
);
502 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
503 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_end
;
505 fp
->_flags
|= _IO_CURRENTLY_PUTTING
;
515 save_for_wbackup (fp
, end_p
)
519 /* Append [_IO_read_base..end_p] to backup area. */
520 _IO_ssize_t least_mark
= _IO_least_wmarker (fp
, end_p
);
521 /* needed_size is how much space we need in the backup area. */
522 _IO_size_t needed_size
= ((end_p
- fp
->_wide_data
->_IO_read_base
)
524 /* FIXME: Dubious arithmetic if pointers are NULL */
525 _IO_size_t current_Bsize
= (fp
->_wide_data
->_IO_save_end
526 - fp
->_wide_data
->_IO_save_base
);
527 _IO_size_t avail
; /* Extra space available for future expansion. */
529 struct _IO_marker
*mark
;
530 if (needed_size
> current_Bsize
)
534 new_buffer
= (wchar_t *) malloc ((avail
+ needed_size
)
536 if (new_buffer
== NULL
)
537 return EOF
; /* FIXME */
541 __wmempcpy (__wmempcpy (new_buffer
+ avail
,
542 fp
->_wide_data
->_IO_save_end
+ least_mark
,
544 fp
->_wide_data
->_IO_read_base
,
545 end_p
- fp
->_wide_data
->_IO_read_base
);
547 memcpy (new_buffer
+ avail
,
548 fp
->_wide_data
->_IO_save_end
+ least_mark
,
549 -least_mark
* sizeof (wchar_t));
550 memcpy (new_buffer
+ avail
- least_mark
,
551 fp
->_wide_data
->_IO_read_base
,
552 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
558 __wmemcpy (new_buffer
+ avail
,
559 fp
->_wide_data
->_IO_read_base
+ least_mark
,
562 memcpy (new_buffer
+ avail
,
563 fp
->_wide_data
->_IO_read_base
+ least_mark
,
564 needed_size
* sizeof (wchar_t));
567 if (fp
->_wide_data
->_IO_save_base
)
568 free (fp
->_wide_data
->_IO_save_base
);
569 fp
->_wide_data
->_IO_save_base
= new_buffer
;
570 fp
->_wide_data
->_IO_save_end
= new_buffer
+ avail
+ needed_size
;
574 avail
= current_Bsize
- needed_size
;
578 __wmemmove (fp
->_wide_data
->_IO_save_base
+ avail
,
579 fp
->_wide_data
->_IO_save_end
+ least_mark
,
581 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
582 fp
->_wide_data
->_IO_read_base
,
583 end_p
- fp
->_wide_data
->_IO_read_base
);
585 memmove (fp
->_wide_data
->_IO_save_base
+ avail
,
586 fp
->_wide_data
->_IO_save_end
+ least_mark
,
587 -least_mark
* sizeof (wchar_t));
588 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
589 fp
->_wide_data
->_IO_read_base
,
590 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
593 else if (needed_size
> 0)
595 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
596 fp
->_wide_data
->_IO_read_base
+ least_mark
,
599 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
600 fp
->_wide_data
->_IO_read_base
+ least_mark
,
601 needed_size
* sizeof (wchar_t));
604 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_base
+ avail
;
605 /* Adjust all the streammarkers. */
606 delta
= end_p
- fp
->_wide_data
->_IO_read_base
;
607 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
613 _IO_sputbackwc (fp
, c
)
619 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
620 && (wchar_t)fp
->_wide_data
->_IO_read_ptr
[-1] == (wchar_t) c
)
622 fp
->_wide_data
->_IO_read_ptr
--;
626 result
= _IO_PBACKFAIL (fp
, c
);
629 fp
->_flags
&= ~_IO_EOF_SEEN
;
640 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
)
642 fp
->_wide_data
->_IO_read_ptr
--;
643 result
= *fp
->_wide_data
->_IO_read_ptr
;
646 result
= _IO_PBACKFAIL (fp
, EOF
);
649 fp
->_flags
&= ~_IO_EOF_SEEN
;
656 _IO_adjust_wcolumn (start
, line
, count
)
661 const wchar_t *ptr
= line
+ count
;
664 return line
+ count
- ptr
- 1;
665 return start
+ count
;
669 _IO_init_wmarker (marker
, fp
)
670 struct _IO_marker
*marker
;
674 if (_IO_in_put_mode (fp
))
675 _IO_switch_to_wget_mode (fp
);
676 if (_IO_in_backup (fp
))
677 marker
->_pos
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
679 marker
->_pos
= (fp
->_wide_data
->_IO_read_ptr
680 - fp
->_wide_data
->_IO_read_base
);
682 /* Should perhaps sort the chain? */
683 marker
->_next
= fp
->_markers
;
684 fp
->_markers
= marker
;
687 #define BAD_DELTA EOF
689 /* Return difference between MARK and current position of MARK's stream. */
691 _IO_wmarker_delta (mark
)
692 struct _IO_marker
*mark
;
695 if (mark
->_sbuf
== NULL
)
697 if (_IO_in_backup (mark
->_sbuf
))
698 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
699 - mark
->_sbuf
->_wide_data
->_IO_read_end
);
701 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
702 - mark
->_sbuf
->_wide_data
->_IO_read_base
);
703 return mark
->_pos
- cur_pos
;
707 _IO_seekwmark (fp
, mark
, delta
)
709 struct _IO_marker
*mark
;
712 if (mark
->_sbuf
!= fp
)
716 if (_IO_in_backup (fp
))
717 _IO_switch_to_main_wget_area (fp
);
718 fp
->_wide_data
->_IO_read_ptr
= (fp
->_wide_data
->_IO_read_base
723 if (!_IO_in_backup (fp
))
724 _IO_switch_to_wbackup_area (fp
);
725 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
+ mark
->_pos
;
731 _IO_unsave_wmarkers (fp
)
734 struct _IO_marker
*mark
= fp
->_markers
;
738 streampos offset
= seekoff (0, ios::cur
, ios::in
);
741 offset
+= eGptr () - Gbase ();
742 for ( ; mark
!= NULL
; mark
= mark
->_next
)
743 mark
->set_streampos (mark
->_pos
+ offset
);
747 for ( ; mark
!= NULL
; mark
= mark
->_next
)
748 mark
->set_streampos (EOF
);
754 if (_IO_have_backup (fp
))
755 _IO_free_wbackup_area (fp
);