1 /*
2 Copyright (C) 2000 Masanao Izumo <mo@goice.co.jp>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include "config.h"
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "libarc/url.h"
24 #include "libarc/memb.h"
25
26 typedef struct _URL_cache
27 {
28 char common[sizeof(struct _URL)];
29 URL reader;
30 int memb_ok;
31 MemBuffer b;
32 long pos;
33 int autoclose;
34 } URL_cache;
35
36 static long url_cache_read(URL url, void *buff, long n);
37 static int url_cache_fgetc(URL url);
38 static long url_cache_seek(URL url, long offset, int whence);
39 static long url_cache_tell(URL url);
40 static void url_cache_close(URL url);
41
url_cache_open(URL url,int autoclose)42 URL url_cache_open(URL url, int autoclose)
43 {
44 URL_cache *urlp;
45
46 if(url->type == URL_cache_t && autoclose)
47 {
48 if(((URL_cache *)url)->memb_ok)
49 delete_memb(&((URL_cache *)url)->b);
50 urlp = (URL_cache *)url;
51 url = urlp->reader;
52 }
53 else
54 {
55 if((urlp = (URL_cache *)alloc_url(sizeof(URL_cache))) == NULL)
56 {
57 if(autoclose)
58 url_close(url);
59 return NULL;
60 }
61 }
62
63 /* common members */
64 URLm(urlp, type) = URL_cache_t;
65 URLm(urlp, url_read) = url_cache_read;
66 URLm(urlp, url_gets) = NULL;
67 URLm(urlp, url_fgetc) = url_cache_fgetc;
68 URLm(urlp, url_seek) = url_cache_seek;
69 URLm(urlp, url_tell) = url_cache_tell;
70 URLm(urlp, url_close) = url_cache_close;
71
72 /* private members */
73 urlp->reader = url;
74 urlp->memb_ok = 1;
75 init_memb(&urlp->b);
76 urlp->pos = 0;
77 urlp->autoclose = autoclose;
78
79 return (URL)urlp;
80 }
81
url_cache_disable(URL url)82 void url_cache_disable(URL url)
83 {
84 if(url->type == URL_cache_t)
85 url->url_seek = NULL;
86 }
87
url_cache_detach(URL url)88 void url_cache_detach(URL url)
89 {
90 if(url != NULL && url->type == URL_cache_t)
91 {
92 URL_cache *urlp = (URL_cache *)url;
93 if(urlp->autoclose && urlp->reader != NULL)
94 url_close(urlp->reader);
95 urlp->reader = NULL;
96 }
97 }
98
url_cache_read(URL url,void * buff,long n)99 static long url_cache_read(URL url, void *buff, long n)
100 {
101 URL_cache *urlp = (URL_cache *)url;
102 MemBuffer *b = &urlp->b;
103
104 if(!urlp->memb_ok)
105 {
106 if(urlp->reader == NULL)
107 return 0;
108 n = url_read(urlp->reader, buff, n);
109 if(n > 0)
110 urlp->pos += n;
111 return n;
112 }
113
114 if(urlp->pos < b->total_size)
115 {
116 if(n > b->total_size - urlp->pos)
117 n = b->total_size - urlp->pos;
118 urlp->pos += read_memb(b, buff, n);
119 return n;
120 }
121
122 if(url->url_seek == NULL)
123 {
124 delete_memb(b);
125 urlp->memb_ok = 0;
126 if(urlp->reader == NULL)
127 return 0;
128 n = url_read(urlp->reader, buff, n);
129 if(n > 0)
130 urlp->pos += n;
131 return n;
132 }
133
134 if(urlp->reader == NULL)
135 return 0;
136 n = url_read(urlp->reader, buff, n);
137 if(n > 0)
138 {
139 push_memb(b, buff, n);
140 b->cur = b->tail;
141 b->cur->pos = b->cur->size;
142 urlp->pos += n;
143 }
144 return n;
145 }
146
url_cache_fgetc(URL url)147 static int url_cache_fgetc(URL url)
148 {
149 URL_cache *urlp = (URL_cache *)url;
150 MemBuffer *b = &urlp->b;
151 char c;
152 int i;
153
154 if(!urlp->memb_ok)
155 {
156 if(urlp->reader == NULL)
157 return EOF;
158 if((i = url_getc(urlp->reader)) == EOF)
159 return EOF;
160 urlp->pos++;
161 return i;
162 }
163
164 if(urlp->pos < b->total_size)
165 {
166 read_memb(b, &c, 1);
167 urlp->pos++;
168 return (int)(unsigned char)c;
169 }
170
171 if(url->url_seek == NULL)
172 {
173 delete_memb(b);
174 urlp->memb_ok = 0;
175 if(urlp->reader == NULL)
176 return EOF;
177 if((i = url_getc(urlp->reader)) == EOF)
178 return EOF;
179 urlp->pos++;
180 return i;
181 }
182
183 if(urlp->reader == NULL)
184 return EOF;
185 if((i = url_getc(urlp->reader)) == EOF)
186 return EOF;
187 c = (char)i;
188 push_memb(b, &c, 1);
189 b->cur = b->tail;
190 b->cur->pos = b->cur->size;
191 urlp->pos++;
192 return i;
193 }
194
url_cache_seek(URL url,long offset,int whence)195 static long url_cache_seek(URL url, long offset, int whence)
196 {
197 URL_cache *urlp = (URL_cache *)url;
198 MemBuffer *b = &urlp->b;
199 long ret, newpos, n, s;
200
201 ret = urlp->pos;
202 switch(whence)
203 {
204 case SEEK_SET:
205 newpos = offset;
206 break;
207 case SEEK_CUR:
208 newpos = ret + offset;
209 break;
210 case SEEK_END:
211 while(url_cache_fgetc(url) != EOF)
212 ;
213 newpos = b->total_size + whence;
214 break;
215 default:
216 url_errno = errno = EPERM;
217 return -1;
218 }
219 if(newpos < 0)
220 newpos = 0;
221 n = newpos - ret;
222
223 if(n < 0)
224 {
225 rewind_memb(b);
226 n = newpos;
227 urlp->pos = 0;
228 }
229
230 s = skip_read_memb(b, n);
231 urlp->pos += s;
232 while(s++ < n && url_cache_fgetc(url) != EOF)
233 ;
234 return ret;
235 }
236
url_cache_tell(URL url)237 static long url_cache_tell(URL url)
238 {
239 return ((URL_cache *)url)->pos;
240 }
241
url_cache_close(URL url)242 static void url_cache_close(URL url)
243 {
244 URL_cache *urlp = (URL_cache *)url;
245 if(urlp->autoclose && urlp->reader != NULL)
246 url_close(urlp->reader);
247 if(urlp->memb_ok)
248 delete_memb(&urlp->b);
249 free(urlp);
250 }
251