]> mj.ucw.cz Git - libucw.git/blob - lib/fastbuf.c
The is_temp_file variable was originally a good idea, but it made
[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 <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 == EOF)
248     return NULL;
249   while (b < e)
250     {
251       if (k == '\n' || k == EOF)
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 byte *
263 bgets0(struct fastbuf *f, byte *b, uns l)
264 {
265   byte *e = b + l - 1;
266   int k;
267
268   k = bgetc(f);
269   if (k == EOF)
270     return NULL;
271   while (b < e)
272     {
273       if (!k || k == EOF)
274         {
275           *b = 0;
276           return b;
277         }
278       *b++ = k;
279       k = bgetc(f);
280     }
281   die("%s: Line too long", f->name);
282 }
283
284 void
285 bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l)
286 {
287   while (l)
288     {
289       byte *fptr, *tptr;
290       uns favail, tavail, n;
291
292       favail = bdirect_read_prepare(f, &fptr);
293       if (favail == (uns)EOF)
294         die("bbcopy: source exhausted");
295       tavail = bdirect_write_prepare(t, &tptr);
296       n = MIN(l, favail);
297       n = MIN(n, tavail);
298       memcpy(tptr, fptr, n);
299       bdirect_read_commit(f, fptr + n);
300       bdirect_write_commit(t, tptr + n);
301       l -= n;
302     }
303 }
304
305 int
306 bconfig(struct fastbuf *f, uns item, int value)
307 {
308   return f->config ? f->config(f, item, value) : -1;
309 }