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)
{
file = v;
head = NULL;
numbytes = 0;
pos_in_buf = 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)
@ -324,21 +328,31 @@ unzStream::~unzStream (void)
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)
{
unsigned char c;
if (numbytes <= 0)
if (buffer_remaining() <= 0)
{
numbytes = unzReadCurrentFile(file, buffer, unz_BUFFSIZ);
if (numbytes <= 0)
fill_buffer();
if (bytes_in_buf <= 0)
return (EOF);
head = buffer;
}
c = *head;
head++;
numbytes--;
c = *(buffer + pos_in_buf);
pos_in_buf++;
return ((int) c);
}
@ -373,28 +387,25 @@ size_t unzStream::read (void *buf, size_t len)
if (len == 0)
return (len);
if (len <= numbytes)
size_t to_read = len;
uint8 *read_to = (uint8 * )buf;
do
{
memcpy(buf, head, len);
numbytes -= len;
head += len;
return (len);
size_t in_buffer = buffer_remaining();
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;
if (numbytes > 0)
{
memcpy(buf, head, numbytes);
numread += numbytes;
head = NULL;
numbytes = 0;
}
memcpy(read_to, buffer + pos_in_buf, in_buffer);
to_read -= in_buffer;
fill_buffer();
} while (bytes_in_buf);
int l = unzReadCurrentFile(file, (uint8 *)buf + numread, len - numread);
if (l > 0)
numread += l;
return (numread);
return (len - to_read);
}
// not supported
@ -405,7 +416,7 @@ size_t unzStream::write (void *buf, size_t len)
size_t unzStream::pos (void)
{
return (unztell(file));
return buf_pos_in_unzipped + pos_in_buf;
}
size_t unzStream::size (void)
@ -415,10 +426,26 @@ size_t unzStream::size (void)
return info.uncompressed_size;
}
// not supported
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()

View File

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