Back to index

glibc  2.9
wstrops.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993,1997-1999,2001-2004, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.
00018 
00019    As a special exception, if you link the code in this file with
00020    files compiled with a GNU compiler to produce an executable,
00021    that does not cause the resulting executable to be covered by
00022    the GNU Lesser General Public License.  This exception does not
00023    however invalidate any other reasons why the executable file
00024    might be covered by the GNU Lesser General Public License.
00025    This exception applies to code released by its copyright holders
00026    in files containing the exception.  */
00027 
00028 #include <assert.h>
00029 #include "strfile.h"
00030 #include "libioP.h"
00031 #include <string.h>
00032 #include <wchar.h>
00033 #include <stdio_ext.h>
00034 
00035 void
00036 _IO_wstr_init_static (fp, ptr, size, pstart)
00037      _IO_FILE *fp;
00038      wchar_t *ptr;
00039      _IO_size_t size;
00040      wchar_t *pstart;
00041 {
00042   wchar_t *end;
00043 
00044   if (size == 0)
00045     end = ptr + __wcslen (ptr);
00046   else if ((_IO_size_t) ptr + size * sizeof (wchar_t) > (_IO_size_t) ptr)
00047     end = ptr + size;
00048   else
00049     /* Even for misaligned ptr make sure there is integral number of wide
00050        characters.  */
00051     end = ptr + (-1 - (_IO_size_t) ptr) / sizeof (wchar_t);
00052   INTUSE(_IO_wsetb) (fp, ptr, end, 0);
00053 
00054   fp->_wide_data->_IO_write_base = ptr;
00055   fp->_wide_data->_IO_read_base = ptr;
00056   fp->_wide_data->_IO_read_ptr = ptr;
00057   if (pstart)
00058     {
00059       fp->_wide_data->_IO_write_ptr = pstart;
00060       fp->_wide_data->_IO_write_end = end;
00061       fp->_wide_data->_IO_read_end = pstart;
00062     }
00063   else
00064     {
00065       fp->_wide_data->_IO_write_ptr = ptr;
00066       fp->_wide_data->_IO_write_end = ptr;
00067       fp->_wide_data->_IO_read_end = end;
00068     }
00069   /* A null _allocate_buffer function flags the strfile as being static. */
00070   (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0;
00071 }
00072 
00073 _IO_wint_t
00074 _IO_wstr_overflow (fp, c)
00075      _IO_FILE *fp;
00076      _IO_wint_t c;
00077 {
00078   int flush_only = c == WEOF;
00079   _IO_size_t pos;
00080   if (fp->_flags & _IO_NO_WRITES)
00081       return flush_only ? 0 : WEOF;
00082   if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
00083     {
00084       fp->_flags |= _IO_CURRENTLY_PUTTING;
00085       fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
00086       fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
00087     }
00088   pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
00089   if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only))
00090     {
00091       if (fp->_flags2 & _IO_FLAGS2_USER_WBUF) /* not allowed to enlarge */
00092        return WEOF;
00093       else
00094        {
00095          wchar_t *new_buf;
00096          wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
00097          size_t old_wblen = _IO_wblen (fp);
00098          _IO_size_t new_size = 2 * old_wblen + 100;
00099          if (new_size < old_wblen)
00100            return EOF;
00101          new_buf
00102            = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
00103                                                                * sizeof (wchar_t));
00104          if (new_buf == NULL)
00105            {
00106              /*        __ferror(fp) = 1; */
00107              return WEOF;
00108            }
00109          if (old_buf)
00110            {
00111              __wmemcpy (new_buf, old_buf, old_wblen);
00112              (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
00113              /* Make sure _IO_setb won't try to delete _IO_buf_base. */
00114              fp->_wide_data->_IO_buf_base = NULL;
00115            }
00116 
00117          wmemset (new_buf + old_wblen, L'\0', new_size - old_wblen);
00118 
00119          INTUSE(_IO_wsetb) (fp, new_buf, new_buf + new_size, 1);
00120          fp->_wide_data->_IO_read_base =
00121            new_buf + (fp->_wide_data->_IO_read_base - old_buf);
00122          fp->_wide_data->_IO_read_ptr =
00123            new_buf + (fp->_wide_data->_IO_read_ptr - old_buf);
00124          fp->_wide_data->_IO_read_end =
00125            new_buf + (fp->_wide_data->_IO_read_end - old_buf);
00126          fp->_wide_data->_IO_write_ptr =
00127            new_buf + (fp->_wide_data->_IO_write_ptr - old_buf);
00128 
00129          fp->_wide_data->_IO_write_base = new_buf;
00130          fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end;
00131        }
00132     }
00133 
00134   if (!flush_only)
00135     *fp->_wide_data->_IO_write_ptr++ = c;
00136   if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
00137     fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
00138   return c;
00139 }
00140 
00141 
00142 _IO_wint_t
00143 _IO_wstr_underflow (fp)
00144      _IO_FILE *fp;
00145 {
00146   if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
00147     fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
00148   if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
00149     {
00150       fp->_flags &= ~_IO_CURRENTLY_PUTTING;
00151       fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
00152       fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end;
00153     }
00154   if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
00155     return *fp->_wide_data->_IO_read_ptr;
00156   else
00157     return WEOF;
00158 }
00159 
00160 
00161 /* The size of the valid part of the buffer.  */
00162 _IO_ssize_t
00163 _IO_wstr_count (fp)
00164      _IO_FILE *fp;
00165 {
00166   struct _IO_wide_data *wd = fp->_wide_data;
00167 
00168   return ((wd->_IO_write_ptr > wd->_IO_read_end
00169           ? wd->_IO_write_ptr : wd->_IO_read_end)
00170          - wd->_IO_read_base);
00171 }
00172 
00173 
00174 static int
00175 enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
00176 {
00177   if ((_IO_ssize_t) offset <= _IO_blen (fp))
00178     return 0;
00179 
00180   struct _IO_wide_data *wd = fp->_wide_data;
00181 
00182   _IO_ssize_t oldend = wd->_IO_write_end - wd->_IO_write_base;
00183 
00184   /* Try to enlarge the buffer.  */
00185   if (fp->_flags2 & _IO_FLAGS2_USER_WBUF)
00186     /* User-provided buffer.  */
00187     return 1;
00188 
00189   _IO_size_t newsize = offset + 100;
00190   wchar_t *oldbuf = wd->_IO_buf_base;
00191   wchar_t *newbuf
00192     = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize
00193                                                         * sizeof (wchar_t));
00194   if (newbuf == NULL)
00195     return 1;
00196 
00197   if (oldbuf != NULL)
00198     {
00199       __wmemcpy (newbuf, oldbuf, _IO_wblen (fp));
00200       (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
00201       /* Make sure _IO_setb won't try to delete
00202         _IO_buf_base. */
00203       wd->_IO_buf_base = NULL;
00204     }
00205 
00206   INTUSE(_IO_wsetb) (fp, newbuf, newbuf + newsize, 1);
00207 
00208   if (reading)
00209     {
00210       wd->_IO_write_base = newbuf + (wd->_IO_write_base - oldbuf);
00211       wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf);
00212       wd->_IO_write_end = newbuf + (wd->_IO_write_end - oldbuf);
00213       wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf);
00214 
00215       wd->_IO_read_base = newbuf;
00216       wd->_IO_read_end = wd->_IO_buf_end;
00217     }
00218   else
00219     {
00220       wd->_IO_read_base = newbuf + (wd->_IO_read_base - oldbuf);
00221       wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf);
00222       wd->_IO_read_end = newbuf + (wd->_IO_read_end - oldbuf);
00223       wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf);
00224 
00225       wd->_IO_write_base = newbuf;
00226       wd->_IO_write_end = wd->_IO_buf_end;
00227     }
00228 
00229   /* Clear the area between the last write position and th
00230      new position.  */
00231   assert (offset >= oldend);
00232   if (reading)
00233     wmemset (wd->_IO_read_base + oldend, L'\0', offset - oldend);
00234   else
00235     wmemset (wd->_IO_write_base + oldend, L'\0', offset - oldend);
00236 
00237   return 0;
00238 }
00239 
00240 
00241 _IO_off64_t
00242 _IO_wstr_seekoff (fp, offset, dir, mode)
00243      _IO_FILE *fp;
00244      _IO_off64_t offset;
00245      int dir;
00246      int mode;
00247 {
00248   _IO_off64_t new_pos;
00249 
00250   if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
00251     mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
00252 
00253   if (mode == 0)
00254     {
00255       /* Don't move any pointers. But there is no clear indication what
00256         mode FP is in. Let's guess. */
00257       if (fp->_IO_file_flags & _IO_NO_WRITES)
00258         new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base;
00259       else
00260         new_pos = (fp->_wide_data->_IO_write_ptr
00261                  - fp->_wide_data->_IO_write_base);
00262     }
00263   else
00264     {
00265       _IO_ssize_t cur_size = _IO_wstr_count (fp);
00266       new_pos = EOF;
00267 
00268       /* Move the get pointer, if requested. */
00269       if (mode & _IOS_INPUT)
00270        {
00271          switch (dir)
00272            {
00273            case _IO_seek_end:
00274              offset += cur_size;
00275              break;
00276            case _IO_seek_cur:
00277              offset += (fp->_wide_data->_IO_read_ptr
00278                       - fp->_wide_data->_IO_read_base);
00279              break;
00280            default: /* case _IO_seek_set: */
00281              break;
00282            }
00283          if (offset < 0)
00284            return EOF;
00285          if ((_IO_ssize_t) offset > cur_size
00286              && enlarge_userbuf (fp, offset, 1) != 0)
00287            return EOF;
00288          fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
00289                                      + offset);
00290          fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base
00291                                      + cur_size);
00292          new_pos = offset;
00293        }
00294 
00295       /* Move the put pointer, if requested. */
00296       if (mode & _IOS_OUTPUT)
00297        {
00298          switch (dir)
00299            {
00300            case _IO_seek_end:
00301              offset += cur_size;
00302              break;
00303            case _IO_seek_cur:
00304              offset += (fp->_wide_data->_IO_write_ptr
00305                       - fp->_wide_data->_IO_write_base);
00306              break;
00307            default: /* case _IO_seek_set: */
00308              break;
00309            }
00310          if (offset < 0)
00311            return EOF;
00312          if ((_IO_ssize_t) offset > cur_size
00313              && enlarge_userbuf (fp, offset, 0) != 0)
00314            return EOF;
00315          fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
00316                                       + offset);
00317          new_pos = offset;
00318        }
00319     }
00320   return new_pos;
00321 }
00322 
00323 _IO_wint_t
00324 _IO_wstr_pbackfail (fp, c)
00325      _IO_FILE *fp;
00326      _IO_wint_t c;
00327 {
00328   if ((fp->_flags & _IO_NO_WRITES) && c != WEOF)
00329     return WEOF;
00330   return INTUSE(_IO_wdefault_pbackfail) (fp, c);
00331 }
00332 
00333 void
00334 _IO_wstr_finish (fp, dummy)
00335      _IO_FILE *fp;
00336      int dummy;
00337 {
00338   if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
00339     (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
00340   fp->_wide_data->_IO_buf_base = NULL;
00341 
00342   INTUSE(_IO_wdefault_finish) (fp, 0);
00343 }
00344 
00345 const struct _IO_jump_t _IO_wstr_jumps =
00346 {
00347   JUMP_INIT_DUMMY,
00348   JUMP_INIT(finish, _IO_wstr_finish),
00349   JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
00350   JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
00351   JUMP_INIT(uflow, (_IO_underflow_t) INTUSE(_IO_wdefault_uflow)),
00352   JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
00353   JUMP_INIT(xsputn, INTUSE(_IO_wdefault_xsputn)),
00354   JUMP_INIT(xsgetn, INTUSE(_IO_wdefault_xsgetn)),
00355   JUMP_INIT(seekoff, _IO_wstr_seekoff),
00356   JUMP_INIT(seekpos, _IO_default_seekpos),
00357   JUMP_INIT(setbuf, _IO_default_setbuf),
00358   JUMP_INIT(sync, _IO_default_sync),
00359   JUMP_INIT(doallocate, INTUSE(_IO_wdefault_doallocate)),
00360   JUMP_INIT(read, _IO_default_read),
00361   JUMP_INIT(write, _IO_default_write),
00362   JUMP_INIT(seek, _IO_default_seek),
00363   JUMP_INIT(close, _IO_default_close),
00364   JUMP_INIT(stat, _IO_default_stat),
00365   JUMP_INIT(showmanyc, _IO_default_showmanyc),
00366   JUMP_INIT(imbue, _IO_default_imbue)
00367 };