os/ossrv/genericopenlibs/cstdlib/LSTDIO/FVWRITE.C
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/LSTDIO/FVWRITE.C	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,199 @@
     1.4 +/* FVWRITE.C
     1.5 + * 
     1.6 + * Portions Copyright (c) 1990-2004 Nokia Corporation and/or its subsidiary(-ies).
     1.7 + * All rights reserved.
     1.8 + */
     1.9 +
    1.10 +/* No user fns here.  Pesch 15apr92. */
    1.11 +
    1.12 +/*
    1.13 + * Copyright (c) 1990 The Regents of the University of California.
    1.14 + * All rights reserved.
    1.15 + *
    1.16 + * Redistribution and use in source and binary forms are permitted
    1.17 + * provided that the above copyright notice and this paragraph are
    1.18 + * duplicated in all such forms and that any documentation,
    1.19 + * advertising materials, and other materials related to such
    1.20 + * distribution and use acknowledge that the software was developed
    1.21 + * by the University of California, Berkeley.  The name of the
    1.22 + * University may not be used to endorse or promote products derived
    1.23 + * from this software without specific prior written permission.
    1.24 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
    1.25 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
    1.26 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    1.27 + */
    1.28 +
    1.29 +#include <stdio_r.h>
    1.30 +#include <string.h>
    1.31 +#include "LOCAL.H"
    1.32 +#include "FVWRITE.H"
    1.33 +
    1.34 +#define	MIN(a, b) ((a) < (b) ? (a) : (b))
    1.35 +#define	COPY(n)	  (void) memmove((void *) fp->_p, (void *) p, (size_t) (n))
    1.36 +
    1.37 +#define GETIOV(extra_work) \
    1.38 +  while (len == 0) \
    1.39 +    { \
    1.40 +      extra_work; \
    1.41 +      p = (const char*)iov->iov_base; \
    1.42 +      len = iov->iov_len; \
    1.43 +      iov++; \
    1.44 +    }
    1.45 +
    1.46 +/*
    1.47 + * Write some memory regions.  Return zero on success, EOF on error.
    1.48 + *
    1.49 + * This routine is large and unsightly, but most of the ugliness due
    1.50 + * to the three different kinds of output buffering is handled here.
    1.51 + */
    1.52 +
    1.53 +int
    1.54 +__sfvwrite (register FILE *fp,register struct __suio *uio)
    1.55 +{
    1.56 +  register size_t len;
    1.57 +  register const char *p;
    1.58 +  register struct __siov *iov;
    1.59 +  register int w, s;
    1.60 +  char *nl;
    1.61 +  int nlknown, nldist = -1;
    1.62 +
    1.63 +  if ((len = uio->uio_resid) == 0)
    1.64 +    return 0;
    1.65 +
    1.66 +  /* make sure we can write */
    1.67 +  if (cantwrite (fp))
    1.68 +    return EOF;
    1.69 +
    1.70 +  iov = uio->uio_iov;
    1.71 +  len = 0;
    1.72 +  if (fp->_flags & __SNBF)
    1.73 +    {
    1.74 +      /*
    1.75 +       * Unbuffered: write up to BUFSIZ bytes at a time.
    1.76 +       */
    1.77 +      do
    1.78 +	{
    1.79 +	  GETIOV (;);
    1.80 +	  w = (*fp->_write) (fp->_cookie, p, MIN (len, BUFSIZ));
    1.81 +	  if (w <= 0)
    1.82 +	    goto err;
    1.83 +	  p += w;
    1.84 +	  len -= w;
    1.85 +	}
    1.86 +      while ((uio->uio_resid -= w) != 0);
    1.87 +    }
    1.88 +  else if ((fp->_flags & __SLBF) == 0)
    1.89 +    {
    1.90 +      /*
    1.91 +       * Fully buffered: fill partially full buffer, if any,
    1.92 +       * and then flush.  If there is no partial buffer, write
    1.93 +       * one _bf._size byte chunk directly (without copying).
    1.94 +       *
    1.95 +       * String output is a special case: write as many bytes
    1.96 +       * as fit, but pretend we wrote everything.  This makes
    1.97 +       * snprintf() return the number of bytes needed, rather
    1.98 +       * than the number used, and avoids its write function
    1.99 +       * (so that the write function can be invalid).
   1.100 +       */
   1.101 +      do
   1.102 +	{
   1.103 +	  GETIOV (;);
   1.104 +	  w = fp->_w;
   1.105 +	  if (fp->_flags & __SSTR)
   1.106 +	    {
   1.107 +	      if ((int)len < w)
   1.108 +		w = len;
   1.109 +	      COPY (w);		/* copy MIN(fp->_w,len), */
   1.110 +	      fp->_w -= w;
   1.111 +	      fp->_p += w;
   1.112 +	      w = len;		/* but pretend copied all */
   1.113 +	    }
   1.114 +	  else if (fp->_p > fp->_bf._base && (int)len > w)
   1.115 +	    {
   1.116 +	      /* fill and flush */
   1.117 +	      COPY (w);
   1.118 +	      /* fp->_w -= w; *//* unneeded */
   1.119 +	      fp->_p += w;
   1.120 +	      if (fflush (fp))
   1.121 +		goto err;
   1.122 +	    }
   1.123 +	  else if ((int)len >= (w = fp->_bf._size))
   1.124 +	    {
   1.125 +	      /* write directly */
   1.126 +	      w = (*fp->_write) (fp->_cookie, p, w);
   1.127 +	      if (w <= 0)
   1.128 +		goto err;
   1.129 +	    }
   1.130 +	  else
   1.131 +	    {
   1.132 +	      /* fill and done */
   1.133 +	      w = len;
   1.134 +	      COPY (w);
   1.135 +	      fp->_w -= w;
   1.136 +	      fp->_p += w;
   1.137 +	    }
   1.138 +	  p += w;
   1.139 +	  len -= w;
   1.140 +	}
   1.141 +      while ((uio->uio_resid -= w) != 0);
   1.142 +    }
   1.143 +  else
   1.144 +    {
   1.145 +      /*
   1.146 +       * Line buffered: like fully buffered, but we
   1.147 +       * must check for newlines.  Compute the distance
   1.148 +       * to the first newline (including the newline),
   1.149 +       * or `infinity' if there is none, then pretend
   1.150 +       * that the amount to write is MIN(len,nldist).
   1.151 +       */
   1.152 +      nlknown = 0;
   1.153 +      do
   1.154 +	{
   1.155 +	  GETIOV (nlknown = 0);
   1.156 +	  if (!nlknown)
   1.157 +	    {
   1.158 +	      nl = (char *)memchr ((void *) p, '\n', len);
   1.159 +	      nldist = nl ? nl + 1 - p : len + 1;
   1.160 +	      nlknown = 1;
   1.161 +	    }
   1.162 +	  s = MIN ((int)len, nldist);
   1.163 +	  w = fp->_w + fp->_bf._size;
   1.164 +	  if (fp->_p > fp->_bf._base && s > w)
   1.165 +	    {
   1.166 +	      COPY (w);
   1.167 +	      /* fp->_w -= w; */
   1.168 +	      fp->_p += w;
   1.169 +	      if (fflush (fp))
   1.170 +		goto err;
   1.171 +	    }
   1.172 +	  else if (s >= (w = fp->_bf._size))
   1.173 +	    {
   1.174 +	      w = (*fp->_write) (fp->_cookie, p, w);
   1.175 +	      if (w <= 0)
   1.176 +		goto err;
   1.177 +	    }
   1.178 +	  else
   1.179 +	    {
   1.180 +	      w = s;
   1.181 +	      COPY (w);
   1.182 +	      fp->_w -= w;
   1.183 +	      fp->_p += w;
   1.184 +	    }
   1.185 +	  if ((nldist -= w) == 0)
   1.186 +	    {
   1.187 +	      /* copied the newline: flush and forget */
   1.188 +	      if (fflush (fp))
   1.189 +		goto err;
   1.190 +	      nlknown = 0;
   1.191 +	    }
   1.192 +	  p += w;
   1.193 +	  len -= w;
   1.194 +	}
   1.195 +      while ((uio->uio_resid -= w) != 0);
   1.196 +    }
   1.197 +  return 0;
   1.198 +
   1.199 +err:
   1.200 +  fp->_flags |= __SERR;
   1.201 +  return EOF;
   1.202 +}