]> mj.ucw.cz Git - libucw.git/blob - lib/fastbuf.c
Moved endianity settings etc. to the per-CPU section.
[libucw.git] / lib / fastbuf.c
1 /*
2  *      UCW Library -- Fast Buffered I/O
3  *
4  *      (c) 1997--2004 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 <stdlib.h>
14
15 void bclose(struct fastbuf *f)
16 {
17   if (f)
18     {
19       bflush(f);
20       if (f->close)
21         f->close(f);
22     }
23 }
24
25 void bflush(struct fastbuf *f)
26 {
27   if (f->bptr > f->bstop)
28     f->spout(f);
29   else if (f->bstop > f->buffer)
30     f->bptr = f->bstop = f->buffer;
31 }
32
33 inline void bsetpos(struct fastbuf *f, sh_off_t pos)
34 {
35   /* We can optimize seeks only when reading */
36   if (pos >= f->pos - (f->bstop - f->buffer) && pos <= f->pos)
37     f->bptr = f->bstop + (pos - f->pos);
38   else
39     {
40       bflush(f);
41       f->seek(f, pos, SEEK_SET);
42     }
43 }
44
45 void bseek(struct fastbuf *f, sh_off_t pos, int whence)
46 {
47   switch (whence)
48     {
49     case SEEK_SET:
50       return bsetpos(f, pos);
51     case SEEK_CUR:
52       return bsetpos(f, btell(f) + pos);
53     case SEEK_END:
54       bflush(f);
55       f->seek(f, pos, SEEK_END);
56       break;
57     default:
58       die("bseek: invalid whence=%d", whence);
59     }
60 }
61
62 int bgetc_slow(struct fastbuf *f)
63 {
64   if (f->bptr < f->bstop)
65     return *f->bptr++;
66   if (!f->refill(f))
67     return EOF;
68   return *f->bptr++;
69 }
70
71 int bpeekc_slow(struct fastbuf *f)
72 {
73   if (f->bptr < f->bstop)
74     return *f->bptr;
75   if (!f->refill(f))
76     return EOF;
77   return *f->bptr;
78 }
79
80 void bputc_slow(struct fastbuf *f, uns c)
81 {
82   if (f->bptr >= f->bufend)
83     f->spout(f);
84   *f->bptr++ = c;
85 }
86
87 int bgetw_slow(struct fastbuf *f)
88 {
89   int w1, w2;
90   w1 = bgetc_slow(f);
91   if (w1 < 0)
92     return w1;
93   w2 = bgetc_slow(f);
94   if (w2 < 0)
95     return w2;
96 #ifdef CPU_BIG_ENDIAN
97   return (w1 << 8) | w2;
98 #else
99   return w1 | (w2 << 8);
100 #endif
101 }
102
103 u32 bgetl_slow(struct fastbuf *f)
104 {
105   u32 l = bgetc_slow(f);
106 #ifdef CPU_BIG_ENDIAN
107   l = (l << 8) | bgetc_slow(f);
108   l = (l << 8) | bgetc_slow(f);
109   return (l << 8) | bgetc_slow(f);
110 #else
111   l = (bgetc_slow(f) << 8) | l;
112   l = (bgetc_slow(f) << 16) | l;
113   return (bgetc_slow(f) << 24) | l;
114 #endif
115 }
116
117 u64 bgetq_slow(struct fastbuf *f)
118 {
119   u32 l, h;
120 #ifdef CPU_BIG_ENDIAN
121   h = bgetl_slow(f);
122   l = bgetl_slow(f);
123 #else
124   l = bgetl_slow(f);
125   h = bgetl_slow(f);
126 #endif
127   return ((u64) h << 32) | l;
128 }
129
130 u64 bget5_slow(struct fastbuf *f)
131 {
132   u32 l, h;
133 #ifdef CPU_BIG_ENDIAN
134   h = bgetc_slow(f);
135   l = bgetl_slow(f);
136 #else
137   l = bgetl_slow(f);
138   h = bgetc_slow(f);
139 #endif
140   return ((u64) h << 32) | l;
141 }
142
143 void bputw_slow(struct fastbuf *f, uns w)
144 {
145 #ifdef CPU_BIG_ENDIAN
146   bputc_slow(f, w >> 8);
147   bputc_slow(f, w);
148 #else
149   bputc_slow(f, w);
150   bputc_slow(f, w >> 8);
151 #endif
152 }
153
154 void bputl_slow(struct fastbuf *f, u32 l)
155 {
156 #ifdef CPU_BIG_ENDIAN
157   bputc_slow(f, l >> 24);
158   bputc_slow(f, l >> 16);
159   bputc_slow(f, l >> 8);
160   bputc_slow(f, l);
161 #else
162   bputc_slow(f, l);
163   bputc_slow(f, l >> 8);
164   bputc_slow(f, l >> 16);
165   bputc_slow(f, l >> 24);
166 #endif
167 }
168
169 void bputq_slow(struct fastbuf *f, u64 q)
170 {
171 #ifdef CPU_BIG_ENDIAN
172   bputl_slow(f, q >> 32);
173   bputl_slow(f, q);
174 #else
175   bputl_slow(f, q);
176   bputl_slow(f, q >> 32);
177 #endif
178 }
179
180 void bput5_slow(struct fastbuf *f, u64 o)
181 {
182   u32 hi = o >> 32;
183   u32 low = o;
184 #ifdef CPU_BIG_ENDIAN
185   bputc_slow(f, hi);
186   bputl_slow(f, low);
187 #else
188   bputl_slow(f, low);
189   bputc_slow(f, hi);
190 #endif
191 }
192
193 uns bread_slow(struct fastbuf *f, void *b, uns l, uns check)
194 {
195   uns total = 0;
196   while (l)
197     {
198       uns k = f->bstop - f->bptr;
199
200       if (!k)
201         {
202           f->refill(f);
203           k = f->bstop - f->bptr;
204           if (!k)
205             break;
206         }
207       if (k > l)
208         k = l;
209       memcpy(b, f->bptr, k);
210       f->bptr += k;
211       b = (byte *)b + k;
212       l -= k;
213       total += k;
214     }
215   if (check && total && l)
216     die("breadb: short read");
217   return total;
218 }
219
220 void bwrite_slow(struct fastbuf *f, void *b, uns l)
221 {
222   while (l)
223     {
224       uns k = f->bufend - f->bptr;
225
226       if (!k)
227         {
228           f->spout(f);
229           k = f->bufend - f->bptr;
230         }
231       if (k > l)
232         k = l;
233       memcpy(f->bptr, b, k);
234       f->bptr += k;
235       b = (byte *)b + k;
236       l -= k;
237     }
238 }
239
240 byte *                                  /* Non-standard */
241 bgets(struct fastbuf *f, byte *b, uns l)
242 {
243   byte *e = b + l - 1;
244   int k;
245
246   k = bgetc(f);
247   if (k < 0)
248     return NULL;
249   while (b < e)
250     {
251       if (k == '\n' || k < 0)
252         {
253           *b = 0;
254           return b;
255         }
256       *b++ = k;
257       k = bgetc(f);
258     }
259   die("%s: Line too long", f->name);
260 }
261
262 int
263 bgets_nodie(struct fastbuf *f, byte *b, uns l)
264 {
265   byte *start = b;
266   byte *e = b + l - 1;
267   int k;
268
269   k = bgetc(f);
270   if (k < 0)
271     return 0;
272   while (b < e)
273     {
274       if (k == '\n' || k < 0)
275         {
276           *b++ = 0;
277           return b - start;
278         }
279       *b++ = k;
280       k = bgetc(f);
281     }
282   return -1;
283 }
284
285 byte *
286 bgets0(struct fastbuf *f, byte *b, uns l)
287 {
288   byte *e = b + l - 1;
289   int k;
290
291   k = bgetc(f);
292   if (k < 0)
293     return NULL;
294   while (b < e)
295     {
296       if (k <= 0)
297         {
298           *b = 0;
299           return b;
300         }
301       *b++ = k;
302       k = bgetc(f);
303     }
304   die("%s: Line too long", f->name);
305 }
306
307 void
308 bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l)
309 {
310   while (l)
311     {
312       byte *fptr, *tptr;
313       uns favail, tavail, n;
314
315       favail = bdirect_read_prepare(f, &fptr);
316       if (!favail)
317         {
318           if (l == ~0U)
319             return;
320           die("bbcopy: source exhausted");
321         }
322       tavail = bdirect_write_prepare(t, &tptr);
323       n = MIN(l, favail);
324       n = MIN(n, tavail);
325       memcpy(tptr, fptr, n);
326       bdirect_read_commit(f, fptr + n);
327       bdirect_write_commit(t, tptr + n);
328       if (l != ~0U)
329         l -= n;
330     }
331 }
332
333 int
334 bconfig(struct fastbuf *f, uns item, int value)
335 {
336   return f->config ? f->config(f, item, value) : -1;
337 }
338
339 void
340 brewind(struct fastbuf *f)
341 {
342   bflush(f);
343   bsetpos(f, 0);
344 }
345
346 int
347 bskip_slow(struct fastbuf *f, uns len)
348 {
349   while (len)
350     {
351       byte *buf;
352       uns l = bdirect_read_prepare(f, &buf);
353       if (!l)
354         return 0;
355       l = MIN(l, len);
356       bdirect_read_commit(f, buf+l);
357       len -= l;
358     }
359   return 1;
360 }
361
362 sh_off_t
363 bfilesize(struct fastbuf *f)
364 {
365   if (!f)
366     return 0;
367   sh_off_t pos = btell(f);
368   bseek(f, 0, SEEK_END);
369   sh_off_t len = btell(f);
370   bsetpos(f, pos);
371   return len;
372 }