]> mj.ucw.cz Git - libucw.git/blob - lib/fastbuf.c
bugfix in image scaling (select the correct strategy)
[libucw.git] / lib / fastbuf.c
1 /*
2  *      UCW Library -- Fast Buffered I/O
3  *
4  *      (c) 1997--2006 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 uns bread_slow(struct fastbuf *f, void *b, uns l, uns check)
88 {
89   uns total = 0;
90   while (l)
91     {
92       uns k = f->bstop - f->bptr;
93
94       if (!k)
95         {
96           f->refill(f);
97           k = f->bstop - f->bptr;
98           if (!k)
99             break;
100         }
101       if (k > l)
102         k = l;
103       memcpy(b, f->bptr, k);
104       f->bptr += k;
105       b = (byte *)b + k;
106       l -= k;
107       total += k;
108     }
109   if (check && total && l)
110     die("breadb: short read");
111   return total;
112 }
113
114 void bwrite_slow(struct fastbuf *f, void *b, uns l)
115 {
116   while (l)
117     {
118       uns k = f->bufend - f->bptr;
119
120       if (!k)
121         {
122           f->spout(f);
123           k = f->bufend - f->bptr;
124         }
125       if (k > l)
126         k = l;
127       memcpy(f->bptr, b, k);
128       f->bptr += k;
129       b = (byte *)b + k;
130       l -= k;
131     }
132 }
133
134 void
135 bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l)
136 {
137   while (l)
138     {
139       byte *fptr, *tptr;
140       uns favail, tavail, n;
141
142       favail = bdirect_read_prepare(f, &fptr);
143       if (!favail)
144         {
145           if (l == ~0U)
146             return;
147           die("bbcopy: source exhausted");
148         }
149       tavail = bdirect_write_prepare(t, &tptr);
150       n = MIN(l, favail);
151       n = MIN(n, tavail);
152       memcpy(tptr, fptr, n);
153       bdirect_read_commit(f, fptr + n);
154       bdirect_write_commit(t, tptr + n);
155       if (l != ~0U)
156         l -= n;
157     }
158 }
159
160 int
161 bconfig(struct fastbuf *f, uns item, int value)
162 {
163   return f->config ? f->config(f, item, value) : -1;
164 }
165
166 void
167 brewind(struct fastbuf *f)
168 {
169   bflush(f);
170   bsetpos(f, 0);
171 }
172
173 int
174 bskip_slow(struct fastbuf *f, uns len)
175 {
176   while (len)
177     {
178       byte *buf;
179       uns l = bdirect_read_prepare(f, &buf);
180       if (!l)
181         return 0;
182       l = MIN(l, len);
183       bdirect_read_commit(f, buf+l);
184       len -= l;
185     }
186   return 1;
187 }
188
189 sh_off_t
190 bfilesize(struct fastbuf *f)
191 {
192   if (!f)
193     return 0;
194   sh_off_t pos = btell(f);
195   bseek(f, 0, SEEK_END);
196   sh_off_t len = btell(f);
197   bsetpos(f, pos);
198   return len;
199 }