OLD | NEW |
1 #include "stdio_impl.h" | 1 #include "stdio_impl.h" |
2 #include <errno.h> | 2 #include <errno.h> |
3 #include <string.h> | 3 #include <string.h> |
4 #include <inttypes.h> | 4 #include <inttypes.h> |
5 | 5 |
6 struct cookie { | 6 struct cookie { |
7 » size_t pos, len, size; | 7 size_t pos, len, size; |
8 » unsigned char *buf; | 8 unsigned char* buf; |
9 » int mode; | 9 int mode; |
10 }; | 10 }; |
11 | 11 |
12 static off_t mseek(FILE *f, off_t off, int whence) | 12 static off_t mseek(FILE* f, off_t off, int whence) { |
13 { | 13 ssize_t base; |
14 » ssize_t base; | 14 struct cookie* c = f->cookie; |
15 » struct cookie *c = f->cookie; | 15 if (whence > 2U) { |
16 » if (whence>2U) { | 16 fail: |
17 fail: | 17 errno = EINVAL; |
18 » » errno = EINVAL; | 18 return -1; |
19 » » return -1; | 19 } |
20 » } | 20 base = (size_t[3]){0, c->pos, c->len}[whence]; |
21 » base = (size_t [3]){0, c->pos, c->len}[whence]; | 21 if (off < -base || off > (ssize_t)c->size - base) |
22 » if (off < -base || off > (ssize_t)c->size-base) goto fail; | 22 goto fail; |
23 » return c->pos = base+off; | 23 return c->pos = base + off; |
24 } | 24 } |
25 | 25 |
26 static size_t mread(FILE *f, unsigned char *buf, size_t len) | 26 static size_t mread(FILE* f, unsigned char* buf, size_t len) { |
27 { | 27 struct cookie* c = f->cookie; |
28 » struct cookie *c = f->cookie; | 28 size_t rem = c->len - c->pos; |
29 » size_t rem = c->len - c->pos; | 29 if (c->pos > c->len) |
30 » if (c->pos > c->len) rem = 0; | 30 rem = 0; |
31 » if (len > rem) { | 31 if (len > rem) { |
32 » » len = rem; | 32 len = rem; |
33 » » f->flags |= F_EOF; | 33 f->flags |= F_EOF; |
34 » } | 34 } |
35 » memcpy(buf, c->buf+c->pos, len); | 35 memcpy(buf, c->buf + c->pos, len); |
36 » c->pos += len; | 36 c->pos += len; |
37 » rem -= len; | 37 rem -= len; |
38 » if (rem > f->buf_size) rem = f->buf_size; | 38 if (rem > f->buf_size) |
39 » f->rpos = f->buf; | 39 rem = f->buf_size; |
40 » f->rend = f->buf + rem; | 40 f->rpos = f->buf; |
41 » memcpy(f->rpos, c->buf+c->pos, rem); | 41 f->rend = f->buf + rem; |
42 » c->pos += rem; | 42 memcpy(f->rpos, c->buf + c->pos, rem); |
43 » return len; | 43 c->pos += rem; |
| 44 return len; |
44 } | 45 } |
45 | 46 |
46 static size_t mwrite(FILE *f, const unsigned char *buf, size_t len) | 47 static size_t mwrite(FILE* f, const unsigned char* buf, size_t len) { |
47 { | 48 struct cookie* c = f->cookie; |
48 » struct cookie *c = f->cookie; | 49 size_t rem; |
49 » size_t rem; | 50 size_t len2 = f->wpos - f->wbase; |
50 » size_t len2 = f->wpos - f->wbase; | 51 if (len2) { |
51 » if (len2) { | 52 f->wpos = f->wbase; |
52 » » f->wpos = f->wbase; | 53 if (mwrite(f, f->wpos, len2) < len2) |
53 » » if (mwrite(f, f->wpos, len2) < len2) return 0; | 54 return 0; |
54 » } | 55 } |
55 » if (c->mode == 'a') c->pos = c->len; | 56 if (c->mode == 'a') |
56 » rem = c->size - c->pos; | 57 c->pos = c->len; |
57 » if (len > rem) len = rem; | 58 rem = c->size - c->pos; |
58 » memcpy(c->buf+c->pos, buf, len); | 59 if (len > rem) |
59 » c->pos += len; | 60 len = rem; |
60 » if (c->pos > c->len) { | 61 memcpy(c->buf + c->pos, buf, len); |
61 » » c->len = c->pos; | 62 c->pos += len; |
62 » » if (c->len < c->size) c->buf[c->len] = 0; | 63 if (c->pos > c->len) { |
63 » » else if ((f->flags&F_NORD) && c->size) c->buf[c->size-1] = 0; | 64 c->len = c->pos; |
64 » } | 65 if (c->len < c->size) |
65 » return len; | 66 c->buf[c->len] = 0; |
| 67 else if ((f->flags & F_NORD) && c->size) |
| 68 c->buf[c->size - 1] = 0; |
| 69 } |
| 70 return len; |
66 } | 71 } |
67 | 72 |
68 static int mclose(FILE *m) | 73 static int mclose(FILE* m) { |
69 { | 74 return 0; |
70 » return 0; | |
71 } | 75 } |
72 | 76 |
73 FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode) | 77 FILE* fmemopen(void* restrict buf, size_t size, const char* restrict mode) { |
74 { | 78 FILE* f; |
75 » FILE *f; | 79 struct cookie* c; |
76 » struct cookie *c; | 80 int plus = !!strchr(mode, '+'); |
77 » int plus = !!strchr(mode, '+'); | |
78 » | |
79 » if (!size || !strchr("rwa", *mode)) { | |
80 » » errno = EINVAL; | |
81 » » return 0; | |
82 » } | |
83 | 81 |
84 » if (!buf && size > SIZE_MAX-sizeof(FILE)-BUFSIZ-UNGET) { | 82 if (!size || !strchr("rwa", *mode)) { |
85 » » errno = ENOMEM; | 83 errno = EINVAL; |
86 » » return 0; | 84 return 0; |
87 » } | 85 } |
88 | 86 |
89 » f = calloc(sizeof *f + sizeof *c + UNGET + BUFSIZ + (buf?0:size), 1); | 87 if (!buf && size > SIZE_MAX - sizeof(FILE) - BUFSIZ - UNGET) { |
90 » if (!f) return 0; | 88 errno = ENOMEM; |
91 » f->cookie = c = (void *)(f+1); | 89 return 0; |
92 » f->fd = -1; | 90 } |
93 » f->lbf = EOF; | |
94 » f->buf = (unsigned char *)(c+1) + UNGET; | |
95 » f->buf_size = BUFSIZ; | |
96 » if (!buf) buf = f->buf + BUFSIZ; | |
97 | 91 |
98 » c->buf = buf; | 92 f = calloc(sizeof *f + sizeof *c + UNGET + BUFSIZ + (buf ? 0 : size), 1); |
99 » c->size = size; | 93 if (!f) |
100 » c->mode = *mode; | 94 return 0; |
101 » | 95 f->cookie = c = (void*)(f + 1); |
102 » if (!plus) f->flags = (*mode == 'r') ? F_NOWR : F_NORD; | 96 f->fd = -1; |
103 » if (*mode == 'r') c->len = size; | 97 f->lbf = EOF; |
104 » else if (*mode == 'a') c->len = c->pos = strnlen(buf, size); | 98 f->buf = (unsigned char*)(c + 1) + UNGET; |
| 99 f->buf_size = BUFSIZ; |
| 100 if (!buf) |
| 101 buf = f->buf + BUFSIZ; |
105 | 102 |
106 » f->read = mread; | 103 c->buf = buf; |
107 » f->write = mwrite; | 104 c->size = size; |
108 » f->seek = mseek; | 105 c->mode = *mode; |
109 » f->close = mclose; | |
110 | 106 |
111 » if (!libc.threaded) f->lock = -1; | 107 if (!plus) |
| 108 f->flags = (*mode == 'r') ? F_NOWR : F_NORD; |
| 109 if (*mode == 'r') |
| 110 c->len = size; |
| 111 else if (*mode == 'a') |
| 112 c->len = c->pos = strnlen(buf, size); |
112 | 113 |
113 » return __ofl_add(f); | 114 f->read = mread; |
| 115 f->write = mwrite; |
| 116 f->seek = mseek; |
| 117 f->close = mclose; |
| 118 |
| 119 if (!libc.threaded) |
| 120 f->lock = -1; |
| 121 |
| 122 return __ofl_add(f); |
114 } | 123 } |
OLD | NEW |