revise pipe sources (again)

Simplify and cleanup.
This commit is contained in:
John Cupitt 2020-10-04 14:05:53 +01:00
parent 0ee8b1e844
commit edbe9bf8ef
2 changed files with 55 additions and 81 deletions

View File

@ -872,6 +872,9 @@ vips_foreign_load_heif_load( VipsForeignLoad *load )
vips_image_write( t[1], load->real ) ) vips_image_write( t[1], load->real ) )
return( -1 ); return( -1 );
if( vips_source_decode( heif->source ) )
return( -1 );
return( 0 ); return( 0 );
} }

View File

@ -42,8 +42,8 @@
*/ */
/* /*
#define TEST_SANITY
#define VIPS_DEBUG #define VIPS_DEBUG
#define TEST_SANITY
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -639,13 +639,15 @@ vips_source_decode( VipsSource *source )
SANITY( source ); SANITY( source );
/* We have finished reading the header. We can discard the header bytes
* we saved.
*/
if( !source->decode ) { if( !source->decode ) {
source->decode = TRUE; source->decode = TRUE;
VIPS_FREEF( g_byte_array_unref, source->header_bytes );
VIPS_FREEF( g_byte_array_unref, source->sniff ); VIPS_FREEF( g_byte_array_unref, source->sniff );
/* If this is still a pipe source, we can discard the header
* bytes we saved.
*/
if( source->is_pipe )
VIPS_FREEF( g_byte_array_unref, source->header_bytes );
} }
vips_source_minimise( source ); vips_source_minimise( source );
@ -655,6 +657,25 @@ vips_source_decode( VipsSource *source )
return( 0 ); return( 0 );
} }
#ifdef VIPS_DEBUG
static void
vips_source_print( VipsSource *source )
{
printf( "vips_source_print: %p\n", source );
printf( " source->read_position = %zd\n", source->read_position );
printf( " source->is_pipe = %d\n", source->is_pipe );
printf( " source->length = %zd\n", source->length );
printf( " source->data = %p\n", source->data );
printf( " source->header_bytes = %p\n", source->header_bytes );
if( source->header_bytes )
printf( " source->header_bytes->len = %d\n",
source->header_bytes->len );
printf( " source->sniff = %p\n", source->sniff );
if( source->sniff )
printf( " source->sniff->len = %d\n", source->sniff->len );
}
#endif /*VIPS_DEBUG*/
/** /**
* vips_source_read: * vips_source_read:
* @source: source to operate on * @source: source to operate on
@ -761,31 +782,13 @@ vips_source_read( VipsSource *source, void *buffer, size_t length )
return( total_read ); return( total_read );
} }
#ifdef DEBUG
static void
vips_source_print( VipsSource *source )
{
printf( "vips_source_print: %p\n", source );
printf( " source->read_position = %zd\n", source->read_position );
printf( " source->is_pipe = %d\n", source->is_pipe );
printf( " source->length = %zd\n", source->length );
printf( " source->data = %p\n", source->data );
printf( " source->header_bytes = %p\n", source->header_bytes );
if( source->header_bytes )
printf( " source->header_bytes->len = %d\n",
source->header_bytes->len );
printf( " source->sniff = %p\n", source->sniff );
if( source->sniff )
printf( " source->sniff->len = %d\n", source->sniff->len );
}
#endif /*DEBUG*/
/* Read to a position. /* Read to a position.
* *
* target == -1 means read to end of source -- useful for forcing a pipe into * target == -1 means read to end of source -- useful for forcing a pipe into
* memory, for example. * memory, for example. This will always set length to the pipe length.
* *
* If we hit EOF, set length on the pipe. * If we hit EOF and we're buffering, set length on the pipe and turn it into
* a memory source.
* *
* read_position is left somewhere indeterminate. * read_position is left somewhere indeterminate.
*/ */
@ -800,6 +803,7 @@ vips_source_pipe_read_to_position( VipsSource *source, gint64 target )
* length). * length).
*/ */
g_assert( source->length == -1 ); g_assert( source->length == -1 );
g_assert( source->is_pipe );
while( target == -1 || while( target == -1 ||
source->read_position < target ) { source->read_position < target ) {
@ -813,6 +817,19 @@ vips_source_pipe_read_to_position( VipsSource *source, gint64 target )
/* No more bytes available, we must be at EOF. /* No more bytes available, we must be at EOF.
*/ */
source->length = source->read_position; source->length = source->read_position;
/* Have we been buffering the whole thing? We can
* become a memory source.
*/
if( source->header_bytes ) {
source->data = source->header_bytes->data;
source->is_pipe = FALSE;
/* TODO ... we could close more fds here.
*/
vips_source_minimise( source );
}
break; break;
} }
@ -853,8 +870,6 @@ vips_source_read_to_memory( VipsSource *source )
byte_array = g_byte_array_new(); byte_array = g_byte_array_new();
g_byte_array_set_size( byte_array, source->length ); g_byte_array_set_size( byte_array, source->length );
/* Read in a series of chunks to reduce stress upstream.
*/
read_position = 0; read_position = 0;
q = byte_array->data; q = byte_array->data;
while( read_position < source->length ) { while( read_position < source->length ) {
@ -887,34 +902,6 @@ vips_source_read_to_memory( VipsSource *source )
return( 0 ); return( 0 );
} }
/* Read the entire pipe into memory and turn this into a memory source.
*/
static int
vips_source_pipe_to_memory( VipsSource *source )
{
VIPS_DEBUG_MSG( "vips_source_pipe_to_memory:\n" );
g_assert( source->is_pipe );
g_assert( !source->blob );
g_assert( !source->decode );
g_assert( source->header_bytes );
if( vips_source_pipe_read_to_position( source, -1 ) )
return( -1 );
/* Steal the header_bytes pointer and turn into a memory source.
*/
source->length = source->header_bytes->len;
source->data = source->header_bytes->data;
source->is_pipe = FALSE;
/* TODO ... we could close more fds here.
*/
vips_source_minimise( source );
return( 0 );
}
static int static int
vips_source_descriptor_to_memory( VipsSource *source ) vips_source_descriptor_to_memory( VipsSource *source )
{ {
@ -1002,7 +989,7 @@ vips_source_map( VipsSource *source, size_t *length_out )
return( NULL ); return( NULL );
} }
else { else {
if( vips_source_pipe_to_memory( source ) ) if( vips_source_pipe_read_to_position( source, -1 ) )
return( NULL ); return( NULL );
} }
} }
@ -1113,8 +1100,7 @@ vips_source_seek( VipsSource *source, gint64 offset, int whence )
/* We have to read the whole source into memory to get /* We have to read the whole source into memory to get
* the length. * the length.
*/ */
if( source->length == -1 && if( vips_source_pipe_read_to_position( source, -1 ) )
vips_source_pipe_to_memory( source ) )
return( -1 ); return( -1 );
new_pos = source->length + offset; new_pos = source->length + offset;
@ -1130,6 +1116,13 @@ vips_source_seek( VipsSource *source, gint64 offset, int whence )
return( -1 ); return( -1 );
} }
/* For pipes, we have to fake seek by reading to that point. This
* might hit EOF and turn the pipe into a memory source.
*/
if( source->is_pipe &&
vips_source_pipe_read_to_position( source, new_pos ) )
return( -1 );
/* Don't allow out of range seeks. /* Don't allow out of range seeks.
*/ */
if( new_pos < 0 || if( new_pos < 0 ||
@ -1140,28 +1133,6 @@ vips_source_seek( VipsSource *source, gint64 offset, int whence )
return( -1 ); return( -1 );
} }
/* For pipes, we have to fake seek by reading to that point.
*/
if( source->is_pipe ) {
if( vips_source_pipe_read_to_position( source, new_pos ) )
return( -1 );
/* We've hit EOF in the pipe, and we've got the whole thing
* buffered. Steal the header_bytes pointer and turn into a
* memory source.
*/
if( source->length != -1 &&
source->header_bytes ) {
source->length = source->header_bytes->len;
source->data = source->header_bytes->data;
source->is_pipe = FALSE;
/* TODO ... we could close more fds here.
*/
vips_source_minimise( source );
}
}
source->read_position = new_pos; source->read_position = new_pos;
VIPS_DEBUG_MSG( " new_pos = %" G_GINT64_FORMAT "\n", new_pos ); VIPS_DEBUG_MSG( " new_pos = %" G_GINT64_FORMAT "\n", new_pos );