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