]> mj.ucw.cz Git - libucw.git/blob - lib/fastbuf.c
9f5d36924da5dbbbb88e1b76227d96c6d0bcb694
[libucw.git] / lib / fastbuf.c
1 /*
2  *      Sherlock Library -- Fast Buffered I/O
3  *
4  *      (c) 1997--2000 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "lib/fastbuf.h"
12
13 #include <stdio.h>
14 #include <stdlib.h>
15
16 void bclose(struct fastbuf *f)
17 {
18   if (f)
19     {
20       bflush(f);
21       f->close(f);
22       xfree(f);
23     }
24 }
25
26 void bflush(struct fastbuf *f)
27 {
28   if (f->bptr != f->buffer)
29     {                                   /* Have something to flush */
30       if (f->bstop > f->buffer)         /* Read data? */
31         {
32           f->bptr = f->bstop = f->buffer;
33           f->pos = f->fdpos;
34         }
35       else                              /* Write data... */
36         f->spout(f);
37     }
38 }
39
40 inline void bsetpos(struct fastbuf *f, sh_off_t pos)
41 {
42   if (pos >= f->pos && (pos <= f->pos + (f->bptr - f->buffer) || pos <= f->pos + (f->bstop - f->buffer)))
43     f->bptr = f->buffer + (pos - f->pos);
44   else
45     {
46       bflush(f);
47       f->seek(f, pos, SEEK_SET);
48     }
49 }
50
51 void bseek(struct fastbuf *f, sh_off_t pos, int whence)
52 {
53   switch (whence)
54     {
55     case SEEK_SET:
56       return bsetpos(f, pos);
57     case SEEK_CUR:
58       return bsetpos(f, btell(f) + pos);
59     case SEEK_END:
60       bflush(f);
61       f->seek(f, pos, SEEK_END);
62       break;
63     default:
64       die("bseek: invalid whence=%d", whence);
65     }
66 }
67
68 int bgetc_slow(struct fastbuf *f)
69 {
70   if (f->bptr < f->bstop)
71     return *f->bptr++;
72   if (!f->refill(f))
73     return EOF;
74   return *f->bptr++;
75 }
76
77 int bpeekc_slow(struct fastbuf *f)
78 {
79   if (f->bptr < f->bstop)
80     return *f->bptr;
81   if (!f->refill(f))
82     return EOF;
83   return *f->bptr;
84 }
85
86 void bputc_slow(struct fastbuf *f, uns c)
87 {
88   if (f->bptr >= f->bufend)
89     f->spout(f);
90   *f->bptr++ = c;
91 }
92
93 int bgetw_slow(struct fastbuf *f)
94 {
95   int w1, w2;
96   w1 = bgetc_slow(f);
97   if (w1 < 0)
98     return w1;
99   w2 = bgetc_slow(f);
100   if (w2 < 0)
101     return w2;
102 #ifdef CPU_BIG_ENDIAN
103   return (w1 << 8) | w2;
104 #else
105   return w1 | (w2 << 8);
106 #endif
107 }
108
109 u32 bgetl_slow(struct fastbuf *f)
110 {
111   u32 l = bgetc_slow(f);
112 #ifdef CPU_BIG_ENDIAN
113   l = (l << 8) | bgetc_slow(f);
114   l = (l << 8) | bgetc_slow(f);
115   return (l << 8) | bgetc_slow(f);
116 #else
117   l = (bgetc_slow(f) << 8) | l;
118   l = (bgetc_slow(f) << 16) | l;
119   return (bgetc_slow(f) << 24) | l;
120 #endif
121 }
122
123 u64 bgetq_slow(struct fastbuf *f)
124 {
125   u32 l, h;
126 #ifdef CPU_BIG_ENDIAN
127   h = bgetl_slow(f);
128   l = bgetl_slow(f);
129 #else
130   l = bgetl_slow(f);
131   h = bgetl_slow(f);
132 #endif
133   return ((u64) h << 32) | l;
134 }
135
136 u64 bget5_slow(struct fastbuf *f)
137 {
138   u32 l, h;
139 #ifdef CPU_BIG_ENDIAN
140   h = bgetc_slow(f);
141   l = bgetl_slow(f);
142 #else
143   l = bgetl_slow(f);
144   h = bgetc_slow(f);
145 #endif
146   return ((u64) h << 32) | l;
147 }
148
149 void bputw_slow(struct fastbuf *f, uns w)
150 {
151 #ifdef CPU_BIG_ENDIAN
152   bputc_slow(f, w >> 8);
153   bputc_slow(f, w);
154 #else
155   bputc_slow(f, w);
156   bputc_slow(f, w >> 8);
157 #endif
158 }
159
160 void bputl_slow(struct fastbuf *f, u32 l)
161 {
162 #ifdef CPU_BIG_ENDIAN
163   bputc_slow(f, l >> 24);
164   bputc_slow(f, l >> 16);
165   bputc_slow(f, l >> 8);
166   bputc_slow(f, l);
167 #else
168   bputc_slow(f, l);
169   bputc_slow(f, l >> 8);
170   bputc_slow(f, l >> 16);
171   bputc_slow(f, l >> 24);
172 #endif
173 }
174
175 void bputq_slow(struct fastbuf *f, u64 q)
176 {
177 #ifdef CPU_BIG_ENDIAN
178   bputl_slow(f, q >> 32);
179   bputl_slow(f, q);
180 #else
181   bputl_slow(f, q);
182   bputl_slow(f, q >> 32);
183 #endif
184 }
185
186 void bput5_slow(struct fastbuf *f, u64 o)
187 {
188   u32 hi = o >> 32;
189   u32 low = o;
190 #ifdef CPU_BIG_ENDIAN
191   bputc_slow(f, hi);
192   bputl_slow(f, low);
193 #else
194   bputl_slow(f, low);
195   bputc_slow(f, hi);
196 #endif
197 }
198
199 uns bread_slow(struct fastbuf *f, void *b, uns l, uns check)
200 {
201   uns total = 0;
202   while (l)
203     {
204       uns k = f->bstop - f->bptr;
205
206       if (!k)
207         {
208           f->refill(f);
209           k = f->bstop - f->bptr;
210           if (!k)
211             break;
212         }
213       if (k > l)
214         k = l;
215       memcpy(b, f->bptr, k);
216       f->bptr += k;
217       b = (byte *)b + k;
218       l -= k;
219       total += k;
220     }
221   if (check && total && l)
222     die("breadb: short read");
223   return total;
224 }
225
226 void bwrite_slow(struct fastbuf *f, void *b, uns l)
227 {
228   while (l)
229     {
230       uns k = f->bufend - f->bptr;
231
232       if (!k)
233         {
234           f->spout(f);
235           k = f->bufend - f->bptr;
236         }
237       if (k > l)
238         k = l;
239       memcpy(f->bptr, b, k);
240       f->bptr += k;
241       b = (byte *)b + k;
242       l -= k;
243     }
244 }
245
246 byte *                                  /* Non-standard */
247 bgets(struct fastbuf *f, byte *b, uns l)
248 {
249   byte *e = b + l - 1;
250   int k;
251
252   k = bgetc(f);
253   if (k == EOF)
254     return NULL;
255   while (b < e)
256     {
257       if (k == '\n' || k == EOF)
258         {
259           *b = 0;
260           return b;
261         }
262       *b++ = k;
263       k = bgetc(f);
264     }
265   die("%s: Line too long", f->name);
266 }
267
268 byte *
269 bgets0(struct fastbuf *f, byte *b, uns l)
270 {
271   byte *e = b + l - 1;
272   int k;
273
274   k = bgetc(f);
275   if (k == EOF)
276     return NULL;
277   while (b < e)
278     {
279       if (!k || k == EOF)
280         {
281           *b = 0;
282           return b;
283         }
284       *b++ = k;
285       k = bgetc(f);
286     }
287   die("%s: Line too long", f->name);
288 }
289
290 int
291 bdirect_read(struct fastbuf *f, byte **buf)
292 {
293   int len;
294
295   if (f->bptr == f->bstop && !f->refill(f))
296     return EOF;
297   *buf = f->bptr;
298   len = f->bstop - f->bptr;
299   f->bptr += len;
300   return len;
301 }
302
303 int
304 bdirect_write_prepare(struct fastbuf *f, byte **buf)
305 {
306   if (f->bptr == f->bufend)
307     f->spout(f);
308   *buf = f->bptr;
309   return f->bufend - f->bptr;
310 }
311
312 void
313 bdirect_write_commit(struct fastbuf *f, byte *pos)
314 {
315   f->bptr = pos;
316 }