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 +}