1 | /* Copyright (C) 1993-2018 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>. |
5 | |
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. |
10 | |
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. |
15 | |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. |
19 | |
20 | As a special exception, if you link the code in this file with |
21 | files compiled with a GNU compiler to produce an executable, |
22 | that does not cause the resulting executable to be covered by |
23 | the GNU Lesser General Public License. This exception does not |
24 | however invalidate any other reasons why the executable file |
25 | might be covered by the GNU Lesser General Public License. |
26 | This exception applies to code released by its copyright holders |
27 | in files containing the exception. */ |
28 | |
29 | /* Generic or default I/O operations. */ |
30 | |
31 | #include "libioP.h" |
32 | #include <stdlib.h> |
33 | #include <string.h> |
34 | #include <wchar.h> |
35 | |
36 | |
37 | static int save_for_wbackup (_IO_FILE *fp, wchar_t *end_p) __THROW; |
38 | |
39 | /* Return minimum _pos markers |
40 | Assumes the current get area is the main get area. */ |
41 | _IO_ssize_t |
42 | _IO_least_wmarker (_IO_FILE *fp, wchar_t *end_p) |
43 | { |
44 | _IO_ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base; |
45 | struct _IO_marker *mark; |
46 | for (mark = fp->_markers; mark != NULL; mark = mark->_next) |
47 | if (mark->_pos < least_so_far) |
48 | least_so_far = mark->_pos; |
49 | return least_so_far; |
50 | } |
51 | libc_hidden_def (_IO_least_wmarker) |
52 | |
53 | /* Switch current get area from backup buffer to (start of) main get area. */ |
54 | void |
55 | _IO_switch_to_main_wget_area (_IO_FILE *fp) |
56 | { |
57 | wchar_t *tmp; |
58 | fp->_flags &= ~_IO_IN_BACKUP; |
59 | /* Swap _IO_read_end and _IO_save_end. */ |
60 | tmp = fp->_wide_data->_IO_read_end; |
61 | fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end; |
62 | fp->_wide_data->_IO_save_end= tmp; |
63 | /* Swap _IO_read_base and _IO_save_base. */ |
64 | tmp = fp->_wide_data->_IO_read_base; |
65 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base; |
66 | fp->_wide_data->_IO_save_base = tmp; |
67 | /* Set _IO_read_ptr. */ |
68 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base; |
69 | } |
70 | libc_hidden_def (_IO_switch_to_main_wget_area) |
71 | |
72 | |
73 | /* Switch current get area from main get area to (end of) backup area. */ |
74 | void |
75 | _IO_switch_to_wbackup_area (_IO_FILE *fp) |
76 | { |
77 | wchar_t *tmp; |
78 | fp->_flags |= _IO_IN_BACKUP; |
79 | /* Swap _IO_read_end and _IO_save_end. */ |
80 | tmp = fp->_wide_data->_IO_read_end; |
81 | fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end; |
82 | fp->_wide_data->_IO_save_end = tmp; |
83 | /* Swap _IO_read_base and _IO_save_base. */ |
84 | tmp = fp->_wide_data->_IO_read_base; |
85 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base; |
86 | fp->_wide_data->_IO_save_base = tmp; |
87 | /* Set _IO_read_ptr. */ |
88 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; |
89 | } |
90 | libc_hidden_def (_IO_switch_to_wbackup_area) |
91 | |
92 | |
93 | void |
94 | _IO_wsetb (_IO_FILE *f, wchar_t *b, wchar_t *eb, int a) |
95 | { |
96 | if (f->_wide_data->_IO_buf_base && !(f->_flags2 & _IO_FLAGS2_USER_WBUF)) |
97 | free (f->_wide_data->_IO_buf_base); |
98 | f->_wide_data->_IO_buf_base = b; |
99 | f->_wide_data->_IO_buf_end = eb; |
100 | if (a) |
101 | f->_flags2 &= ~_IO_FLAGS2_USER_WBUF; |
102 | else |
103 | f->_flags2 |= _IO_FLAGS2_USER_WBUF; |
104 | } |
105 | libc_hidden_def (_IO_wsetb) |
106 | |
107 | |
108 | wint_t |
109 | _IO_wdefault_pbackfail (_IO_FILE *fp, wint_t c) |
110 | { |
111 | if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base |
112 | && !_IO_in_backup (fp) |
113 | && (wint_t) fp->_IO_read_ptr[-1] == c) |
114 | --fp->_IO_read_ptr; |
115 | else |
116 | { |
117 | /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/ |
118 | if (!_IO_in_backup (fp)) |
119 | { |
120 | /* We need to keep the invariant that the main get area |
121 | logically follows the backup area. */ |
122 | if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base |
123 | && _IO_have_wbackup (fp)) |
124 | { |
125 | if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr)) |
126 | return WEOF; |
127 | } |
128 | else if (!_IO_have_wbackup (fp)) |
129 | { |
130 | /* No backup buffer: allocate one. */ |
131 | /* Use nshort buffer, if unused? (probably not) FIXME */ |
132 | int backup_size = 128; |
133 | wchar_t *bbuf = (wchar_t *) malloc (backup_size |
134 | * sizeof (wchar_t)); |
135 | if (bbuf == NULL) |
136 | return WEOF; |
137 | fp->_wide_data->_IO_save_base = bbuf; |
138 | fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base |
139 | + backup_size); |
140 | fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end; |
141 | } |
142 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr; |
143 | _IO_switch_to_wbackup_area (fp); |
144 | } |
145 | else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base) |
146 | { |
147 | /* Increase size of existing backup buffer. */ |
148 | _IO_size_t new_size; |
149 | _IO_size_t old_size = (fp->_wide_data->_IO_read_end |
150 | - fp->_wide_data->_IO_read_base); |
151 | wchar_t *new_buf; |
152 | new_size = 2 * old_size; |
153 | new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t)); |
154 | if (new_buf == NULL) |
155 | return WEOF; |
156 | __wmemcpy (new_buf + (new_size - old_size), |
157 | fp->_wide_data->_IO_read_base, old_size); |
158 | free (fp->_wide_data->_IO_read_base); |
159 | _IO_wsetg (fp, new_buf, new_buf + (new_size - old_size), |
160 | new_buf + new_size); |
161 | fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr; |
162 | } |
163 | |
164 | *--fp->_wide_data->_IO_read_ptr = c; |
165 | } |
166 | return c; |
167 | } |
168 | libc_hidden_def (_IO_wdefault_pbackfail) |
169 | |
170 | |
171 | void |
172 | _IO_wdefault_finish (_IO_FILE *fp, int dummy) |
173 | { |
174 | struct _IO_marker *mark; |
175 | if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) |
176 | { |
177 | free (fp->_wide_data->_IO_buf_base); |
178 | fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL; |
179 | } |
180 | |
181 | for (mark = fp->_markers; mark != NULL; mark = mark->_next) |
182 | mark->_sbuf = NULL; |
183 | |
184 | if (fp->_IO_save_base) |
185 | { |
186 | free (fp->_wide_data->_IO_save_base); |
187 | fp->_IO_save_base = NULL; |
188 | } |
189 | |
190 | #ifdef _IO_MTSAFE_IO |
191 | if (fp->_lock != NULL) |
192 | _IO_lock_fini (*fp->_lock); |
193 | #endif |
194 | |
195 | _IO_un_link ((struct _IO_FILE_plus *) fp); |
196 | } |
197 | libc_hidden_def (_IO_wdefault_finish) |
198 | |
199 | |
200 | wint_t |
201 | _IO_wdefault_uflow (_IO_FILE *fp) |
202 | { |
203 | wint_t wch; |
204 | wch = _IO_UNDERFLOW (fp); |
205 | if (wch == WEOF) |
206 | return WEOF; |
207 | return *fp->_wide_data->_IO_read_ptr++; |
208 | } |
209 | libc_hidden_def (_IO_wdefault_uflow) |
210 | |
211 | |
212 | wint_t |
213 | __woverflow (_IO_FILE *f, wint_t wch) |
214 | { |
215 | if (f->_mode == 0) |
216 | _IO_fwide (f, 1); |
217 | return _IO_OVERFLOW (f, wch); |
218 | } |
219 | libc_hidden_def (__woverflow) |
220 | |
221 | |
222 | wint_t |
223 | __wuflow (_IO_FILE *fp) |
224 | { |
225 | if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) |
226 | return WEOF; |
227 | |
228 | if (fp->_mode == 0) |
229 | _IO_fwide (fp, 1); |
230 | if (_IO_in_put_mode (fp)) |
231 | if (_IO_switch_to_wget_mode (fp) == EOF) |
232 | return WEOF; |
233 | if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) |
234 | return *fp->_wide_data->_IO_read_ptr++; |
235 | if (_IO_in_backup (fp)) |
236 | { |
237 | _IO_switch_to_main_wget_area (fp); |
238 | if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) |
239 | return *fp->_wide_data->_IO_read_ptr++; |
240 | } |
241 | if (_IO_have_markers (fp)) |
242 | { |
243 | if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end)) |
244 | return WEOF; |
245 | } |
246 | else if (_IO_have_wbackup (fp)) |
247 | _IO_free_wbackup_area (fp); |
248 | return _IO_UFLOW (fp); |
249 | } |
250 | libc_hidden_def (__wuflow) |
251 | |
252 | wint_t |
253 | __wunderflow (_IO_FILE *fp) |
254 | { |
255 | if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) |
256 | return WEOF; |
257 | |
258 | if (fp->_mode == 0) |
259 | _IO_fwide (fp, 1); |
260 | if (_IO_in_put_mode (fp)) |
261 | if (_IO_switch_to_wget_mode (fp) == EOF) |
262 | return WEOF; |
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)) |
266 | { |
267 | _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; |
270 | } |
271 | if (_IO_have_markers (fp)) |
272 | { |
273 | if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end)) |
274 | return WEOF; |
275 | } |
276 | else if (_IO_have_backup (fp)) |
277 | _IO_free_wbackup_area (fp); |
278 | return _IO_UNDERFLOW (fp); |
279 | } |
280 | libc_hidden_def (__wunderflow) |
281 | |
282 | |
283 | _IO_size_t |
284 | _IO_wdefault_xsputn (_IO_FILE *f, const void *data, _IO_size_t n) |
285 | { |
286 | const wchar_t *s = (const wchar_t *) data; |
287 | _IO_size_t more = n; |
288 | if (more <= 0) |
289 | return 0; |
290 | for (;;) |
291 | { |
292 | /* Space available. */ |
293 | _IO_ssize_t count = (f->_wide_data->_IO_write_end |
294 | - f->_wide_data->_IO_write_ptr); |
295 | if (count > 0) |
296 | { |
297 | if ((_IO_size_t) count > more) |
298 | count = more; |
299 | if (count > 20) |
300 | { |
301 | f->_wide_data->_IO_write_ptr = |
302 | __wmempcpy (f->_wide_data->_IO_write_ptr, s, count); |
303 | s += count; |
304 | } |
305 | else if (count <= 0) |
306 | count = 0; |
307 | else |
308 | { |
309 | wchar_t *p = f->_wide_data->_IO_write_ptr; |
310 | _IO_ssize_t i; |
311 | for (i = count; --i >= 0; ) |
312 | *p++ = *s++; |
313 | f->_wide_data->_IO_write_ptr = p; |
314 | } |
315 | more -= count; |
316 | } |
317 | if (more == 0 || __woverflow (f, *s++) == WEOF) |
318 | break; |
319 | more--; |
320 | } |
321 | return n - more; |
322 | } |
323 | libc_hidden_def (_IO_wdefault_xsputn) |
324 | |
325 | |
326 | _IO_size_t |
327 | _IO_wdefault_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n) |
328 | { |
329 | _IO_size_t more = n; |
330 | wchar_t *s = (wchar_t*) data; |
331 | for (;;) |
332 | { |
333 | /* Data available. */ |
334 | _IO_ssize_t count = (fp->_wide_data->_IO_read_end |
335 | - fp->_wide_data->_IO_read_ptr); |
336 | if (count > 0) |
337 | { |
338 | if ((_IO_size_t) count > more) |
339 | count = more; |
340 | if (count > 20) |
341 | { |
342 | s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count); |
343 | fp->_wide_data->_IO_read_ptr += count; |
344 | } |
345 | else if (count <= 0) |
346 | count = 0; |
347 | else |
348 | { |
349 | wchar_t *p = fp->_wide_data->_IO_read_ptr; |
350 | int i = (int) count; |
351 | while (--i >= 0) |
352 | *s++ = *p++; |
353 | fp->_wide_data->_IO_read_ptr = p; |
354 | } |
355 | more -= count; |
356 | } |
357 | if (more == 0 || __wunderflow (fp) == WEOF) |
358 | break; |
359 | } |
360 | return n - more; |
361 | } |
362 | libc_hidden_def (_IO_wdefault_xsgetn) |
363 | |
364 | |
365 | void |
366 | _IO_wdoallocbuf (_IO_FILE *fp) |
367 | { |
368 | if (fp->_wide_data->_IO_buf_base) |
369 | return; |
370 | if (!(fp->_flags & _IO_UNBUFFERED)) |
371 | if ((wint_t)_IO_WDOALLOCATE (fp) != WEOF) |
372 | return; |
373 | _IO_wsetb (fp, fp->_wide_data->_shortbuf, |
374 | fp->_wide_data->_shortbuf + 1, 0); |
375 | } |
376 | libc_hidden_def (_IO_wdoallocbuf) |
377 | |
378 | |
379 | int |
380 | _IO_wdefault_doallocate (_IO_FILE *fp) |
381 | { |
382 | wchar_t *buf; |
383 | |
384 | buf = malloc (_IO_BUFSIZ); |
385 | if (__glibc_unlikely (buf == NULL)) |
386 | return EOF; |
387 | _IO_wsetb (fp, buf, buf + _IO_BUFSIZ, 1); |
388 | return 1; |
389 | } |
390 | libc_hidden_def (_IO_wdefault_doallocate) |
391 | |
392 | |
393 | int |
394 | _IO_switch_to_wget_mode (_IO_FILE *fp) |
395 | { |
396 | if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base) |
397 | if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF) |
398 | return EOF; |
399 | if (_IO_in_backup (fp)) |
400 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base; |
401 | else |
402 | { |
403 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base; |
404 | if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) |
405 | fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; |
406 | } |
407 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr; |
408 | |
409 | fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr |
410 | = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr; |
411 | |
412 | fp->_flags &= ~_IO_CURRENTLY_PUTTING; |
413 | return 0; |
414 | } |
415 | libc_hidden_def (_IO_switch_to_wget_mode) |
416 | |
417 | void |
418 | _IO_free_wbackup_area (_IO_FILE *fp) |
419 | { |
420 | if (_IO_in_backup (fp)) |
421 | _IO_switch_to_main_wget_area (fp); /* Just in case. */ |
422 | free (fp->_wide_data->_IO_save_base); |
423 | fp->_wide_data->_IO_save_base = NULL; |
424 | fp->_wide_data->_IO_save_end = NULL; |
425 | fp->_wide_data->_IO_backup_base = NULL; |
426 | } |
427 | libc_hidden_def (_IO_free_wbackup_area) |
428 | |
429 | #if 0 |
430 | int |
431 | _IO_switch_to_wput_mode (_IO_FILE *fp) |
432 | { |
433 | fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_read_ptr; |
434 | fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr; |
435 | /* Following is wrong if line- or un-buffered? */ |
436 | fp->_wide_data->_IO_write_end = (fp->_flags & _IO_IN_BACKUP |
437 | ? fp->_wide_data->_IO_read_end |
438 | : fp->_wide_data->_IO_buf_end); |
439 | |
440 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; |
441 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_end; |
442 | |
443 | fp->_flags |= _IO_CURRENTLY_PUTTING; |
444 | return 0; |
445 | } |
446 | #endif |
447 | |
448 | |
449 | static int |
450 | save_for_wbackup (_IO_FILE *fp, wchar_t *end_p) |
451 | { |
452 | /* Append [_IO_read_base..end_p] to backup area. */ |
453 | _IO_ssize_t least_mark = _IO_least_wmarker (fp, end_p); |
454 | /* needed_size is how much space we need in the backup area. */ |
455 | _IO_size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base) |
456 | - least_mark); |
457 | /* FIXME: Dubious arithmetic if pointers are NULL */ |
458 | _IO_size_t current_Bsize = (fp->_wide_data->_IO_save_end |
459 | - fp->_wide_data->_IO_save_base); |
460 | _IO_size_t avail; /* Extra space available for future expansion. */ |
461 | _IO_ssize_t delta; |
462 | struct _IO_marker *mark; |
463 | if (needed_size > current_Bsize) |
464 | { |
465 | wchar_t *new_buffer; |
466 | avail = 100; |
467 | new_buffer = (wchar_t *) malloc ((avail + needed_size) |
468 | * sizeof (wchar_t)); |
469 | if (new_buffer == NULL) |
470 | return EOF; /* FIXME */ |
471 | if (least_mark < 0) |
472 | { |
473 | __wmempcpy (__wmempcpy (new_buffer + avail, |
474 | fp->_wide_data->_IO_save_end + least_mark, |
475 | -least_mark), |
476 | fp->_wide_data->_IO_read_base, |
477 | end_p - fp->_wide_data->_IO_read_base); |
478 | } |
479 | else |
480 | { |
481 | __wmemcpy (new_buffer + avail, |
482 | fp->_wide_data->_IO_read_base + least_mark, |
483 | needed_size); |
484 | } |
485 | free (fp->_wide_data->_IO_save_base); |
486 | fp->_wide_data->_IO_save_base = new_buffer; |
487 | fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size; |
488 | } |
489 | else |
490 | { |
491 | avail = current_Bsize - needed_size; |
492 | if (least_mark < 0) |
493 | { |
494 | __wmemmove (fp->_wide_data->_IO_save_base + avail, |
495 | fp->_wide_data->_IO_save_end + least_mark, |
496 | -least_mark); |
497 | __wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark, |
498 | fp->_wide_data->_IO_read_base, |
499 | end_p - fp->_wide_data->_IO_read_base); |
500 | } |
501 | else if (needed_size > 0) |
502 | __wmemcpy (fp->_wide_data->_IO_save_base + avail, |
503 | fp->_wide_data->_IO_read_base + least_mark, |
504 | needed_size); |
505 | } |
506 | fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail; |
507 | /* Adjust all the streammarkers. */ |
508 | delta = end_p - fp->_wide_data->_IO_read_base; |
509 | for (mark = fp->_markers; mark != NULL; mark = mark->_next) |
510 | mark->_pos -= delta; |
511 | return 0; |
512 | } |
513 | |
514 | wint_t |
515 | _IO_sputbackwc (_IO_FILE *fp, wint_t c) |
516 | { |
517 | wint_t result; |
518 | |
519 | if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base |
520 | && (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c) |
521 | { |
522 | fp->_wide_data->_IO_read_ptr--; |
523 | result = c; |
524 | } |
525 | else |
526 | result = _IO_PBACKFAIL (fp, c); |
527 | |
528 | if (result != WEOF) |
529 | fp->_flags &= ~_IO_EOF_SEEN; |
530 | |
531 | return result; |
532 | } |
533 | libc_hidden_def (_IO_sputbackwc) |
534 | |
535 | wint_t |
536 | _IO_sungetwc (_IO_FILE *fp) |
537 | { |
538 | wint_t result; |
539 | |
540 | if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base) |
541 | { |
542 | fp->_wide_data->_IO_read_ptr--; |
543 | result = *fp->_wide_data->_IO_read_ptr; |
544 | } |
545 | else |
546 | result = _IO_PBACKFAIL (fp, EOF); |
547 | |
548 | if (result != WEOF) |
549 | fp->_flags &= ~_IO_EOF_SEEN; |
550 | |
551 | return result; |
552 | } |
553 | |
554 | |
555 | unsigned |
556 | _IO_adjust_wcolumn (unsigned start, const wchar_t *line, int count) |
557 | { |
558 | const wchar_t *ptr = line + count; |
559 | while (ptr > line) |
560 | if (*--ptr == L'\n') |
561 | return line + count - ptr - 1; |
562 | return start + count; |
563 | } |
564 | |
565 | void |
566 | _IO_init_wmarker (struct _IO_marker *marker, _IO_FILE *fp) |
567 | { |
568 | marker->_sbuf = fp; |
569 | if (_IO_in_put_mode (fp)) |
570 | _IO_switch_to_wget_mode (fp); |
571 | if (_IO_in_backup (fp)) |
572 | marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end; |
573 | else |
574 | marker->_pos = (fp->_wide_data->_IO_read_ptr |
575 | - fp->_wide_data->_IO_read_base); |
576 | |
577 | /* Should perhaps sort the chain? */ |
578 | marker->_next = fp->_markers; |
579 | fp->_markers = marker; |
580 | } |
581 | |
582 | #define BAD_DELTA EOF |
583 | |
584 | /* Return difference between MARK and current position of MARK's stream. */ |
585 | int |
586 | _IO_wmarker_delta (struct _IO_marker *mark) |
587 | { |
588 | int cur_pos; |
589 | if (mark->_sbuf == NULL) |
590 | return BAD_DELTA; |
591 | if (_IO_in_backup (mark->_sbuf)) |
592 | cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr |
593 | - mark->_sbuf->_wide_data->_IO_read_end); |
594 | else |
595 | cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr |
596 | - mark->_sbuf->_wide_data->_IO_read_base); |
597 | return mark->_pos - cur_pos; |
598 | } |
599 | |
600 | int |
601 | _IO_seekwmark (_IO_FILE *fp, struct _IO_marker *mark, int delta) |
602 | { |
603 | if (mark->_sbuf != fp) |
604 | return EOF; |
605 | if (mark->_pos >= 0) |
606 | { |
607 | if (_IO_in_backup (fp)) |
608 | _IO_switch_to_main_wget_area (fp); |
609 | fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base |
610 | + mark->_pos); |
611 | } |
612 | else |
613 | { |
614 | if (!_IO_in_backup (fp)) |
615 | _IO_switch_to_wbackup_area (fp); |
616 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos; |
617 | } |
618 | return 0; |
619 | } |
620 | |
621 | void |
622 | _IO_unsave_wmarkers (_IO_FILE *fp) |
623 | { |
624 | struct _IO_marker *mark = fp->_markers; |
625 | if (mark) |
626 | { |
627 | #ifdef TODO |
628 | streampos offset = seekoff (0, ios::cur, ios::in); |
629 | if (offset != EOF) |
630 | { |
631 | offset += eGptr () - Gbase (); |
632 | for ( ; mark != NULL; mark = mark->_next) |
633 | mark->set_streampos (mark->_pos + offset); |
634 | } |
635 | else |
636 | { |
637 | for ( ; mark != NULL; mark = mark->_next) |
638 | mark->set_streampos (EOF); |
639 | } |
640 | #endif |
641 | fp->_markers = 0; |
642 | } |
643 | |
644 | if (_IO_have_backup (fp)) |
645 | _IO_free_wbackup_area (fp); |
646 | } |
647 | |