add mmap input sources

falls back to read() if no mmap
This commit is contained in:
John Cupitt 2019-10-15 14:04:47 +01:00
parent 28daeb1a8a
commit 5a788b89cf
2 changed files with 53 additions and 36 deletions

View File

@ -166,6 +166,7 @@ typedef struct _VipsStreamInputClass {
/* Subclasses can define these to implement other input methods.
*/
ssize_t (*read)( VipsStreamInput *, unsigned char *, size_t );
const void * (*map)( VipsStreamInput *, size_t * );
int (*rewind)( VipsStreamInput * );
/* Shut down anything that can safely restarted. For example, if

View File

@ -325,6 +325,27 @@ vips_stream_input_read_real( VipsStreamInput *input,
}
}
static const void *
vips_stream_input_map_real( VipsStreamInput *input, size_t *length )
{
VipsStream *stream = VIPS_STREAM( input );
gint64 file_length;
const void *file_baseaddr;
if( (file_length = vips_file_length( stream->descriptor )) < 0 )
return( NULL );
if( !(file_baseaddr = vips__mmap( stream->descriptor,
FALSE, file_length, 0 )) )
return( NULL );
if( length )
*length = file_length;
return( file_baseaddr );
}
static int
vips_stream_input_rewind_real( VipsStreamInput *input )
{
@ -332,12 +353,6 @@ vips_stream_input_rewind_real( VipsStreamInput *input )
VIPS_DEBUG_MSG( "vips_stream_input_rewind_real:\n" );
if( input->decode ) {
vips_error( STREAM_NAME( stream ),
"%s", _( "can't rewind after decode begins" ) );
return( -1 );
}
if( input->seekable &&
stream->descriptor != -1 ) {
off_t new_pos;
@ -353,8 +368,6 @@ vips_stream_input_rewind_real( VipsStreamInput *input )
}
}
input->read_position = 0;
return( 0 );
}
@ -385,6 +398,7 @@ vips_stream_input_class_init( VipsStreamInputClass *class )
object_class->build = vips_stream_input_build;
class->read = vips_stream_input_read_real;
class->map = vips_stream_input_map_real;
class->rewind = vips_stream_input_rewind_real;
class->minimise = vips_stream_input_minimise_real;
@ -611,43 +625,28 @@ vips_stream_input_read( VipsStreamInput *input,
return( bytes_read );
}
static const void *
vips_stream_input_try_map( VipsStreamInput *input, size_t *length )
{
VipsStream *stream = VIPS_STREAM( input );
if( input->length < 0 )
input->length = vips_file_length( stream->descriptor );
if( input->length < 0 )
return( NULL );
if( !input->baseaddr ) {
input->baseaddr = vips__mmap( stream->descriptor,
FALSE, input->length, 0 );
if( !input->baseaddr )
return( NULL );
}
if( length )
*length = input->length;
return( input->baseaddr );
}
const void *
vips_stream_input_map( VipsStreamInput *input, size_t *length )
{
VipsStreamInputClass *class = VIPS_STREAM_INPUT_GET_CLASS( input );
unsigned char buffer[4096];
VIPS_DEBUG_MSG( "vips_stream_input_map:\n" );
/* Memory source ... easy!
*/
if( input->blob )
if( input->blob ) {
VIPS_DEBUG_MSG( " memory source\n" );
return( vips_blob_get( input->blob, length ) );
}
/* An input that supports mmap.
*/
if( input->mapable ) {
VIPS_DEBUG_MSG( " mmaping source\n" );
if( !input->baseaddr ) {
input->baseaddr = vips_stream_input_try_map( input,
&input->length );
input->baseaddr = class->map( input, &input->length );
if( !input->baseaddr )
return( NULL );
}
@ -658,10 +657,19 @@ vips_stream_input_map( VipsStreamInput *input, size_t *length )
return( input->baseaddr );
}
/* Have to read() the whole thing.
/* Have to read() the whole thing. header_bytes will keep a copy of
* the file.
*/
VIPS_DEBUG_MSG( " read() of entire source\n" );
if( vips_stream_input_rewind( input ) )
return( NULL );
while( vips_stream_input_read( input, buffer, 4096 ) > 0 )
;
return( NULL );
if( length )
*length = input->header_bytes->len;
return( input->header_bytes->data );
}
int
@ -671,6 +679,14 @@ vips_stream_input_rewind( VipsStreamInput *input )
VIPS_DEBUG_MSG( "vips_stream_input_rewind:\n" );
if( input->decode ) {
vips_error( STREAM_NAME( input ),
"%s", _( "can't rewind after decode begins" ) );
return( -1 );
}
input->read_position = 0;
return( class->rewind( input ) );
}