Add seek capability to unzStream

This commit is contained in:
OV2 2016-12-03 17:09:52 +01:00
parent 2b68d129a7
commit 6d148ebb4a
2 changed files with 66 additions and 34 deletions

View File

@ -315,8 +315,12 @@ void fStream::closeStream()
unzStream::unzStream (unzFile &v) unzStream::unzStream (unzFile &v)
{ {
file = v; file = v;
head = NULL; pos_in_buf = 0;
numbytes = 0; buf_pos_in_unzipped = unztell(file);
bytes_in_buf = 0;
// remember start pos for seeks
unzGetFilePos(file, &unz_file_start_pos);
} }
unzStream::~unzStream (void) unzStream::~unzStream (void)
@ -324,21 +328,31 @@ unzStream::~unzStream (void)
return; return;
} }
size_t unzStream::buffer_remaining()
{
return bytes_in_buf - pos_in_buf;
}
void unzStream::fill_buffer()
{
buf_pos_in_unzipped = unztell(file);
bytes_in_buf = unzReadCurrentFile(file, buffer, unz_BUFFSIZ);
pos_in_buf = 0;
}
int unzStream::get_char (void) int unzStream::get_char (void)
{ {
unsigned char c; unsigned char c;
if (numbytes <= 0) if (buffer_remaining() <= 0)
{ {
numbytes = unzReadCurrentFile(file, buffer, unz_BUFFSIZ); fill_buffer();
if (numbytes <= 0) if (bytes_in_buf <= 0)
return (EOF); return (EOF);
head = buffer;
} }
c = *head; c = *(buffer + pos_in_buf);
head++; pos_in_buf++;
numbytes--;
return ((int) c); return ((int) c);
} }
@ -373,28 +387,25 @@ size_t unzStream::read (void *buf, size_t len)
if (len == 0) if (len == 0)
return (len); return (len);
if (len <= numbytes) size_t to_read = len;
{ uint8 *read_to = (uint8 * )buf;
memcpy(buf, head, len); do
numbytes -= len; {
head += len; size_t in_buffer = buffer_remaining();
return (len); if (to_read <= in_buffer)
} {
memcpy(read_to, buffer + pos_in_buf, to_read);
pos_in_buf += to_read;
to_read = 0;
break;
}
size_t numread = 0; memcpy(read_to, buffer + pos_in_buf, in_buffer);
if (numbytes > 0) to_read -= in_buffer;
{ fill_buffer();
memcpy(buf, head, numbytes); } while (bytes_in_buf);
numread += numbytes;
head = NULL;
numbytes = 0;
}
int l = unzReadCurrentFile(file, (uint8 *)buf + numread, len - numread); return (len - to_read);
if (l > 0)
numread += l;
return (numread);
} }
// not supported // not supported
@ -405,7 +416,7 @@ size_t unzStream::write (void *buf, size_t len)
size_t unzStream::pos (void) size_t unzStream::pos (void)
{ {
return (unztell(file)); return buf_pos_in_unzipped + pos_in_buf;
} }
size_t unzStream::size (void) size_t unzStream::size (void)
@ -415,10 +426,26 @@ size_t unzStream::size (void)
return info.uncompressed_size; return info.uncompressed_size;
} }
// not supported
int unzStream::revert (size_t from, size_t offset) int unzStream::revert (size_t from, size_t offset)
{ {
return -1; size_t target_pos = from + offset;
// new pos inside buffered data
if (target_pos >= buf_pos_in_unzipped && target_pos < buf_pos_in_unzipped + bytes_in_buf)
{
pos_in_buf = target_pos - buf_pos_in_unzipped;
}
else // outside of buffer, reset file and read until pos
{
unzGoToFilePos(file, &unz_file_start_pos);
int times_to_read = target_pos / unz_BUFFSIZ + 1;
for( int i = 0; i < times_to_read; i++)
{
fill_buffer();
}
pos_in_buf = target_pos % unz_BUFFSIZ;
}
return 0;
} }
void unzStream::closeStream() void unzStream::closeStream()

View File

@ -252,10 +252,15 @@ class unzStream : public Stream
virtual void closeStream(); virtual void closeStream();
private: private:
void fill_buffer();
size_t buffer_remaining();
unzFile file; unzFile file;
char buffer[unz_BUFFSIZ]; char buffer[unz_BUFFSIZ];
char *head; size_t pos_in_buf;
size_t numbytes; size_t buf_pos_in_unzipped;
size_t bytes_in_buf;
unz_file_pos unz_file_start_pos;
}; };
#endif #endif