This source file includes following definitions.
- mbfile_multi_getc
- mbfile_multi_ungetc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 #ifndef _MBFILE_H
48 #define _MBFILE_H 1
49
50 #include <assert.h>
51 #include <stdbool.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <wchar.h>
55
56 #include "mbchar.h"
57
58 #ifndef _GL_INLINE_HEADER_BEGIN
59 #error "Please include config.h first."
60 #endif
61 _GL_INLINE_HEADER_BEGIN
62 #ifndef MBFILE_INLINE
63 # define MBFILE_INLINE _GL_INLINE
64 #endif
65
66 struct mbfile_multi {
67 FILE *fp;
68 bool eof_seen;
69 bool have_pushback;
70 mbstate_t state;
71 unsigned int bufcount;
72 char buf[MBCHAR_BUF_SIZE];
73 struct mbchar pushback;
74 };
75
76 MBFILE_INLINE void
77 mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi *mbf)
78 {
79 size_t bytes;
80
81
82
83 if (mbf->eof_seen)
84 goto eof;
85
86
87 if (mbf->have_pushback)
88 {
89 mb_copy (mbc, &mbf->pushback);
90 mbf->have_pushback = false;
91 return;
92 }
93
94
95 if (mbf->bufcount == 0)
96 {
97 int c = getc (mbf->fp);
98 if (c == EOF)
99 {
100 mbf->eof_seen = true;
101 goto eof;
102 }
103 mbf->buf[0] = (unsigned char) c;
104 mbf->bufcount++;
105 }
106
107
108 if (mbf->bufcount == 1 && mbsinit (&mbf->state) && is_basic (mbf->buf[0]))
109 {
110
111
112
113 mbc->wc = mbc->buf[0] = mbf->buf[0];
114 mbc->wc_valid = true;
115 mbc->ptr = &mbc->buf[0];
116 mbc->bytes = 1;
117 mbf->bufcount = 0;
118 return;
119 }
120
121
122
123
124 for (;;)
125 {
126
127
128
129
130
131
132
133
134
135
136 mbstate_t backup_state = mbf->state;
137
138 bytes = mbrtowc (&mbc->wc, &mbf->buf[0], mbf->bufcount, &mbf->state);
139
140 if (bytes == (size_t) -1)
141 {
142
143
144 bytes = 1;
145 mbc->wc_valid = false;
146 break;
147 }
148 else if (bytes == (size_t) -2)
149 {
150
151 mbf->state = backup_state;
152 if (mbf->bufcount == MBCHAR_BUF_SIZE)
153 {
154
155
156 bytes = 1;
157 mbc->wc_valid = false;
158 break;
159 }
160 else
161 {
162
163 int c = getc (mbf->fp);
164 if (c == EOF)
165 {
166
167 mbf->eof_seen = true;
168 bytes = mbf->bufcount;
169 mbc->wc_valid = false;
170 break;
171 }
172 mbf->buf[mbf->bufcount] = (unsigned char) c;
173 mbf->bufcount++;
174 }
175 }
176 else
177 {
178 if (bytes == 0)
179 {
180
181 bytes = 1;
182 assert (mbf->buf[0] == '\0');
183 assert (mbc->wc == 0);
184 }
185 mbc->wc_valid = true;
186 break;
187 }
188 }
189
190
191 mbc->ptr = &mbc->buf[0];
192 memcpy (&mbc->buf[0], &mbf->buf[0], bytes);
193 mbc->bytes = bytes;
194
195 mbf->bufcount -= bytes;
196 if (mbf->bufcount > 0)
197 {
198
199 unsigned int count = mbf->bufcount;
200 char *p = &mbf->buf[0];
201
202 do
203 {
204 *p = *(p + bytes);
205 p++;
206 }
207 while (--count > 0);
208 }
209 return;
210
211 eof:
212
213 mbc->ptr = NULL;
214 mbc->bytes = 0;
215 mbc->wc_valid = false;
216 return;
217 }
218
219 MBFILE_INLINE void
220 mbfile_multi_ungetc (const struct mbchar *mbc, struct mbfile_multi *mbf)
221 {
222 mb_copy (&mbf->pushback, mbc);
223 mbf->have_pushback = true;
224 }
225
226 typedef struct mbfile_multi mb_file_t;
227
228 typedef mbchar_t mbf_char_t;
229
230 #define mbf_init(mbf, stream) \
231 ((mbf).fp = (stream), \
232 (mbf).eof_seen = false, \
233 (mbf).have_pushback = false, \
234 memset (&(mbf).state, '\0', sizeof (mbstate_t)), \
235 (mbf).bufcount = 0)
236
237 #define mbf_getc(mbc, mbf) mbfile_multi_getc (&(mbc), &(mbf))
238
239 #define mbf_ungetc(mbc, mbf) mbfile_multi_ungetc (&(mbc), &(mbf))
240
241 #define mb_iseof(mbc) ((mbc).bytes == 0)
242
243 _GL_INLINE_HEADER_END
244
245 #endif