]> pd.if.org Git - pdclib/blobdiff - functions/stdio/fwrite.c
Merged PDPCLIB and Therx code.
[pdclib] / functions / stdio / fwrite.c
index 4eece021380b9a43ed0925fa3a9f2c6784e1cca9..97bbbd50f22ace32cceb9ecad23813fee6dd4f32 100644 (file)
@@ -6,3 +6,477 @@
 // ----------------------------------------------------------------------------
 
 size_t fwrite( const void * restrict ptr, size_t size, size_t nelem, FILE * restrict stream ) { /* TODO */ };
+
+/* 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);
+    }
+}
+
+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;
+}
+
+
+/* can still be called on binary files, if the binary file is
+   line buffered  */
+
+static void fwriteSlowT(const void *ptr,
+                        FILE *stream,
+                        size_t towrite,
+                        size_t *actualWritten)
+{
+    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
+
+    *actualWritten = 0;
+    tptr = (char *)ptr;
+    p = tptr;
+    oldp = p;
+    p = (char *)memchr(oldp, '\n', towrite - (size_t)(oldp - tptr));
+    while (p != NULL)
+    {
+        diffp = (size_t)(p - oldp);
+        fin = 0;
+        while (!fin)
+        {
+            rem = (size_t)(stream->endbuf - stream->upto);
+            if (diffp < rem)
+            {
+                memcpy(stream->upto, oldp, diffp);
+                stream->upto += diffp;
+                *actualWritten += diffp;
+                fin = 1;
+            }
+            else
+            {
+                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
+                {
+                    *actualWritten += rem;
+                    stream->upto = stream->fbuf;
+                    stream->bufStartR += tempWritten;
+                }
+            }
+        }
+        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
+        {
+            memcpy(stream->upto, oldp, rem);
+#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
+            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;
+}
+
+/* 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 spare;
+#ifdef __OS2__
+    ULONG tempWritten;
+    APIRET rc;
+#endif
+#ifdef __MSDOS__
+    size_t tempWritten;
+    int errind;
+#endif
+
+    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;
+}
+#endif
+*/