fix map of custom seekable streams
We failed for seekable custom streams. See https://github.com/libvips/libvips/issues/1494#issuecomment-567190830
This commit is contained in:
parent
53dac98b55
commit
8030d7b926
|
@ -672,7 +672,7 @@ vips_streami_read( VipsStreami *streami, void *buffer, size_t length )
|
||||||
bytes_read += available;
|
bytes_read += available;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Some kind of filesystem source.
|
/* Some kind of filesystem or custom source.
|
||||||
*
|
*
|
||||||
* Get what we can from header_bytes. We may need to read
|
* Get what we can from header_bytes. We may need to read
|
||||||
* some more after this.
|
* some more after this.
|
||||||
|
@ -769,12 +769,12 @@ vips_streami_pipe_read_to_position( VipsStreami *streami, gint64 target )
|
||||||
|
|
||||||
while( target == -1 ||
|
while( target == -1 ||
|
||||||
streami->read_position < target ) {
|
streami->read_position < target ) {
|
||||||
ssize_t read;
|
ssize_t bytes_read;
|
||||||
|
|
||||||
read = vips_streami_read( streami, buffer, 4096 );
|
bytes_read = vips_streami_read( streami, buffer, 4096 );
|
||||||
if( read == -1 )
|
if( bytes_read == -1 )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( read == 0 )
|
if( bytes_read == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( target == -1 &&
|
if( target == -1 &&
|
||||||
|
@ -790,6 +790,66 @@ vips_streami_pipe_read_to_position( VipsStreami *streami, gint64 target )
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert a seekable source that can't be mapped (eg. a custom input with a
|
||||||
|
* seek method) into a memory source.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
vips_streami_read_to_memory( VipsStreami *streami )
|
||||||
|
{
|
||||||
|
GByteArray *byte_array;
|
||||||
|
gint64 read_position;
|
||||||
|
unsigned char *q;
|
||||||
|
|
||||||
|
VIPS_DEBUG_MSG( "vips_streami_read_to_memory:\n" );
|
||||||
|
|
||||||
|
g_assert( !streami->is_pipe );
|
||||||
|
g_assert( !streami->blob );
|
||||||
|
g_assert( !streami->header_bytes );
|
||||||
|
g_assert( streami->length >= 0 );
|
||||||
|
|
||||||
|
if( vips_streami_rewind( streami ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
/* We know the length, so we can size the buffer correctly and read
|
||||||
|
* directly to it.
|
||||||
|
*/
|
||||||
|
byte_array = g_byte_array_new();
|
||||||
|
g_byte_array_set_size( byte_array, streami->length );
|
||||||
|
|
||||||
|
/* Read in a series of chunks to reduce stress upstream.
|
||||||
|
*/
|
||||||
|
read_position = 0;
|
||||||
|
q = byte_array->data;
|
||||||
|
while( read_position < streami->length ) {
|
||||||
|
ssize_t bytes_read;
|
||||||
|
|
||||||
|
bytes_read = vips_streami_read( streami, q,
|
||||||
|
VIPS_MAX( 4096, streami->length - read_position ) );
|
||||||
|
if( bytes_read == -1 ) {
|
||||||
|
VIPS_FREEF( g_byte_array_unref, byte_array );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
if( bytes_read == 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
read_position += bytes_read;
|
||||||
|
q += bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Steal the byte_array pointer and turn into a memory source.
|
||||||
|
*
|
||||||
|
* We save byte_array in the header_bytes field to get it freed when
|
||||||
|
* we are freed.
|
||||||
|
*/
|
||||||
|
streami->data = byte_array->data;
|
||||||
|
streami->is_pipe = FALSE;
|
||||||
|
streami->header_bytes = byte_array;
|
||||||
|
|
||||||
|
vips_streami_minimise( streami );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the entire pipe into memory and turn this into a memory source stream.
|
/* Read the entire pipe into memory and turn this into a memory source stream.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
@ -844,6 +904,10 @@ vips_streami_descriptor_to_memory( VipsStreami *streami )
|
||||||
* vips_streami_is_mappable:
|
* vips_streami_is_mappable:
|
||||||
* @streami: input stream to operate on
|
* @streami: input stream to operate on
|
||||||
*
|
*
|
||||||
|
* Some streams can be efficiently mapped into memory.
|
||||||
|
* You can still use vips_streami_map() if this function returns %FALSE,
|
||||||
|
* but it will be slow.
|
||||||
|
*
|
||||||
* Returns: %TRUE if the stream can be efficiently mapped into memory.
|
* Returns: %TRUE if the stream can be efficiently mapped into memory.
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -859,7 +923,7 @@ vips_streami_is_mappable( VipsStreami *streami )
|
||||||
return( streami->data ||
|
return( streami->data ||
|
||||||
VIPS_STREAM( streami )->filename ||
|
VIPS_STREAM( streami )->filename ||
|
||||||
(!streami->is_pipe &&
|
(!streami->is_pipe &&
|
||||||
VIPS_STREAM( streami )->descriptor) );
|
VIPS_STREAM( streami )->descriptor != -1) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -889,13 +953,17 @@ vips_streami_map( VipsStreami *streami, size_t *length_out )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
if( !streami->data ) {
|
if( !streami->data ) {
|
||||||
/* Seekable descriptors can simply be mapped. All other sources
|
/* Seekable descriptors can simply be mapped. Seekable sources
|
||||||
* must be read into memory.
|
* can be read. All other sources must be streamed into memory.
|
||||||
*/
|
*/
|
||||||
if( vips_streami_is_mappable( streami ) ) {
|
if( vips_streami_is_mappable( streami ) ) {
|
||||||
if( vips_streami_descriptor_to_memory( streami ) )
|
if( vips_streami_descriptor_to_memory( streami ) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
else if( !streami->is_pipe ) {
|
||||||
|
if( vips_streami_read_to_memory( streami ) )
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if( vips_streami_pipe_to_memory( streami ) )
|
if( vips_streami_pipe_to_memory( streami ) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
@ -1131,7 +1199,7 @@ vips_streami_sniff_at_most( VipsStreami *streami,
|
||||||
unsigned char **data, size_t length )
|
unsigned char **data, size_t length )
|
||||||
{
|
{
|
||||||
unsigned char *q;
|
unsigned char *q;
|
||||||
size_t bytes_read;
|
gint64 read_position;
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "vips_streami_sniff_at_most: %zd bytes\n", length );
|
VIPS_DEBUG_MSG( "vips_streami_sniff_at_most: %zd bytes\n", length );
|
||||||
|
|
||||||
|
@ -1143,26 +1211,27 @@ vips_streami_sniff_at_most( VipsStreami *streami,
|
||||||
|
|
||||||
g_byte_array_set_size( streami->sniff, length );
|
g_byte_array_set_size( streami->sniff, length );
|
||||||
|
|
||||||
|
read_position = 0;
|
||||||
q = streami->sniff->data;
|
q = streami->sniff->data;
|
||||||
bytes_read = 0;
|
while( read_position < length ) {
|
||||||
while( bytes_read < length ) {
|
ssize_t bytes_read;
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
n = vips_streami_read( streami, q, length - bytes_read );
|
bytes_read = vips_streami_read( streami, q,
|
||||||
if( n == -1 )
|
length - read_position );
|
||||||
|
if( bytes_read == -1 )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( n == 0 )
|
if( bytes_read == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
bytes_read += n;
|
read_position += bytes_read;
|
||||||
q += n;
|
q += bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
SANITY( streami );
|
SANITY( streami );
|
||||||
|
|
||||||
*data = streami->sniff->data;
|
*data = streami->sniff->data;
|
||||||
|
|
||||||
return( bytes_read );
|
return( read_position );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue