]> mj.ucw.cz Git - libucw.git/blob - lib/fastbuf.c
1a5544fb59b4ed918bd3ce72d1ada4827e83f49a
[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 <stdio.h>
8 #include <stdlib.h>
9
10 #include "lib.h"
11 #include "fastbuf.h"
12
13 void bclose(struct fastbuf *f)
14 {
15   bflush(f);
16   f->close(f);
17   free(f);
18 }
19
20 void bflush(struct fastbuf *f)
21 {
22   if (f->bptr != f->buffer)
23     {                                   /* Have something to flush */
24       if (f->bstop > f->buffer)         /* Read data? */
25         {
26           f->bptr = f->bstop = f->buffer;
27           f->pos = f->fdpos;
28         }
29       else                              /* Write data... */
30         f->spout(f);
31     }
32 }
33
34 inline void bsetpos(struct fastbuf *f, sh_off_t pos)
35 {
36   if (pos >= f->pos && (pos <= f->pos + (f->bptr - f->buffer) || pos <= f->pos + (f->bstop - f->buffer)))
37     f->bptr = f->buffer + (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, byte c)
81 {
82   if (f->bptr >= f->bufend)
83     f->spout(f);
84   *f->bptr++ = c;
85 }
86
87 word bgetw_slow(struct fastbuf *f)
88 {
89   word w = bgetc_slow(f);
90 #ifdef CPU_BIG_ENDIAN
91   return (w << 8) | bgetc_slow(f);
92 #else
93   return w | (bgetc_slow(f) << 8);
94 #endif
95 }
96
97 u32 bgetl_slow(struct fastbuf *f)
98 {
99   u32 l = bgetc_slow(f);
100 #ifdef CPU_BIG_ENDIAN
101   l = (l << 8) | bgetc_slow(f);
102   l = (l << 8) | bgetc_slow(f);
103   return (l << 8) | bgetc_slow(f);
104 #else
105   l = (bgetc_slow(f) << 8) | l;
106   l = (bgetc_slow(f) << 16) | l;
107   return (bgetc_slow(f) << 24) | l;
108 #endif
109 }
110
111 u64 bgetq_slow(struct fastbuf *f)
112 {
113   u32 l, h;
114 #ifdef CPU_BIG_ENDIAN
115   h = bgetl_slow(f);
116   l = bgetl_slow(f);
117 #else
118   l = bgetl_slow(f);
119   h = bgetl_slow(f);
120 #endif
121   return ((u64) h << 32) | l;
122 }
123
124 u64 bget5_slow(struct fastbuf *f)
125 {
126   u32 l, h;
127 #ifdef CPU_BIG_ENDIAN
128   h = bgetc_slow(f);
129   l = bgetl_slow(f);
130 #else
131   l = bgetl_slow(f);
132   h = bgetc_slow(f);
133 #endif
134   return ((u64) h << 32) | l;
135 }
136
137 void bputw_slow(struct fastbuf *f, word w)
138 {
139 #ifdef CPU_BIG_ENDIAN
140   bputc_slow(f, w >> 8);
141   bputc_slow(f, w);
142 #else
143   bputc_slow(f, w);
144   bputc_slow(f, w >> 8);
145 #endif
146 }
147
148 void bputl_slow(struct fastbuf *f, u32 l)
149 {
150 #ifdef CPU_BIG_ENDIAN
151   bputc_slow(f, l >> 24);
152   bputc_slow(f, l >> 16);
153   bputc_slow(f, l >> 8);
154   bputc_slow(f, l);
155 #else
156   bputc_slow(f, l);
157   bputc_slow(f, l >> 8);
158   bputc_slow(f, l >> 16);
159   bputc_slow(f, l >> 24);
160 #endif
161 }
162
163 void bputq_slow(struct fastbuf *f, u64 q)
164 {
165 #ifdef CPU_BIG_ENDIAN
166   bputl_slow(f, q >> 32);
167   bputl_slow(f, q);
168 #else
169   bputl_slow(f, q);
170   bputl_slow(f, q >> 32);
171 #endif
172 }
173
174 void bput5_slow(struct fastbuf *f, u64 o)
175 {
176   u32 hi = o >> 32;
177   u32 low = o;
178 #ifdef CPU_BIG_ENDIAN
179   bputc_slow(f, hi);
180   bputl_slow(f, low);
181 #else
182   bputl_slow(f, low);
183   bputc_slow(f, hi);
184 #endif
185 }
186
187 void bread_slow(struct fastbuf *f, void *b, uns l)
188 {
189   while (l)
190     {
191       uns k = f->bstop - f->bptr;
192
193       if (!k)
194         {
195           f->refill(f);
196           k = f->bstop - f->bptr;
197           if (!k)
198             die("bread on %s: file exhausted", f->name);
199         }
200       if (k > l)
201         k = l;
202       memcpy(b, f->bptr, k);
203       f->bptr += k;
204       b = (byte *)b + k;
205       l -= k;
206     }
207 }
208
209 void bwrite_slow(struct fastbuf *f, void *b, uns l)
210 {
211   while (l)
212     {
213       uns k = f->bufend - f->bptr;
214
215       if (!k)
216         {
217           f->spout(f);
218           k = f->bufend - f->bptr;
219         }
220       if (k > l)
221         k = l;
222       memcpy(f->bptr, b, k);
223       f->bptr += k;
224       b = (byte *)b + k;
225       l -= k;
226     }
227 }
228
229 byte *                                  /* Non-standard */
230 bgets(struct fastbuf *f, byte *b, uns l)
231 {
232   byte *e = b + l - 1;
233   int k;
234
235   k = bgetc(f);
236   if (k == EOF)
237     return NULL;
238   while (b < e)
239     {
240       if (k == '\n' || k == EOF)
241         {
242           *b = 0;
243           return b;
244         }
245       *b++ = k;
246       k = bgetc(f);
247     }
248   die("%s: Line too long", f->name);
249 }