start adding mmap input to stream
This commit is contained in:
parent
88aa1bca86
commit
28daeb1a8a
@ -136,6 +136,7 @@ void *vips__link_map( VipsImage *image, gboolean upstream,
|
||||
char *vips__b64_encode( const unsigned char *data, size_t data_length );
|
||||
unsigned char *vips__b64_decode( const char *buffer, size_t *data_length );
|
||||
|
||||
gboolean vips__mmap_supported( int fd );
|
||||
void *vips__mmap( int fd, int writeable, size_t length, gint64 offset );
|
||||
int vips__munmap( const void *start, size_t length );
|
||||
int vips_mapfile( VipsImage * );
|
||||
|
@ -129,6 +129,11 @@ typedef struct _VipsStreamInput {
|
||||
*/
|
||||
gboolean seekable;
|
||||
|
||||
/* TRUE is this descriptor supports mmap(). If not, then we have to
|
||||
* read() the whole thing.
|
||||
*/
|
||||
gboolean mapable;
|
||||
|
||||
/*< private >*/
|
||||
|
||||
/* The current read point.
|
||||
@ -148,6 +153,11 @@ typedef struct _VipsStreamInput {
|
||||
*/
|
||||
VipsBlob *blob;
|
||||
|
||||
/* If we've mmaped the file, the base and length.
|
||||
*/
|
||||
const void *baseaddr;
|
||||
size_t length;
|
||||
|
||||
} VipsStreamInput;
|
||||
|
||||
typedef struct _VipsStreamInputClass {
|
||||
|
@ -90,6 +90,59 @@
|
||||
#include <io.h>
|
||||
#endif /*OS_WIN32*/
|
||||
|
||||
/* Does this fd support mmap. Pipes won't, for example.
|
||||
*/
|
||||
gboolean
|
||||
vips__mmap_supported( int fd )
|
||||
{
|
||||
void *baseaddr;
|
||||
size_t length = 4096;
|
||||
off_t offset = 0;
|
||||
|
||||
#ifdef OS_WIN32
|
||||
{
|
||||
HANDLE hFile = (HANDLE) _get_osfhandle( fd );
|
||||
|
||||
DWORD flProtect;
|
||||
HANDLE hMMFile;
|
||||
|
||||
DWORD dwDesiredAccess;
|
||||
ULARGE_INTEGER quad;
|
||||
DWORD dwFileOffsetHigh;
|
||||
DWORD dwFileOffsetLow;
|
||||
|
||||
flProtect = PAGE_READONLY;
|
||||
if( !(hMMFile = CreateFileMapping( hFile,
|
||||
NULL, flProtect, 0, 0, NULL )) )
|
||||
return( FALSE );
|
||||
|
||||
dwDesiredAccess = FILE_MAP_READ;
|
||||
quad.QuadPart = offset;
|
||||
dwFileOffsetLow = quad.LowPart;
|
||||
dwFileOffsetHigh = quad.HighPart;
|
||||
if( !(baseaddr = (char *)MapViewOfFile( hMMFile, dwDesiredAccess,
|
||||
dwFileOffsetHigh, dwFileOffsetLow, length )) ) {
|
||||
CloseHandle( hMMFile );
|
||||
return( FALSE );
|
||||
}
|
||||
CloseHandle( hMMFile );
|
||||
UnmapViewOfFile( baseaddr );
|
||||
}
|
||||
#else /*!OS_WIN32*/
|
||||
{
|
||||
int prot = PROT_READ;
|
||||
int flags = MAP_SHARED;
|
||||
|
||||
baseaddr = mmap( 0, length, prot, flags, fd, (off_t) offset );
|
||||
if( baseaddr == MAP_FAILED )
|
||||
return( FALSE );
|
||||
munmap( baseaddr, length );
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
void *
|
||||
vips__mmap( int fd, int writeable, size_t length, gint64 offset )
|
||||
{
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
/* Try to make an O_BINARY ... sometimes need the leading '_'.
|
||||
@ -270,6 +271,9 @@ vips_stream_input_build( VipsObject *object )
|
||||
*/
|
||||
if( lseek( stream->descriptor, 0, SEEK_CUR ) != -1 )
|
||||
input->seekable = TRUE;
|
||||
|
||||
if( vips__mmap_supported( stream->descriptor ) )
|
||||
input->mapable = TRUE;
|
||||
}
|
||||
|
||||
if( vips_object_argument_isset( object, "blob" ) )
|
||||
@ -396,6 +400,7 @@ vips_stream_input_class_init( VipsStreamInputClass *class )
|
||||
static void
|
||||
vips_stream_input_init( VipsStreamInput *input )
|
||||
{
|
||||
input->length = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -606,9 +611,57 @@ vips_stream_input_read( VipsStreamInput *input,
|
||||
return( bytes_read );
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
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 )
|
||||
{
|
||||
/* Memory source ... easy!
|
||||
*/
|
||||
if( input->blob )
|
||||
return( vips_blob_get( input->blob, length ) );
|
||||
|
||||
/* An input that supports mmap.
|
||||
*/
|
||||
if( input->mapable ) {
|
||||
if( !input->baseaddr ) {
|
||||
input->baseaddr = vips_stream_input_try_map( input,
|
||||
&input->length );
|
||||
if( !input->baseaddr )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if( length )
|
||||
*length = input->length;
|
||||
|
||||
return( input->baseaddr );
|
||||
}
|
||||
|
||||
/* Have to read() the whole thing.
|
||||
*/
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user