@@ -61,8 +61,11 @@ struct git_istream {
6161 } incore ;
6262
6363 struct {
64- int fd ; /* open for reading */
65- /* NEEDSWORK: what else? */
64+ void * mapped ;
65+ unsigned long mapsize ;
66+ char hdr [32 ];
67+ int hdr_avail ;
68+ int hdr_used ;
6669 } loose ;
6770
6871 struct {
@@ -150,9 +153,85 @@ static void close_deflated_stream(struct git_istream *st)
150153 *
151154 *****************************************************************/
152155
156+ static read_method_decl (loose )
157+ {
158+ size_t total_read = 0 ;
159+
160+ switch (st -> z_state ) {
161+ case z_done :
162+ return 0 ;
163+ case z_error :
164+ return -1 ;
165+ default :
166+ break ;
167+ }
168+
169+ if (st -> u .loose .hdr_used < st -> u .loose .hdr_avail ) {
170+ size_t to_copy = st -> u .loose .hdr_avail - st -> u .loose .hdr_used ;
171+ if (sz < to_copy )
172+ to_copy = sz ;
173+ memcpy (buf , st -> u .loose .hdr + st -> u .loose .hdr_used , to_copy );
174+ st -> u .loose .hdr_used += to_copy ;
175+ total_read += to_copy ;
176+ }
177+
178+ while (total_read < sz ) {
179+ int status ;
180+
181+ st -> z .next_out = (unsigned char * )buf + total_read ;
182+ st -> z .avail_out = sz - total_read ;
183+ status = git_inflate (& st -> z , Z_FINISH );
184+
185+ total_read = st -> z .next_out - (unsigned char * )buf ;
186+
187+ if (status == Z_STREAM_END ) {
188+ git_inflate_end (& st -> z );
189+ st -> z_state = z_done ;
190+ break ;
191+ }
192+ if (status != Z_OK && status != Z_BUF_ERROR ) {
193+ git_inflate_end (& st -> z );
194+ st -> z_state = z_error ;
195+ return -1 ;
196+ }
197+ }
198+ return total_read ;
199+ }
200+
201+ static close_method_decl (loose )
202+ {
203+ close_deflated_stream (st );
204+ munmap (st -> u .loose .mapped , st -> u .loose .mapsize );
205+ return 0 ;
206+ }
207+
208+ static struct stream_vtbl loose_vtbl = {
209+ close_istream_loose ,
210+ read_istream_loose ,
211+ };
212+
153213static open_method_decl (loose )
154214{
155- return -1 ; /* for now */
215+ st -> u .loose .mapped = map_sha1_file (sha1 , & st -> u .loose .mapsize );
216+ if (!st -> u .loose .mapped )
217+ return -1 ;
218+ if (unpack_sha1_header (& st -> z ,
219+ st -> u .loose .mapped ,
220+ st -> u .loose .mapsize ,
221+ st -> u .loose .hdr ,
222+ sizeof (st -> u .loose .hdr )) < 0 ) {
223+ git_inflate_end (& st -> z );
224+ munmap (st -> u .loose .mapped , st -> u .loose .mapsize );
225+ return -1 ;
226+ }
227+
228+ parse_sha1_header (st -> u .loose .hdr , & st -> size );
229+ st -> u .loose .hdr_used = strlen (st -> u .loose .hdr ) + 1 ;
230+ st -> u .loose .hdr_avail = st -> z .total_out ;
231+ st -> z_state = z_used ;
232+
233+ st -> vtbl = & loose_vtbl ;
234+ return 0 ;
156235}
157236
158237
0 commit comments