os/ossrv/genericopenlibs/cstdlib/LSTDIO/FVWRITE.C
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* FVWRITE.C
     2  * 
     3  * Portions Copyright (c) 1990-2004 Nokia Corporation and/or its subsidiary(-ies).
     4  * All rights reserved.
     5  */
     6 
     7 /* No user fns here.  Pesch 15apr92. */
     8 
     9 /*
    10  * Copyright (c) 1990 The Regents of the University of California.
    11  * All rights reserved.
    12  *
    13  * Redistribution and use in source and binary forms are permitted
    14  * provided that the above copyright notice and this paragraph are
    15  * duplicated in all such forms and that any documentation,
    16  * advertising materials, and other materials related to such
    17  * distribution and use acknowledge that the software was developed
    18  * by the University of California, Berkeley.  The name of the
    19  * University may not be used to endorse or promote products derived
    20  * from this software without specific prior written permission.
    21  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
    22  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
    23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    24  */
    25 
    26 #include <stdio_r.h>
    27 #include <string.h>
    28 #include "LOCAL.H"
    29 #include "FVWRITE.H"
    30 
    31 #define	MIN(a, b) ((a) < (b) ? (a) : (b))
    32 #define	COPY(n)	  (void) memmove((void *) fp->_p, (void *) p, (size_t) (n))
    33 
    34 #define GETIOV(extra_work) \
    35   while (len == 0) \
    36     { \
    37       extra_work; \
    38       p = (const char*)iov->iov_base; \
    39       len = iov->iov_len; \
    40       iov++; \
    41     }
    42 
    43 /*
    44  * Write some memory regions.  Return zero on success, EOF on error.
    45  *
    46  * This routine is large and unsightly, but most of the ugliness due
    47  * to the three different kinds of output buffering is handled here.
    48  */
    49 
    50 int
    51 __sfvwrite (register FILE *fp,register struct __suio *uio)
    52 {
    53   register size_t len;
    54   register const char *p;
    55   register struct __siov *iov;
    56   register int w, s;
    57   char *nl;
    58   int nlknown, nldist = -1;
    59 
    60   if ((len = uio->uio_resid) == 0)
    61     return 0;
    62 
    63   /* make sure we can write */
    64   if (cantwrite (fp))
    65     return EOF;
    66 
    67   iov = uio->uio_iov;
    68   len = 0;
    69   if (fp->_flags & __SNBF)
    70     {
    71       /*
    72        * Unbuffered: write up to BUFSIZ bytes at a time.
    73        */
    74       do
    75 	{
    76 	  GETIOV (;);
    77 	  w = (*fp->_write) (fp->_cookie, p, MIN (len, BUFSIZ));
    78 	  if (w <= 0)
    79 	    goto err;
    80 	  p += w;
    81 	  len -= w;
    82 	}
    83       while ((uio->uio_resid -= w) != 0);
    84     }
    85   else if ((fp->_flags & __SLBF) == 0)
    86     {
    87       /*
    88        * Fully buffered: fill partially full buffer, if any,
    89        * and then flush.  If there is no partial buffer, write
    90        * one _bf._size byte chunk directly (without copying).
    91        *
    92        * String output is a special case: write as many bytes
    93        * as fit, but pretend we wrote everything.  This makes
    94        * snprintf() return the number of bytes needed, rather
    95        * than the number used, and avoids its write function
    96        * (so that the write function can be invalid).
    97        */
    98       do
    99 	{
   100 	  GETIOV (;);
   101 	  w = fp->_w;
   102 	  if (fp->_flags & __SSTR)
   103 	    {
   104 	      if ((int)len < w)
   105 		w = len;
   106 	      COPY (w);		/* copy MIN(fp->_w,len), */
   107 	      fp->_w -= w;
   108 	      fp->_p += w;
   109 	      w = len;		/* but pretend copied all */
   110 	    }
   111 	  else if (fp->_p > fp->_bf._base && (int)len > w)
   112 	    {
   113 	      /* fill and flush */
   114 	      COPY (w);
   115 	      /* fp->_w -= w; *//* unneeded */
   116 	      fp->_p += w;
   117 	      if (fflush (fp))
   118 		goto err;
   119 	    }
   120 	  else if ((int)len >= (w = fp->_bf._size))
   121 	    {
   122 	      /* write directly */
   123 	      w = (*fp->_write) (fp->_cookie, p, w);
   124 	      if (w <= 0)
   125 		goto err;
   126 	    }
   127 	  else
   128 	    {
   129 	      /* fill and done */
   130 	      w = len;
   131 	      COPY (w);
   132 	      fp->_w -= w;
   133 	      fp->_p += w;
   134 	    }
   135 	  p += w;
   136 	  len -= w;
   137 	}
   138       while ((uio->uio_resid -= w) != 0);
   139     }
   140   else
   141     {
   142       /*
   143        * Line buffered: like fully buffered, but we
   144        * must check for newlines.  Compute the distance
   145        * to the first newline (including the newline),
   146        * or `infinity' if there is none, then pretend
   147        * that the amount to write is MIN(len,nldist).
   148        */
   149       nlknown = 0;
   150       do
   151 	{
   152 	  GETIOV (nlknown = 0);
   153 	  if (!nlknown)
   154 	    {
   155 	      nl = (char *)memchr ((void *) p, '\n', len);
   156 	      nldist = nl ? nl + 1 - p : len + 1;
   157 	      nlknown = 1;
   158 	    }
   159 	  s = MIN ((int)len, nldist);
   160 	  w = fp->_w + fp->_bf._size;
   161 	  if (fp->_p > fp->_bf._base && s > w)
   162 	    {
   163 	      COPY (w);
   164 	      /* fp->_w -= w; */
   165 	      fp->_p += w;
   166 	      if (fflush (fp))
   167 		goto err;
   168 	    }
   169 	  else if (s >= (w = fp->_bf._size))
   170 	    {
   171 	      w = (*fp->_write) (fp->_cookie, p, w);
   172 	      if (w <= 0)
   173 		goto err;
   174 	    }
   175 	  else
   176 	    {
   177 	      w = s;
   178 	      COPY (w);
   179 	      fp->_w -= w;
   180 	      fp->_p += w;
   181 	    }
   182 	  if ((nldist -= w) == 0)
   183 	    {
   184 	      /* copied the newline: flush and forget */
   185 	      if (fflush (fp))
   186 		goto err;
   187 	      nlknown = 0;
   188 	    }
   189 	  p += w;
   190 	  len -= w;
   191 	}
   192       while ((uio->uio_resid -= w) != 0);
   193     }
   194   return 0;
   195 
   196 err:
   197   fp->_flags |= __SERR;
   198   return EOF;
   199 }