]> pd.if.org Git - pdclib/blob - functions/stdio/fwrite.c
Merged PDPCLIB and Therx code.
[pdclib] / functions / stdio / fwrite.c
1 // ----------------------------------------------------------------------------
2 // $Id$
3 // ----------------------------------------------------------------------------
4 // Public Domain C Library - http://pdclib.sourceforge.net
5 // This code is Public Domain. Use, modify, and redistribute at will.
6 // ----------------------------------------------------------------------------
7
8 size_t fwrite( const void * restrict ptr, size_t size, size_t nelem, FILE * restrict stream ) { /* TODO */ };
9
10 /* PDPC code - unreviewed, verbatim.
11 Read the note in fopen.c.
12 #ifndef __MVS__
13 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
14 {
15     size_t towrite;
16     size_t elemWritten;
17 #ifdef __OS2__
18     ULONG actualWritten;
19     APIRET rc;
20 #endif
21 #ifdef __MSDOS__
22     size_t actualWritten;
23     int errind;
24 #endif
25
26     if (nmemb == 1)
27     {
28         towrite = size;
29     }
30     else if (size == 1)
31     {
32         towrite = nmemb;
33     }
34     else
35     {
36         towrite = size * nmemb;
37     }
38     if (towrite < stream->szfbuf)
39     {
40         stream->quickBin = 0;
41         if ((stream->bufTech == _IONBF) && !stream->textMode)
42         {
43             stream->quickBin = 1;
44         }
45     }
46     if (!stream->quickBin)
47     {
48         fwriteSlow(ptr, size, nmemb, stream, towrite, &elemWritten);
49         return (elemWritten);
50     }
51     else
52     {
53 #ifdef __OS2__
54         rc = DosWrite(stream->hfile, (VOID *)ptr, towrite, &actualWritten);
55         if (rc != 0)
56         {
57             stream->errorInd = 1;
58             actualWritten = 0;
59             errno = rc;
60         }
61 #endif
62 #ifdef __MSDOS__
63         actualWritten = __write(stream->hfile,
64                                 ptr,
65                                 towrite,
66                                 &errind);
67         if (errind)
68         {
69             stream->errorInd = 1;
70             actualWritten = 0;
71             errno = actualWritten;
72         }
73 #endif
74         if (nmemb == 1)
75         {
76             if (actualWritten == size)
77             {
78                 elemWritten = 1;
79             }
80             else
81             {
82                 elemWritten = 0;
83             }
84         }
85         else if (size == 1)
86         {
87             elemWritten = actualWritten;
88         }
89         else
90         {
91             elemWritten = actualWritten / size;
92         }
93         stream->bufStartR += actualWritten;
94         return (elemWritten);
95     }
96 }
97
98 static void fwriteSlow(const void *ptr,
99                        size_t size,
100                        size_t nmemb,
101                        FILE *stream,
102                        size_t towrite,
103                        size_t *elemWritten)
104 {
105     size_t actualWritten;
106
107     /* Normally, on output, there will never be a situation where
108        the write buffer is full, but it hasn't been written out.
109        If we find this to be the case, then it is because we have
110        done an fseek, and didn't know whether we were going to do
111        a read or a write after it, so now that we know, we switch
112        the buffer to being set up for write.  We could use a flag,
113        but I thought it would be better to just put some magic
114        code in with a comment */
115     if (stream->upto == stream->endbuf)
116     {
117         stream->bufStartR += (stream->endbuf - stream->fbuf);
118         stream->upto = stream->fbuf;
119         stream->mode = __WRITE_MODE;
120     }
121     if ((stream->textMode) || (stream->bufTech == _IOLBF))
122     {
123         fwriteSlowT(ptr, stream, towrite, &actualWritten);
124     }
125     else
126     {
127         fwriteSlowB(ptr, stream, towrite, &actualWritten);
128     }
129     if (nmemb == 1)
130     {
131         if (actualWritten == size)
132         {
133             *elemWritten = 1;
134         }
135         else
136         {
137             *elemWritten = 0;
138         }
139     }
140     else if (size == 1)
141     {
142         *elemWritten = actualWritten;
143     }
144     else
145     {
146         *elemWritten = actualWritten / size;
147     }
148     return;
149 }
150
151
152 /* can still be called on binary files, if the binary file is
153    line buffered  */
154
155 static void fwriteSlowT(const void *ptr,
156                         FILE *stream,
157                         size_t towrite,
158                         size_t *actualWritten)
159 {
160     char *p;
161     char *tptr;
162     char *oldp;
163     size_t diffp;
164     size_t rem;
165     int fin;
166 #ifdef __OS2__
167     ULONG tempWritten;
168     APIRET rc;
169 #endif
170 #ifdef __MSDOS__
171     size_t tempWritten;
172     int errind;
173 #endif
174
175     *actualWritten = 0;
176     tptr = (char *)ptr;
177     p = tptr;
178     oldp = p;
179     p = (char *)memchr(oldp, '\n', towrite - (size_t)(oldp - tptr));
180     while (p != NULL)
181     {
182         diffp = (size_t)(p - oldp);
183         fin = 0;
184         while (!fin)
185         {
186             rem = (size_t)(stream->endbuf - stream->upto);
187             if (diffp < rem)
188             {
189                 memcpy(stream->upto, oldp, diffp);
190                 stream->upto += diffp;
191                 *actualWritten += diffp;
192                 fin = 1;
193             }
194             else
195             {
196                 memcpy(stream->upto, oldp, rem);
197                 oldp += rem;
198                 diffp -= rem;
199 #ifdef __OS2__
200                 rc = DosWrite(stream->hfile,
201                               stream->fbuf,
202                               stream->szfbuf,
203                               &tempWritten);
204                 if (rc != 0)
205                 {
206                     stream->errorInd = 1;
207                     return;
208                 }
209 #endif
210 #ifdef __MSDOS__
211                 tempWritten = __write(stream->hfile,
212                                       stream->fbuf,
213                                       stream->szfbuf,
214                                       &errind);
215                 if (errind)
216                 {
217                     stream->errorInd = 1;
218                     return;
219                 }
220 #endif
221                 else
222                 {
223                     *actualWritten += rem;
224                     stream->upto = stream->fbuf;
225                     stream->bufStartR += tempWritten;
226                 }
227             }
228         }
229         rem = (size_t)(stream->endbuf - stream->upto);
230         if (rem < 2)
231         {
232 #ifdef __OS2__
233             rc = DosWrite(stream->hfile,
234                           stream->fbuf,
235                           (size_t)(stream->upto - stream->fbuf),
236                           &tempWritten);
237             if (rc != 0)
238             {
239                 stream->errorInd = 1;
240                 errno = rc;
241                 return;
242             }
243 #endif
244 #ifdef __MSDOS__
245             tempWritten = __write(stream->hfile,
246                                   stream->fbuf,
247                                   (size_t)(stream->upto - stream->fbuf),
248                                   &errind);
249             if (errind)
250             {
251                 stream->errorInd = 1;
252                 errno = tempWritten;
253                 return;
254             }
255 #endif
256             stream->upto = stream->fbuf;
257             stream->bufStartR += tempWritten;
258         }
259         if (stream->textMode)
260         {
261             memcpy(stream->upto, "\r\n", 2);
262             stream->upto += 2;
263         }
264         else
265         {
266             memcpy(stream->upto, "\n", 1);
267             stream->upto += 1;
268         }
269         *actualWritten += 1;
270         oldp = p + 1;
271         p = (char *)memchr(oldp, '\n', towrite - (size_t)(oldp - tptr));
272     }
273
274     if ((stream->bufTech == _IOLBF)
275         && (stream->upto != stream->fbuf)
276         && (oldp != tptr))
277     {
278 #ifdef __OS2__
279         rc = DosWrite(stream->hfile,
280                       stream->fbuf,
281                       (size_t)(stream->upto - stream->fbuf),
282                       &tempWritten);
283         if (rc != 0)
284         {
285             stream->errorInd = 1;
286             errno = rc;
287             return;
288         }
289 #endif
290 #ifdef __MSDOS__
291         tempWritten = __write(stream->hfile,
292                               stream->fbuf,
293                               (size_t)(stream->upto - stream->fbuf),
294                               &errind);
295         if (errind)
296         {
297             stream->errorInd = 1;
298             errno = tempWritten;
299             return;
300         }
301 #endif
302         stream->upto = stream->fbuf;
303         stream->bufStartR += tempWritten;
304     }
305
306     diffp = towrite - *actualWritten;
307     while (diffp != 0)
308     {
309         rem = (size_t)(stream->endbuf - stream->upto);
310         if (diffp < rem)
311         {
312             memcpy(stream->upto, oldp, diffp);
313             stream->upto += diffp;
314             *actualWritten += diffp;
315         }
316         else
317         {
318             memcpy(stream->upto, oldp, rem);
319 #ifdef __OS2__
320             rc = DosWrite(stream->hfile,
321                           stream->fbuf,
322                           stream->szfbuf,
323                           &tempWritten);
324             if (rc != 0)
325             {
326                 stream->errorInd = 1;
327                 errno = rc;
328                 return;
329             }
330 #endif
331 #ifdef __MSDOS__
332             tempWritten = __write(stream->hfile,
333                                   stream->fbuf,
334                                   stream->szfbuf,
335                                   &errind);
336             if (errind)
337             {
338                 stream->errorInd = 1;
339                 errno = tempWritten;
340                 return;
341             }
342 #endif
343             else
344             {
345                 *actualWritten += rem;
346                 stream->upto = stream->fbuf;
347             }
348             stream->bufStartR += tempWritten;
349             oldp += rem;
350         }
351         diffp = towrite - *actualWritten;
352     }
353     if ((stream->bufTech == _IONBF)
354         && (stream->upto != stream->fbuf))
355     {
356 #ifdef __OS2__
357         rc = DosWrite(stream->hfile,
358                       stream->fbuf,
359                       (size_t)(stream->upto - stream->fbuf),
360                       &tempWritten);
361         if (rc != 0)
362         {
363             stream->errorInd = 1;
364             errno = rc;
365             return;
366         }
367 #endif
368 #ifdef __MSDOS__
369         tempWritten = __write(stream->hfile,
370                               stream->fbuf,
371                               (size_t)(stream->upto - stream->fbuf),
372                               &errind);
373         if (errind)
374         {
375             stream->errorInd = 1;
376             errno = tempWritten;
377             return;
378         }
379 #endif
380         stream->upto = stream->fbuf;
381         stream->bufStartR += tempWritten;
382     }
383     return;
384 }
385
386 /* whilst write requests are smaller than a buffer, we do not turn
387    on quickbin */
388
389 static void fwriteSlowB(const void *ptr,
390                         FILE *stream,
391                         size_t towrite,
392                         size_t *actualWritten)
393 {
394     size_t spare;
395 #ifdef __OS2__
396     ULONG tempWritten;
397     APIRET rc;
398 #endif
399 #ifdef __MSDOS__
400     size_t tempWritten;
401     int errind;
402 #endif
403
404     spare = (size_t)(stream->endbuf - stream->upto);
405     if (towrite < spare)
406     {
407         memcpy(stream->upto, ptr, towrite);
408         *actualWritten = towrite;
409         stream->upto += towrite;
410         return;
411     }
412     memcpy(stream->upto, ptr, spare);
413 #ifdef __OS2__
414     rc = DosWrite(stream->hfile,
415                   stream->fbuf,
416                   stream->szfbuf,
417                   &tempWritten);
418     if (rc != 0)
419     {
420         stream->errorInd = 1;
421         errno = rc;
422         return;
423     }
424 #endif
425 #ifdef __MSDOS__
426     tempWritten = __write(stream->hfile,
427                           stream->fbuf,
428                           stream->szfbuf,
429                           &errind);
430     if (errind)
431     {
432         stream->errorInd = 1;
433         errno = tempWritten;
434         return;
435     }
436 #endif
437     *actualWritten = spare;
438     stream->upto = stream->fbuf;
439     stream->bufStartR += tempWritten;
440     if (towrite > stream->szfbuf)
441     {
442         stream->quickBin = 1;
443 #ifdef __OS2__
444         rc = DosWrite(stream->hfile,
445                       (char *)ptr + *actualWritten,
446                       towrite - *actualWritten,
447                       &tempWritten);
448         if (rc != 0)
449         {
450             stream->errorInd = 1;
451             errno = rc;
452             return;
453         }
454 #endif
455 #ifdef __MSDOS__
456         tempWritten = __write(stream->hfile,
457                               (char *)ptr + *actualWritten,
458                               towrite - *actualWritten,
459                               &errind);
460         if (errind)
461         {
462             stream->errorInd = 1;
463             errno = tempWritten;
464             return;
465         }
466 #endif
467         *actualWritten += tempWritten;
468         stream->bufStartR += tempWritten;
469     }
470     else
471     {
472         memcpy(stream->fbuf,
473                (char *)ptr + *actualWritten,
474                towrite - *actualWritten);
475         stream->upto += (towrite - *actualWritten);
476         *actualWritten = towrite;
477     }
478     stream->bufStartR += *actualWritten;
479     return;
480 }
481 #endif
482 */