]> pd.if.org Git - pdclib.old/blobdiff - functions/stdio/fwrite.c
fwrite: output line buffered content as we go along
[pdclib.old] / functions / stdio / fwrite.c
index d2698b840de8efca2f10f0e03eeb338f76f5eaaf..d0efadb207df354eabdca050be5819c1756a370d 100644 (file)
-/* ----------------------------------------------------------------------------
- * $Id$
- * ----------------------------------------------------------------------------
- * Public Domain C Library - http://pdclib.sourceforge.net
- * This code is Public Domain. Use, modify, and redistribute at will.
- * --------------------------------------------------------------------------*/
+/* $Id$ */
 
-size_t fwrite( const void * restrict ptr, size_t size, size_t nelem, FILE * restrict stream ) { /* TODO */ };
+/* fwrite( const void *, size_t, size_t, FILE * )
 
-/* PDPC code - unreviewed, verbatim.
-Read the note in fopen.c.
-#ifndef __MVS__
-size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
-    size_t towrite;
-    size_t elemWritten;
-#ifdef __OS2__
-    ULONG actualWritten;
-    APIRET rc;
-#endif
-#ifdef __MSDOS__
-    size_t actualWritten;
-    int errind;
-#endif
-
-    if (nmemb == 1)
-    {
-        towrite = size;
-    }
-    else if (size == 1)
-    {
-        towrite = nmemb;
-    }
-    else
-    {
-        towrite = size * nmemb;
-    }
-    if (towrite < stream->szfbuf)
-    {
-        stream->quickBin = 0;
-        if ((stream->bufTech == _IONBF) && !stream->textMode)
-        {
-            stream->quickBin = 1;
-        }
-    }
-    if (!stream->quickBin)
-    {
-        fwriteSlow(ptr, size, nmemb, stream, towrite, &elemWritten);
-        return (elemWritten);
-    }
-    else
-    {
-#ifdef __OS2__
-        rc = DosWrite(stream->hfile, (VOID *)ptr, towrite, &actualWritten);
-        if (rc != 0)
-        {
-            stream->errorInd = 1;
-            actualWritten = 0;
-            errno = rc;
-        }
-#endif
-#ifdef __MSDOS__
-        actualWritten = __write(stream->hfile,
-                                ptr,
-                                towrite,
-                                &errind);
-        if (errind)
-        {
-            stream->errorInd = 1;
-            actualWritten = 0;
-            errno = actualWritten;
-        }
-#endif
-        if (nmemb == 1)
-        {
-            if (actualWritten == size)
-            {
-                elemWritten = 1;
-            }
-            else
-            {
-                elemWritten = 0;
-            }
-        }
-        else if (size == 1)
-        {
-            elemWritten = actualWritten;
-        }
-        else
-        {
-            elemWritten = actualWritten / size;
-        }
-        stream->bufStartR += actualWritten;
-        return (elemWritten);
-    }
-}
+   This file is part of the Public Domain C Library (PDCLib).
+   Permission is granted to use, modify, and / or redistribute at will.
+*/
 
-static void fwriteSlow(const void *ptr,
-                       size_t size,
-                       size_t nmemb,
-                       FILE *stream,
-                       size_t towrite,
-                       size_t *elemWritten)
-{
-    size_t actualWritten;
-
-    /* Normally, on output, there will never be a situation where
-       the write buffer is full, but it hasn't been written out.
-       If we find this to be the case, then it is because we have
-       done an fseek, and didn't know whether we were going to do
-       a read or a write after it, so now that we know, we switch
-       the buffer to being set up for write.  We could use a flag,
-       but I thought it would be better to just put some magic
-       code in with a comment */
-    if (stream->upto == stream->endbuf)
-    {
-        stream->bufStartR += (stream->endbuf - stream->fbuf);
-        stream->upto = stream->fbuf;
-        stream->mode = __WRITE_MODE;
-    }
-    if ((stream->textMode) || (stream->bufTech == _IOLBF))
-    {
-        fwriteSlowT(ptr, stream, towrite, &actualWritten);
-    }
-    else
-    {
-        fwriteSlowB(ptr, stream, towrite, &actualWritten);
-    }
-    if (nmemb == 1)
-    {
-        if (actualWritten == size)
-        {
-            *elemWritten = 1;
-        }
-        else
-        {
-            *elemWritten = 0;
-        }
-    }
-    else if (size == 1)
-    {
-        *elemWritten = actualWritten;
-    }
-    else
-    {
-        *elemWritten = actualWritten / size;
-    }
-    return;
-}
+#include <stdio.h>
 
+#ifndef REGTEST
+#include <_PDCLIB_io.h>
+#include <_PDCLIB_glue.h>
 
-/* can still be called on binary files, if the binary file is
-   line buffered  */
+#include <stdbool.h>
+#include <string.h>
 
