PatchworkOS
Loading...
Searching...
No Matches
fwrite.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "user/common/file.h"
7
8size_t fwrite(const void* _RESTRICT ptr, size_t size, size_t nmemb, FILE* _RESTRICT stream)
9{
10 mtx_lock(&stream->mtx);
11
12 if (_file_prepare_write(stream) == ERR)
13 {
14 mtx_unlock(&stream->mtx);
15 return 0;
16 }
17
18 uint64_t newLineOffset = 0;
19 uint64_t n = 0;
20 for (; n < nmemb; n++)
21 {
22 for (uint64_t i = 0; i < size; i++)
23 {
24 // TODO: For better performance, write block-wise, not byte-wise.
25 uint8_t byte = ((uint8_t*)ptr)[n * size + i];
26 stream->buf[stream->bufIndex++] = byte;
27
28 if (byte == '\n')
29 {
30 // Remember last newline, in case we have to do a partial line-buffered flush
31 newLineOffset = stream->bufIndex;
32 }
33
34 if (stream->bufIndex == stream->bufSize)
35 {
36 if (_file_flush_buffer(stream) == ERR)
37 {
38 mtx_unlock(&stream->mtx);
39 return n;
40 }
41
42 newLineOffset = 0;
43 }
44 }
45 }
46
47 if (stream->flags & _FILE_UNBUFFERED)
48 {
49 if (_file_flush_buffer(stream) == ERR)
50 {
51 /* We are in a pinch here. We have an error, which requires a
52 return value < nmemb. On the other hand, all objects have
53 been written to buffer, which means all the caller had to
54 do was removing the error cause, and re-flush the stream...
55 Catch 22. We'll return a value one short, to indicate the
56 error, and can't really do anything about the inconsistency.
57 */
58 mtx_unlock(&stream->mtx);
59 return n - 1;
60 }
61 }
62 else if (stream->flags & _FILE_LINE_BUFFERED)
63 {
64 if (newLineOffset > 0)
65 {
66 size_t bufIndex = stream->bufIndex;
67 stream->bufIndex = newLineOffset;
68
69 if (_file_flush_buffer(stream) == ERR)
70 {
71 /* See comment above. */
72 stream->bufIndex = bufIndex;
73 mtx_unlock(&stream->mtx);
74 return n - 1;
75 }
76
77 stream->bufIndex = bufIndex - newLineOffset;
78 memmove(stream->buf, stream->buf + newLineOffset, stream->bufIndex);
79 }
80 }
81
82 mtx_unlock(&stream->mtx);
83 return n;
84}
size_t fwrite(const void *_RESTRICT ptr, size_t size, size_t nmemb, FILE *_RESTRICT stream)
Definition fwrite.c:8
#define ERR
Integer error value.
Definition ERR.h:17
#define _RESTRICT
Definition config.h:17
uint64_t _file_prepare_write(FILE *stream)
Definition file.c:239
uint64_t _file_flush_buffer(FILE *stream)
Definition file.c:158
@ _FILE_UNBUFFERED
Definition file.h:18
@ _FILE_LINE_BUFFERED
Definition file.h:17
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC void * memmove(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition file.h:34
_PUBLIC int mtx_lock(mtx_t *mtx)
Definition mtx_lock.c:11
_PUBLIC int mtx_unlock(mtx_t *mtx)
Definition mtx_unlock.c:10