]> mj.ucw.cz Git - libucw.git/blob - lib/fastbuf.c
717372fdfcfb42f797b1d2199d96d87f86467216
[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   sh_off_t l;
48
49   switch (whence)
50     {
51     case SEEK_SET:
52       return bsetpos(f, pos);
53     case SEEK_CUR:
54       return bsetpos(f, btell(f) + pos);
55     case SEEK_END:
56       bflush(f);
57       f->seek(f, pos, SEEK_END);
58       break;
59     default:
60       die("bseek: invalid whence=%d", whence);
61     }
62 }
63
64 int bgetc_slow(struct fastbuf *f)
65 {
66   if (f->bptr < f->bstop)
67     return *f->bptr++;
68   if (!f->refill(f))
69     return EOF;
70   return *f->bptr++;
71 }
72
73 int bpeekc_slow(struct fastbuf *f)
74 {
75   if (f->bptr < f->bstop)
76     return *f->bptr;
77   if (!f->refill(f))
78     return EOF;
79   return *f->bptr;
80 }
81
82 void bputc_slow(struct fastbuf *f, byte c)
83 {
84   if (f->bptr >= f->bufend)
85     f->spout(f);
86   *f->bptr++ = c;
87 }
88
89 word bgetw_slow(struct fastbuf *f)
90 {
91   word w = bgetc_slow(f);
92 #ifdef CPU_BIG_ENDIAN
93   return (w << 8) | bgetc_slow(f);
94 #else
95   return w | (bgetc_slow(f) << 8);
96 #endif
97 }
98
99 u32 bgetl_slow(struct fastbuf *f)
100 {
101   u32 l = bgetc_slow(f);
102 #ifdef CPU_BIG_ENDIAN
103   l = (l << 8) | bgetc_slow(f);
104   l = (l << 8) | bgetc_slow(f);
105   return (l << 8) | bgetc_slow(f);
106 #else
107   l = (bgetc_slow(f) << 8) | l;
108   l = (bgetc_slow(f) << 16) | l;
109   return (bgetc_slow(f) << 24) | l;
110 #endif
111 }
112
113 u64 bgetq_slow(struct fastbuf *f)
114 {
115   u32 l, h;
116 #ifdef CPU_BIG_ENDIAN
117   h = bgetl_slow(f);
118   l = bgetl_slow(f);
119 #else
120   l = bgetl_slow(f);
121   h = bgetl_slow(f);
122 #endif
123   return ((u64) h << 32) | l;
124 }
125
126 u64 bget5_slow(struct fastbuf *f)
127 {
128   u32 l, h;
129 #ifdef CPU_BIG_ENDIAN
130   h = bgetc_slow(f);
131   l = bgetl_slow(f);
132 #else
133   l = bgetl_slow(f);
134   h = bgetc_slow(f);
135 #endif
136   return ((u64) h << 32) | l;
137 }
138
139 void bputw_slow(struct fastbuf *f, word w)
140 {
141 #ifdef CPU_BIG_ENDIAN
142   bputc_slow(f, w >> 8);
143   bputc_slow(f, w);
144 #else
145   bputc_slow(f, w);
146   bputc_slow(f, w >> 8);
147 #endif
148 }
149
150 void bputl_slow(struct fastbuf *f, u32 l)
151 {
152 #ifdef CPU_BIG_ENDIAN
153   bputc_slow(f, l >> 24);
154   bputc_slow(f, l >> 16);
155   bputc_slow(f, l >> 8);
156   bputc_slow(f, l);
157 #else
158   bputc_slow(f, l);
159   bputc_slow(f, l >> 8);
160   bputc_slow(f, l >> 16);
161   bputc_slow(f, l >> 24);
162 #endif
163 }
164
165 void bputq_slow(struct fastbuf *f, u64 q)
166 {
167 #ifdef CPU_BIG_ENDIAN
168   bputl_slow(f, q >> 32);
169   bputl_slow(f, q);
170 #else
171   bputl_slow(f, q);
172   bputl_slow(f, q >> 32);
173 #endif
174 }
175
176 void bput5_slow(struct fastbuf *f, u64 o)
177 {
178   u32 hi = o >> 32;
179   u32 low = o;
180 #ifdef CPU_BIG_ENDIAN
181   bputc_slow(f, hi);
182   bputl_slow(f, low);
183 #else
184   bputl_slow(f, low);
185   bputc_slow(f, hi);
186 #endif
187 }
188
189 void bread_slow(struct fastbuf *f, void *b, uns l)
190 {
191   while (l)
192     {
193       uns k = f->bstop - f->bptr;
194
195       if (!k)
196         {
197           f->refill(f);
198           k = f->bstop - f->bptr;
199           if (!k)
200             die("bread on %s: file exhausted", f->name);
201         }
202       if (k > l)
203         k = l;
204       memcpy(b, f->bptr, k);
205       f->bptr += k;
206       b = (byte *)b + k;
207       l -= k;
208     }
209 }
210
211 void bwrite_slow(struct fastbuf *f, void *b, uns l)
212 {
213   while (l)
214     {
215       uns k = f->bufend - f->bptr;
216
217       if (!k)
218         {
219           f->spout(f);
220           k = f->bufend - f->bptr;
221         }
222       if (k > l)
223         k = l;
224       memcpy(f->bptr, b, k);
225       f->bptr += k;
226       b = (byte *)b + k;
227       l -= k;
228     }
229 }
230
231 byte *                                  /* Non-standard */
232 bgets(struct fastbuf *f, byte *b, uns l)
233 {
234   byte *e = b + l - 1;
235   int k;
236
237   k = bgetc(f);
238   if (k == EOF)
239     return NULL;
240   while (b < e)
241     {
242       if (k == '\n' || k == EOF)
243         {
244           *b = 0;
245           return b;
246         }
247       *b++ = k;
248       k = bgetc(f);
249     }
250   die("%s: Line too long", f->name);
251 }