-static void fwriteSlowT(const void *ptr,
-                        FILE *stream,
-                        size_t towrite,
-                        size_t *actualWritten)
+size_t _PDCLIB_fwrite_unlocked( const void *restrict vptr,
+               size_t size, size_t nmemb,
+               FILE * _PDCLIB_restrict stream )
 {
-    char *p;
-    char *tptr;
-    char *oldp;
-    size_t diffp;
-    size_t rem;
-    int fin;
-#ifdef __OS2__
-    ULONG tempWritten;
-    APIRET rc;
-#endif
-#ifdef __MSDOS__
-    size_t tempWritten;
-    int errind;
-#endif
+    if ( _PDCLIB_prepwrite( stream ) == EOF )
+    {
+        return 0;
+    }
 
-    *actualWritten = 0;
-    tptr = (char *)ptr;
-    p = tptr;
-    oldp = p;
-    p = (char *)memchr(oldp, '\n', towrite - (size_t)(oldp - tptr));
-    while (p != NULL)
+    const char *restrict ptr = vptr;
+    size_t nmemb_i;
+    for ( nmemb_i = 0; nmemb_i < nmemb; ++nmemb_i )
     {
-        diffp = (size_t)(p - oldp);
-        fin = 0;
-        while (!fin)
+        for ( size_t size_i = 0; size_i < size; ++size_i )
         {
-            rem = (size_t)(stream->endbuf - stream->upto);
-            if (diffp < rem)
-            {
-                memcpy(stream->upto, oldp, diffp);
-                stream->upto += diffp;
-                *actualWritten += diffp;
-                fin = 1;
-            }
-            else
+            char c = ptr[ nmemb_i * size + size_i ];
+            stream->buffer[ stream->bufidx++ ] = c;
+
+            if ( stream->bufidx == stream->bufsize || ( c == '\n' && stream->status & _IOLBF ) )
             {
-                memcpy(stream->upto, oldp, rem);
-                oldp += rem;
-                diffp -= rem;
-#ifdef __OS2__
-                rc = DosWrite(stream->hfile,
-                              stream->fbuf,
-                              stream->szfbuf,
-                              &tempWritten);
-                if (rc != 0)
-                {
-                    stream->errorInd = 1;
-                    return;
-                }
-#endif
-#ifdef __MSDOS__
-                tempWritten = __write(stream->hfile,
-                                      stream->fbuf,
-                                      stream->szfbuf,
-                                      &errind);
-                if (errind)
-                {
-                    stream->errorInd = 1;
-                    return;
-                }
-#endif
-                else
+                if ( _PDCLIB_flushbuffer( stream ) == EOF )
                 {
-                    *actualWritten += rem;
-                    stream->upto = stream->fbuf;
-                    stream->bufStartR += tempWritten;
+                    /* Returning number of objects completely buffered */
+                    return nmemb_i;
                 }
             }
         }
-        rem = (size_t)(stream->endbuf - stream->upto);
-        if (rem < 2)
-        {
-#ifdef __OS2__
-            rc = DosWrite(stream->hfile,
-                          stream->fbuf,
-                          (size_t)(stream->upto - stream->fbuf),
-                          &tempWritten);
-            if (rc != 0)
-            {
-                stream->errorInd = 1;
-                errno = rc;
-                return;
-            }
-#endif
-#ifdef __MSDOS__
-            tempWritten = __write(stream->hfile,
-                                  stream->fbuf,
-                                  (size_t)(stream->upto - stream->fbuf),
-                                  &errind);
-            if (errind)
-            {
-                stream->errorInd = 1;
-                errno = tempWritten;
-                return;
-            }
-#endif
-            stream->upto = stream->fbuf;
-            stream->bufStartR += tempWritten;
-        }
-        if (stream->textMode)
-        {
-            memcpy(stream->upto, "\r\n", 2);
-            stream->upto += 2;
-        }
-        else
-        {
-            memcpy(stream->upto, "\n", 1);
-            stream->upto += 1;
-        }
-        *actualWritten += 1;
-        oldp = p + 1;
-        p = (char *)memchr(oldp, '\n', towrite - (size_t)(oldp - tptr));
-    }
-
-    if ((stream->bufTech == _IOLBF)
-        && (stream->upto != stream->fbuf)
-        && (oldp != tptr))
-    {
-#ifdef __OS2__
-        rc = DosWrite(stream->hfile,
-                      stream->fbuf,
-                      (size_t)(stream->upto - stream->fbuf),
-                      &tempWritten);
-        if (rc != 0)
-        {
-            stream->errorInd = 1;
-            errno = rc;
-            return;
-        }
-#endif
-#ifdef __MSDOS__
-        tempWritten = __write(stream->hfile,
-                              stream->fbuf,
-                              (size_t)(stream->upto - stream->fbuf),
-                              &errind);
-        if (errind)
-        {
-            stream->errorInd = 1;
-            errno = tempWritten;
-            return;
-        }
-#endif
-        stream->upto = stream->fbuf;
-        stream->bufStartR += tempWritten;
-    }
 
-    diffp = towrite - *actualWritten;
-    while (diffp != 0)
-    {
-        rem = (size_t)(stream->endbuf - stream->upto);
-        if (diffp < rem)
-        {
-            memcpy(stream->upto, oldp, diffp);
-            stream->upto += diffp;
-            *actualWritten += diffp;
-        }
-        else
+        if ( stream->status & _IONBF )
         {
-            memcpy(stream->upto, oldp, rem);
-#ifdef __OS2__
-            rc = DosWrite(stream->hfile,
-                          stream->fbuf,
-                          stream->szfbuf,
-                          &tempWritten);
-            if (rc != 0)
+            if ( _PDCLIB_flushbuffer( stream ) == EOF )
             {
-                stream->errorInd = 1;
-                errno = rc;
-                return;
+                /* Returning number of objects completely buffered */
+                return nmemb_i;
             }
-#endif
-#ifdef __MSDOS__
-            tempWritten = __write(stream->hfile,
-                                  stream->fbuf,
-                                  stream->szfbuf,
-                                  &errind);
-            if (errind)
-            {
-                stream->errorInd = 1;
-                errno = tempWritten;
-                return;
-            }
-#endif
-            else
-            {
-                *actualWritten += rem;
-                stream->upto = stream->fbuf;
-            }
-            stream->bufStartR += tempWritten;
-            oldp += rem;
         }
-        diffp = towrite - *actualWritten;
     }
-    if ((stream->bufTech == _IONBF)
-        && (stream->upto != stream->fbuf))
-    {
-#ifdef __OS2__
-        rc = DosWrite(stream->hfile,
-                      stream->fbuf,
-                      (size_t)(stream->upto - stream->fbuf),
-                      &tempWritten);
-        if (rc != 0)
-        {
-            stream->errorInd = 1;
-            errno = rc;
-            return;
-        }
-#endif
-#ifdef __MSDOS__
-        tempWritten = __write(stream->hfile,
-                              stream->fbuf,
-                              (size_t)(stream->upto - stream->fbuf),
-                              &errind);
-        if (errind)
-        {
-            stream->errorInd = 1;
-            errno = tempWritten;
-            return;
-        }
-#endif
-        stream->upto = stream->fbuf;
-        stream->bufStartR += tempWritten;
-    }
-    return;
+    return nmemb_i;
 }
 
