xref: /haiku/src/system/libroot/posix/glibc/libio/wstrops.c (revision 1e36cfc2721ef13a187c6f7354dc9cbc485e89d3)
1 /* Copyright (C) 1993,1997,1998,1999,2001,2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
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.
8 
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.
13 
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.
18 
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.  */
27 
28 #include "strfile.h"
29 #include "libioP.h"
30 #include <string.h>
31 #include <wchar.h>
32 #include <stdio_ext.h>
33 
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. */
38 
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))
42 
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)
46 
47 /* alsize:  the suggested minimum size for a dynamic array object. */
48 #define ALSIZE(FP) ??? /* not stored */
49 
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)
53 
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)
57 
58 #endif
59 
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.
63    */
64 #endif
65 
66 void
67 _IO_wstr_init_static (fp, ptr, size, pstart)
68      _IO_FILE *fp;
69      wchar_t *ptr;
70      int size;
71      wchar_t *pstart;
72 {
73   if (size == 0)
74     size = __wcslen (ptr);
75   else if (size < 0)
76     {
77       /* If size is negative 'the characters are assumed to
78 	 continue indefinitely.'  This is kind of messy ... */
79       int s;
80       size = 512;
81       /* Try increasing powers of 2, as long as we don't wrap around. */
82       for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
83 	size = s;
84       /* Try increasing size as much as we can without wrapping around. */
85       for (s = size >> 1; s > 0; s >>= 1)
86 	{
87 	  if (ptr + size + s > ptr)
88 	    size += s;
89 	}
90     }
91   INTUSE(_IO_wsetb) (fp, ptr, ptr + size, 0);
92 
93   fp->_wide_data->_IO_write_base = ptr;
94   fp->_wide_data->_IO_read_base = ptr;
95   fp->_wide_data->_IO_read_ptr = ptr;
96   if (pstart)
97     {
98       fp->_wide_data->_IO_write_ptr = pstart;
99       fp->_wide_data->_IO_write_end = ptr + size;
100       fp->_wide_data->_IO_read_end = pstart;
101     }
102   else
103     {
104       fp->_wide_data->_IO_write_ptr = ptr;
105       fp->_wide_data->_IO_write_end = ptr;
106       fp->_wide_data->_IO_read_end = ptr + size;
107     }
108   /* A null _allocate_buffer function flags the strfile as being static. */
109   (((_IO_strfile *) fp)->_s._allocate_buffer) =  (_IO_alloc_type)0;
110 }
111 
112 void
113 _IO_wstr_init_readonly (fp, ptr, size)
114      _IO_FILE *fp;
115      const char *ptr;
116      int size;
117 {
118   _IO_wstr_init_static (fp, (wchar_t *) ptr, size, NULL);
119   fp->_IO_file_flags |= _IO_NO_WRITES;
120 }
121 
122 _IO_wint_t
123 _IO_wstr_overflow (fp, c)
124      _IO_FILE *fp;
125      _IO_wint_t c;
126 {
127   int flush_only = c == WEOF;
128   _IO_size_t pos;
129   if (fp->_flags & _IO_NO_WRITES)
130       return flush_only ? 0 : WEOF;
131   if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
132     {
133       fp->_flags |= _IO_CURRENTLY_PUTTING;
134       fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
135       fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
136     }
137   pos =  fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
138   if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only))
139     {
140       if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
141 	return WEOF;
142       else
143 	{
144 	  wchar_t *new_buf;
145 	  wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
146 	  _IO_size_t new_size = 2 * _IO_wblen (fp) + 100;
147 	  new_buf
148 	    = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
149 									* sizeof (wchar_t));
150 	  if (new_buf == NULL)
151 	    {
152 	      /*	  __ferror(fp) = 1; */
153 	      return WEOF;
154 	    }
155 	  if (old_buf)
156 	    {
157 	      __wmemcpy (new_buf, old_buf, _IO_wblen (fp));
158 	      (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
159 	      /* Make sure _IO_setb won't try to delete _IO_buf_base. */
160 	      fp->_wide_data->_IO_buf_base = NULL;
161 	    }
162 	  INTUSE(_IO_wsetb) (fp, new_buf, new_buf + new_size, 1);
163 	  fp->_wide_data->_IO_read_base =
164 	    new_buf + (fp->_wide_data->_IO_read_base - old_buf);
165 	  fp->_wide_data->_IO_read_ptr =
166 	    new_buf + (fp->_wide_data->_IO_read_ptr - old_buf);
167 	  fp->_wide_data->_IO_read_end =
168 	    new_buf + (fp->_wide_data->_IO_read_end - old_buf);
169 	  fp->_wide_data->_IO_write_ptr =
170 	    new_buf + (fp->_wide_data->_IO_write_ptr - old_buf);
171 
172 	  fp->_wide_data->_IO_write_base = new_buf;
173 	  fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end;
174 	}
175     }
176 
177   if (!flush_only)
178     *fp->_wide_data->_IO_write_ptr++ = c;
179   if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
180     fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
181   return c;
182 }
183 
184 _IO_wint_t
185 _IO_wstr_underflow (fp)
186      _IO_FILE *fp;
187 {
188   if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
189     fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
190   if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
191     {
192       fp->_flags &= ~_IO_CURRENTLY_PUTTING;
193       fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
194       fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end;
195     }
196   if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
197     return *fp->_wide_data->_IO_read_ptr;
198   else
199     return WEOF;
200 }
201 
202 /* The size of the valid part of the buffer.  */
203 
204 _IO_ssize_t
205 _IO_wstr_count (fp)
206      _IO_FILE *fp;
207 {
208   return ((fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end
209 	   ? fp->_wide_data->_IO_write_ptr : fp->_wide_data->_IO_read_end)
210 	  - fp->_wide_data->_IO_read_base);
211 }
212 
213 _IO_off64_t
214 _IO_wstr_seekoff (fp, offset, dir, mode)
215      _IO_FILE *fp;
216      _IO_off64_t offset;
217      int dir;
218      int mode;
219 {
220   _IO_off64_t new_pos;
221 
222   if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
223     mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
224 
225   if (mode == 0)
226     {
227       /* Don't move any pointers. But there is no clear indication what
228 	 mode FP is in. Let's guess. */
229       if (fp->_IO_file_flags & _IO_NO_WRITES)
230         new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base;
231       else
232         new_pos = (fp->_wide_data->_IO_write_ptr
233 		   - fp->_wide_data->_IO_write_base);
234     }
235   else
236     {
237       _IO_ssize_t cur_size = _IO_wstr_count (fp);
238       new_pos = EOF;
239 
240       /* Move the get pointer, if requested. */
241       if (mode & _IOS_INPUT)
242 	{
243 	  switch (dir)
244 	    {
245 	    case _IO_seek_end:
246 	      offset += cur_size;
247 	      break;
248 	    case _IO_seek_cur:
249 	      offset += (fp->_wide_data->_IO_read_ptr
250 			 - fp->_wide_data->_IO_read_base);
251 	      break;
252 	    default: /* case _IO_seek_set: */
253 	      break;
254 	    }
255 	  if (offset < 0 || (_IO_ssize_t) offset > cur_size)
256 	    return EOF;
257 	  fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
258 					  + offset);
259 	  fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base
260 					  + cur_size);
261 	  new_pos = offset;
262 	}
263 
264       /* Move the put pointer, if requested. */
265       if (mode & _IOS_OUTPUT)
266 	{
267 	  switch (dir)
268 	    {
269 	    case _IO_seek_end:
270 	      offset += cur_size;
271 	      break;
272 	    case _IO_seek_cur:
273 	      offset += (fp->_wide_data->_IO_write_ptr
274 			 - fp->_wide_data->_IO_write_base);
275 	      break;
276 	    default: /* case _IO_seek_set: */
277 	      break;
278 	    }
279 	  if (offset < 0 || (_IO_ssize_t) offset > cur_size)
280 	    return EOF;
281 	  fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
282 					   + offset);
283 	  new_pos = offset;
284 	}
285     }
286   return new_pos;
287 }
288 
289 _IO_wint_t
290 _IO_wstr_pbackfail (fp, c)
291      _IO_FILE *fp;
292      _IO_wint_t c;
293 {
294   if ((fp->_flags & _IO_NO_WRITES) && c != WEOF)
295     return WEOF;
296   return INTUSE(_IO_wdefault_pbackfail) (fp, c);
297 }
298 
299 void
300 _IO_wstr_finish (fp, dummy)
301      _IO_FILE *fp;
302      int dummy;
303 {
304   if (fp->_wide_data->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
305     (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
306   fp->_wide_data->_IO_buf_base = NULL;
307 
308   INTUSE(_IO_wdefault_finish) (fp, 0);
309 }
310 
311 struct _IO_jump_t _IO_wstr_jumps =
312 {
313   JUMP_INIT_DUMMY,
314   JUMP_INIT(finish, _IO_wstr_finish),
315   JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
316   JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
317   JUMP_INIT(uflow, (_IO_underflow_t) INTUSE(_IO_wdefault_uflow)),
318   JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
319   JUMP_INIT(xsputn, INTUSE(_IO_wdefault_xsputn)),
320   JUMP_INIT(xsgetn, INTUSE(_IO_wdefault_xsgetn)),
321   JUMP_INIT(seekoff, _IO_wstr_seekoff),
322   JUMP_INIT(seekpos, _IO_default_seekpos),
323   JUMP_INIT(setbuf, _IO_default_setbuf),
324   JUMP_INIT(sync, _IO_default_sync),
325   JUMP_INIT(doallocate, INTUSE(_IO_wdefault_doallocate)),
326   JUMP_INIT(read, _IO_default_read),
327   JUMP_INIT(write, _IO_default_write),
328   JUMP_INIT(seek, _IO_default_seek),
329   JUMP_INIT(close, _IO_default_close),
330   JUMP_INIT(stat, _IO_default_stat),
331   JUMP_INIT(showmanyc, _IO_default_showmanyc),
332   JUMP_INIT(imbue, _IO_default_imbue)
333 };
334