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