Add some more ulps.
[glibc/pb-stable.git] / libio / wstrops.c
blobaf2c957b0513279f5e1da237737770fb4f6cbbf3
1 /* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
2 This file is part of the GNU IO Library.
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2, or (at
7 your option) any later version.
9 This library is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this library; see the file COPYING. If not, write to
16 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
17 MA 02111-1307, USA.
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does
21 not cause the resulting executable to be covered by the GNU General
22 Public License. This exception does not however invalidate any
23 other reasons why the executable file might be covered by the GNU
24 General Public License. */
26 #include "strfile.h"
27 #include "libioP.h"
28 #include <string.h>
29 #include <wchar.h>
31 #if 0
32 /* The following definitions are for exposition only.
33 They map the terminology used in the ANSI/ISO C++ draft standard
34 to the implementation. */
36 /* allocated: set when a dynamic array object has been allocated, and
37 hence should be freed by the destructor for the strstreambuf object. */
38 #define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP))
40 /* constant: set when the array object has const elements,
41 so the output sequence cannot be written. */
42 #define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES)
44 /* alsize: the suggested minimum size for a dynamic array object. */
45 #define ALSIZE(FP) ??? /* not stored */
47 /* palloc: points to the function to call to allocate a dynamic array object.*/
48 #define PALLOC(FP) \
49 ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer)
51 /* pfree: points to the function to call to free a dynamic array object. */
52 #define PFREE(FP) \
53 ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer)
55 #endif
57 #ifdef TODO
58 /* An "unbounded buffer" is when a buffer is supplied, but with no
59 specified length. An example is the buffer argument to sprintf.
61 #endif
63 void
64 _IO_wstr_init_static (fp, ptr, size, pstart)
65 _IO_FILE *fp;
66 wchar_t *ptr;
67 int size;
68 wchar_t *pstart;
70 if (size == 0)
71 size = __wcslen (ptr);
72 else if (size < 0)
74 /* If size is negative 'the characters are assumed to
75 continue indefinitely.' This is kind of messy ... */
76 int s;
77 size = 512;
78 /* Try increasing powers of 2, as long as we don't wrap around. */
79 for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
80 size = s;
81 /* Try increasing size as much as we can without wrapping around. */
82 for (s = size >> 1; s > 0; s >>= 1)
84 if (ptr + size + s > ptr)
85 size += s;
88 _IO_wsetb (fp, ptr, ptr + size, 0);
90 fp->_wide_data->_IO_write_base = ptr;
91 fp->_wide_data->_IO_read_base = ptr;
92 fp->_wide_data->_IO_read_ptr = ptr;
93 if (pstart)
95 fp->_wide_data->_IO_write_ptr = pstart;
96 fp->_wide_data->_IO_write_end = ptr + size;
97 fp->_wide_data->_IO_read_end = pstart;
99 else
101 fp->_wide_data->_IO_write_ptr = ptr;
102 fp->_wide_data->_IO_write_end = ptr;
103 fp->_wide_data->_IO_read_end = ptr + size;
105 /* A null _allocate_buffer function flags the strfile as being static. */
106 (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0;
109 void
110 _IO_wstr_init_readonly (fp, ptr, size)
111 _IO_FILE *fp;
112 const char *ptr;
113 int size;
115 _IO_wstr_init_static (fp, (wchar_t *) ptr, size, NULL);
116 fp->_IO_file_flags |= _IO_NO_WRITES;
119 _IO_wint_t
120 _IO_wstr_overflow (fp, c)
121 _IO_FILE *fp;
122 _IO_wint_t c;
124 int flush_only = c == WEOF;
125 _IO_size_t pos;
126 if (fp->_flags & _IO_NO_WRITES)
127 return flush_only ? 0 : WEOF;
128 if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
130 fp->_flags |= _IO_CURRENTLY_PUTTING;
131 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
132 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
134 pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
135 if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only))
137 if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
138 return WEOF;
139 else
141 wchar_t *new_buf;
142 wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
143 _IO_size_t new_size = 2 * _IO_wblen (fp) + 100;
144 new_buf
145 = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
146 * sizeof (wchar_t));
147 if (new_buf == NULL)
149 /* __ferror(fp) = 1; */
150 return WEOF;
152 if (old_buf)
154 __wmemcpy (new_buf, old_buf, _IO_wblen (fp));
155 (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
156 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
157 fp->_wide_data->_IO_buf_base = NULL;
159 _IO_wsetb (fp, new_buf, new_buf + new_size, 1);
160 fp->_wide_data->_IO_read_base =
161 new_buf + (fp->_wide_data->_IO_read_base - old_buf);
162 fp->_wide_data->_IO_read_ptr =
163 new_buf + (fp->_wide_data->_IO_read_ptr - old_buf);
164 fp->_wide_data->_IO_read_end =
165 new_buf + (fp->_wide_data->_IO_read_end - old_buf);
166 fp->_wide_data->_IO_write_ptr =
167 new_buf + (fp->_wide_data->_IO_write_ptr - old_buf);
169 fp->_wide_data->_IO_write_base = new_buf;
170 fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end;
174 if (!flush_only)
175 *fp->_wide_data->_IO_write_ptr++ = c;
176 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
177 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
178 return c;
181 _IO_wint_t
182 _IO_wstr_underflow (fp)
183 _IO_FILE *fp;
185 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
186 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
187 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
189 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
190 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
191 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end;
193 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
194 return *fp->_wide_data->_IO_read_ptr;
195 else
196 return WEOF;
199 /* The size of the valid part of the buffer. */
201 _IO_ssize_t
202 _IO_wstr_count (fp)
203 _IO_FILE *fp;
205 return ((fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end
206 ? fp->_wide_data->_IO_write_ptr : fp->_wide_data->_IO_read_end)
207 - fp->_wide_data->_IO_read_base);
210 _IO_off64_t
211 _IO_wstr_seekoff (fp, offset, dir, mode)
212 _IO_FILE *fp;
213 _IO_off64_t offset;
214 int dir;
215 int mode;
217 _IO_off64_t new_pos;
219 if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
220 mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
222 if (mode == 0)
224 /* Don't move any pointers. But there is no clear indication what
225 mode FP is in. Let's guess. */
226 if (fp->_IO_file_flags & _IO_NO_WRITES)
227 new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base;
228 else
229 new_pos = (fp->_wide_data->_IO_write_ptr
230 - fp->_wide_data->_IO_write_base);
232 else
234 _IO_ssize_t cur_size = _IO_wstr_count (fp);
235 new_pos = EOF;
237 /* Move the get pointer, if requested. */
238 if (mode & _IOS_INPUT)
240 switch (dir)
242 case _IO_seek_end:
243 offset += cur_size;
244 break;
245 case _IO_seek_cur:
246 offset += (fp->_wide_data->_IO_read_ptr
247 - fp->_wide_data->_IO_read_base);
248 break;
249 default: /* case _IO_seek_set: */
250 break;
252 if (offset < 0 || (_IO_ssize_t) offset > cur_size)
253 return EOF;
254 fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
255 + offset);
256 fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base
257 + cur_size);
258 new_pos = offset;
261 /* Move the put pointer, if requested. */
262 if (mode & _IOS_OUTPUT)
264 switch (dir)
266 case _IO_seek_end:
267 offset += cur_size;
268 break;
269 case _IO_seek_cur:
270 offset += (fp->_wide_data->_IO_write_ptr
271 - fp->_wide_data->_IO_write_base);
272 break;
273 default: /* case _IO_seek_set: */
274 break;
276 if (offset < 0 || (_IO_ssize_t) offset > cur_size)
277 return EOF;
278 fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
279 + offset);
280 new_pos = offset;
283 return new_pos;
286 _IO_wint_t
287 _IO_wstr_pbackfail (fp, c)
288 _IO_FILE *fp;
289 _IO_wint_t c;
291 if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
292 return WEOF;
293 return _IO_wdefault_pbackfail (fp, c);
296 void
297 _IO_wstr_finish (fp, dummy)
298 _IO_FILE *fp;
299 int dummy;
301 if (fp->_wide_data->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
302 (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
303 fp->_wide_data->_IO_buf_base = NULL;
305 _IO_wdefault_finish (fp, 0);
308 struct _IO_jump_t _IO_wstr_jumps =
310 JUMP_INIT_DUMMY,
311 JUMP_INIT(finish, _IO_wstr_finish),
312 JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
313 JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
314 JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
315 JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
316 JUMP_INIT(xsputn, _IO_wdefault_xsputn),
317 JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),
318 JUMP_INIT(seekoff, _IO_wstr_seekoff),
319 JUMP_INIT(seekpos, _IO_default_seekpos),
320 JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_wdefault_setbuf),
321 JUMP_INIT(sync, _IO_default_sync),
322 JUMP_INIT(doallocate, _IO_wdefault_doallocate),
323 JUMP_INIT(read, _IO_default_read),
324 JUMP_INIT(write, _IO_default_write),
325 JUMP_INIT(seek, _IO_default_seek),
326 JUMP_INIT(close, _IO_default_close),
327 JUMP_INIT(stat, _IO_default_stat),
328 JUMP_INIT(showmanyc, _IO_default_showmanyc),
329 JUMP_INIT(imbue, _IO_default_imbue)