(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / libio / wstrops.c
blob32f7ef3cf7ef1b60aa3dd315847406066d436ea4
1 /* Copyright (C) 1993,1997-1999,2001-2003,2004 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA.
19 As a special exception, if you link the code in this file with
20 files compiled with a GNU compiler to produce an executable,
21 that does not cause the resulting executable to be covered by
22 the GNU Lesser General Public License. This exception does not
23 however invalidate any other reasons why the executable file
24 might be covered by the GNU Lesser General Public License.
25 This exception applies to code released by its copyright holders
26 in files containing the exception. */
28 #include "strfile.h"
29 #include "libioP.h"
30 #include <string.h>
31 #include <wchar.h>
32 #include <stdio_ext.h>
34 #if 0
35 /* The following definitions are for exposition only.
36 They map the terminology used in the ANSI/ISO C++ draft standard
37 to the implementation. */
39 /* allocated: set when a dynamic array object has been allocated, and
40 hence should be freed by the destructor for the strstreambuf object. */
41 #define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP))
43 /* constant: set when the array object has const elements,
44 so the output sequence cannot be written. */
45 #define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES)
47 /* alsize: the suggested minimum size for a dynamic array object. */
48 #define ALSIZE(FP) ??? /* not stored */
50 /* palloc: points to the function to call to allocate a dynamic array object.*/
51 #define PALLOC(FP) \
52 ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer)
54 /* pfree: points to the function to call to free a dynamic array object. */
55 #define PFREE(FP) \
56 ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer)
58 #endif
60 #ifdef TODO
61 /* An "unbounded buffer" is when a buffer is supplied, but with no
62 specified length. An example is the buffer argument to sprintf.
64 #endif
66 void
67 _IO_wstr_init_static (fp, ptr, size, pstart)
68 _IO_FILE *fp;
69 wchar_t *ptr;
70 _IO_size_t size;
71 wchar_t *pstart;
73 wchar_t *end;
75 if (size == 0)
76 end = ptr + __wcslen (ptr);
77 else if ((_IO_size_t) ptr + size * sizeof (wchar_t) > (_IO_size_t) ptr)
78 end = ptr + size;
79 else
80 /* Even for misaligned ptr make sure there is integral number of wide
81 characters. */
82 end = ptr + (-1 - (_IO_size_t) ptr) / sizeof (wchar_t);
83 INTUSE(_IO_wsetb) (fp, ptr, end, 0);
85 fp->_wide_data->_IO_write_base = ptr;
86 fp->_wide_data->_IO_read_base = ptr;
87 fp->_wide_data->_IO_read_ptr = ptr;
88 if (pstart)
90 fp->_wide_data->_IO_write_ptr = pstart;
91 fp->_wide_data->_IO_write_end = end;
92 fp->_wide_data->_IO_read_end = pstart;
94 else
96 fp->_wide_data->_IO_write_ptr = ptr;
97 fp->_wide_data->_IO_write_end = ptr;
98 fp->_wide_data->_IO_read_end = end;
100 /* A null _allocate_buffer function flags the strfile as being static. */
101 (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0;
104 _IO_wint_t
105 _IO_wstr_overflow (fp, c)
106 _IO_FILE *fp;
107 _IO_wint_t c;
109 int flush_only = c == WEOF;
110 _IO_size_t pos;
111 if (fp->_flags & _IO_NO_WRITES)
112 return flush_only ? 0 : WEOF;
113 if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
115 fp->_flags |= _IO_CURRENTLY_PUTTING;
116 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
117 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
119 pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
120 if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only))
122 if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
123 return WEOF;
124 else
126 wchar_t *new_buf;
127 wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
128 _IO_size_t new_size = 2 * _IO_wblen (fp) + 100;
129 new_buf
130 = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
131 * sizeof (wchar_t));
132 if (new_buf == NULL)
134 /* __ferror(fp) = 1; */
135 return WEOF;
137 if (old_buf)
139 __wmemcpy (new_buf, old_buf, _IO_wblen (fp));
140 (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
141 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
142 fp->_wide_data->_IO_buf_base = NULL;
144 INTUSE(_IO_wsetb) (fp, new_buf, new_buf + new_size, 1);
145 fp->_wide_data->_IO_read_base =
146 new_buf + (fp->_wide_data->_IO_read_base - old_buf);
147 fp->_wide_data->_IO_read_ptr =
148 new_buf + (fp->_wide_data->_IO_read_ptr - old_buf);
149 fp->_wide_data->_IO_read_end =
150 new_buf + (fp->_wide_data->_IO_read_end - old_buf);
151 fp->_wide_data->_IO_write_ptr =
152 new_buf + (fp->_wide_data->_IO_write_ptr - old_buf);
154 fp->_wide_data->_IO_write_base = new_buf;
155 fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end;
159 if (!flush_only)
160 *fp->_wide_data->_IO_write_ptr++ = c;
161 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
162 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
163 return c;
166 _IO_wint_t
167 _IO_wstr_underflow (fp)
168 _IO_FILE *fp;
170 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
171 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
172 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
174 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
175 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
176 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end;
178 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
179 return *fp->_wide_data->_IO_read_ptr;
180 else
181 return WEOF;
184 /* The size of the valid part of the buffer. */
186 _IO_ssize_t
187 _IO_wstr_count (fp)
188 _IO_FILE *fp;
190 return ((fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end
191 ? fp->_wide_data->_IO_write_ptr : fp->_wide_data->_IO_read_end)
192 - fp->_wide_data->_IO_read_base);
195 _IO_off64_t
196 _IO_wstr_seekoff (fp, offset, dir, mode)
197 _IO_FILE *fp;
198 _IO_off64_t offset;
199 int dir;
200 int mode;
202 _IO_off64_t new_pos;
204 if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
205 mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
207 if (mode == 0)
209 /* Don't move any pointers. But there is no clear indication what
210 mode FP is in. Let's guess. */
211 if (fp->_IO_file_flags & _IO_NO_WRITES)
212 new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base;
213 else
214 new_pos = (fp->_wide_data->_IO_write_ptr
215 - fp->_wide_data->_IO_write_base);
217 else
219 _IO_ssize_t cur_size = _IO_wstr_count (fp);
220 new_pos = EOF;
222 /* Move the get pointer, if requested. */
223 if (mode & _IOS_INPUT)
225 switch (dir)
227 case _IO_seek_end:
228 offset += cur_size;
229 break;
230 case _IO_seek_cur:
231 offset += (fp->_wide_data->_IO_read_ptr
232 - fp->_wide_data->_IO_read_base);
233 break;
234 default: /* case _IO_seek_set: */
235 break;
237 if (offset < 0 || (_IO_ssize_t) offset > cur_size)
238 return EOF;
239 fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
240 + offset);
241 fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base
242 + cur_size);
243 new_pos = offset;
246 /* Move the put pointer, if requested. */
247 if (mode & _IOS_OUTPUT)
249 switch (dir)
251 case _IO_seek_end:
252 offset += cur_size;
253 break;
254 case _IO_seek_cur:
255 offset += (fp->_wide_data->_IO_write_ptr
256 - fp->_wide_data->_IO_write_base);
257 break;
258 default: /* case _IO_seek_set: */
259 break;
261 if (offset < 0 || (_IO_ssize_t) offset > cur_size)
262 return EOF;
263 fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
264 + offset);
265 new_pos = offset;
268 return new_pos;
271 _IO_wint_t
272 _IO_wstr_pbackfail (fp, c)
273 _IO_FILE *fp;
274 _IO_wint_t c;
276 if ((fp->_flags & _IO_NO_WRITES) && c != WEOF)
277 return WEOF;
278 return INTUSE(_IO_wdefault_pbackfail) (fp, c);
281 void
282 _IO_wstr_finish (fp, dummy)
283 _IO_FILE *fp;
284 int dummy;
286 if (fp->_wide_data->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
287 (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
288 fp->_wide_data->_IO_buf_base = NULL;
290 INTUSE(_IO_wdefault_finish) (fp, 0);
293 const struct _IO_jump_t _IO_wstr_jumps =
295 JUMP_INIT_DUMMY,
296 JUMP_INIT(finish, _IO_wstr_finish),
297 JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
298 JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
299 JUMP_INIT(uflow, (_IO_underflow_t) INTUSE(_IO_wdefault_uflow)),
300 JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
301 JUMP_INIT(xsputn, INTUSE(_IO_wdefault_xsputn)),
302 JUMP_INIT(xsgetn, INTUSE(_IO_wdefault_xsgetn)),
303 JUMP_INIT(seekoff, _IO_wstr_seekoff),
304 JUMP_INIT(seekpos, _IO_default_seekpos),
305 JUMP_INIT(setbuf, _IO_default_setbuf),
306 JUMP_INIT(sync, _IO_default_sync),
307 JUMP_INIT(doallocate, INTUSE(_IO_wdefault_doallocate)),
308 JUMP_INIT(read, _IO_default_read),
309 JUMP_INIT(write, _IO_default_write),
310 JUMP_INIT(seek, _IO_default_seek),
311 JUMP_INIT(close, _IO_default_close),
312 JUMP_INIT(stat, _IO_default_stat),
313 JUMP_INIT(showmanyc, _IO_default_showmanyc),
314 JUMP_INIT(imbue, _IO_default_imbue)