-/* whilst write requests are smaller than a buffer, we do not turn
-   on quickbin */
-
-static void fwriteSlowB(const void *ptr,
-                        FILE *stream,
-                        size_t towrite,
-                        size_t *actualWritten)
+size_t fwrite( const void * _PDCLIB_restrict ptr,
+               size_t size, size_t nmemb,
+               FILE * _PDCLIB_restrict stream )
 {
-    size_t spare;
-#ifdef __OS2__
-    ULONG tempWritten;
-    APIRET rc;
-#endif
-#ifdef __MSDOS__
-    size_t tempWritten;
-    int errind;
-#endif
+    _PDCLIB_flockfile( stream );
+    size_t r = _PDCLIB_fwrite_unlocked( ptr, size, nmemb, stream );
+    _PDCLIB_funlockfile( stream );
+    return r;
+}
 
-    spare = (size_t)(stream->endbuf - stream->upto);
-    if (towrite < spare)
-    {
-        memcpy(stream->upto, ptr, towrite);
-        *actualWritten = towrite;
-        stream->upto += towrite;
-        return;
-    }
-    memcpy(stream->upto, ptr, spare);
-#ifdef __OS2__
-    rc = DosWrite(stream->hfile,
-                  stream->fbuf,
-                  stream->szfbuf,
-                  &tempWritten);
-    if (rc != 0)
-    {
-        stream->errorInd = 1;
-        errno = rc;
-        return;
-    }
-#endif
-#ifdef __MSDOS__
-    tempWritten = __write(stream->hfile,
-                          stream->fbuf,
-                          stream->szfbuf,
-                          &errind);
-    if (errind)
-    {
-        stream->errorInd = 1;
-        errno = tempWritten;
-        return;
-    }
 #endif
-    *actualWritten = spare;
-    stream->upto = stream->fbuf;
-    stream->bufStartR += tempWritten;
-    if (towrite > stream->szfbuf)
-    {
-        stream->quickBin = 1;
-#ifdef __OS2__
-        rc = DosWrite(stream->hfile,
-                      (char *)ptr + *actualWritten,
-                      towrite - *actualWritten,
-                      &tempWritten);
-        if (rc != 0)
-        {
-            stream->errorInd = 1;
-            errno = rc;
-            return;
-        }
-#endif
-#ifdef __MSDOS__
-        tempWritten = __write(stream->hfile,
-                              (char *)ptr + *actualWritten,
-                              towrite - *actualWritten,
-                              &errind);
-        if (errind)
-        {
-            stream->errorInd = 1;
-            errno = tempWritten;
-            return;
-        }
-#endif
-        *actualWritten += tempWritten;
-        stream->bufStartR += tempWritten;
-    }
-    else
-    {
-        memcpy(stream->fbuf,
-               (char *)ptr + *actualWritten,
-               towrite - *actualWritten);
-        stream->upto += (towrite - *actualWritten);
-        *actualWritten = towrite;
-    }
-    stream->bufStartR += *actualWritten;
-    return;
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    /* Testing covered by fread(). */
+    return TEST_RESULTS;
 }
+
 #endif
-*/
+