start reworking again
This commit is contained in:
parent
af8a3bfee7
commit
0e29e1c41e
@ -173,24 +173,15 @@ typedef struct _VipsStreamiClass {
|
||||
/* Subclasses can define these to implement other streami methods.
|
||||
*/
|
||||
|
||||
/* Read up to N bytes from the stream into the supplied buffer,
|
||||
* returning the number of bytes actually read.
|
||||
*
|
||||
* -1 on error, 0 on EOF.
|
||||
/* Read from the stream into the supplied buffer, args exactly as
|
||||
* read(2).
|
||||
*/
|
||||
ssize_t (*read)( VipsStreami *, void *, size_t );
|
||||
|
||||
/* Map the entire stream into memory, for example with mmap(). Return
|
||||
* the base and size of the mapped area.
|
||||
/* Seek to a certain position, args exactly as lseek(2).
|
||||
*
|
||||
* If this is not defined, the file will be read in with repeated
|
||||
* calls to ->read().
|
||||
*
|
||||
* NULL on error.
|
||||
*/
|
||||
const void *(*map)( VipsStreami *, size_t * );
|
||||
|
||||
/* Seek to a certain position, args exactly as lseek(2).
|
||||
* Unseekable streams should just return -1. VipsStreami will then
|
||||
* seek by _read()ing bytes into memory as required.
|
||||
*/
|
||||
gint64 (*seek)( VipsStreami *, gint64 offset, int );
|
||||
|
||||
@ -207,11 +198,6 @@ typedef struct _VipsStreamiClass {
|
||||
*/
|
||||
int (*unminimise)( VipsStreami * );
|
||||
|
||||
/* Length of object in bytes. If this is a pipe, it will force the
|
||||
* whole object to be read into memory, so use cautiously.
|
||||
*/
|
||||
gint64 (*size)( VipsStreami * );
|
||||
|
||||
} VipsStreamiClass;
|
||||
|
||||
GType vips_streami_get_type( void );
|
||||
|
@ -277,7 +277,6 @@ GSList *vips__gslist_gvalue_merge( GSList *a, const GSList *b );
|
||||
char *vips__gslist_gvalue_get( const GSList *list );
|
||||
|
||||
gint64 vips__seek( int fd, gint64 pos, int whence );
|
||||
gboolean vips__can_seek( int fd );
|
||||
int vips__ftruncate( int fd, gint64 pos );
|
||||
int vips_existsf( const char *name, ... )
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
|
@ -34,6 +34,8 @@
|
||||
/* TODO
|
||||
*
|
||||
* - filename encoding
|
||||
* - gaussblur is missing the vector path again argh
|
||||
* - can we map and then close the fd?
|
||||
* - are we detecting EOF correctly? what about interrupted reads? perhaps
|
||||
* we should check errno as well
|
||||
* - need to be able to set is_pipe via constructor
|
||||
@ -203,6 +205,7 @@ vips_streami_build( VipsObject *object )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( object );
|
||||
VipsStreami *streami = VIPS_STREAMI( object );
|
||||
VipsStreamiClass *class = VIPS_STREAMI_GET_CLASS( streami );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_build: %p\n", streami );
|
||||
|
||||
@ -234,28 +237,28 @@ vips_streami_build( VipsObject *object )
|
||||
*/
|
||||
if( stream->descriptor != -1 ) {
|
||||
/* Can we seek? If not, this is some kind of pipe.
|
||||
*
|
||||
* We must call the class method directly: if we go via
|
||||
* vips_streami_seek() we'll trigger seek emulation on pipes.
|
||||
*/
|
||||
if( !vips__can_seek( stream->descriptor ) ) {
|
||||
vips_error_freeze();
|
||||
if( class->seek( stream->descriptor, 0, SEEK_CUR ) == -1 ) {
|
||||
VIPS_DEBUG_MSG( " not seekable\n" );
|
||||
streami->is_pipe = TRUE;
|
||||
}
|
||||
vips_error_thaw();
|
||||
|
||||
/* Try and get the length. Don't bother for pipes.
|
||||
/* Try and get the length, as long as we're seekable.
|
||||
*/
|
||||
if( !streami->is_pipe &&
|
||||
(streami->length =
|
||||
vips_file_length( stream->descriptor )) == -1 )
|
||||
(streami->length = vips_streami_size( streami )) == -1 )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Need to save the header for pipe-style sources.
|
||||
/* If we can seek, we won't need to save header bytes.
|
||||
*/
|
||||
if( streami->is_pipe )
|
||||
streami->header_bytes = g_byte_array_new();
|
||||
|
||||
/* We always want a sniff buffer.
|
||||
*/
|
||||
streami->sniff = g_byte_array_new();
|
||||
if( !streami->is_pipe )
|
||||
VIPS_FREEF( g_byte_array_unref, streami->header_bytes );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -267,44 +270,7 @@ vips_streami_read_real( VipsStreami *streami, void *data, size_t length )
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_read_real:\n" );
|
||||
|
||||
if( streami->blob ) {
|
||||
VipsArea *area = VIPS_AREA( streami->blob );
|
||||
ssize_t available = VIPS_MIN( length,
|
||||
area->length - streami->read_position );
|
||||
|
||||
if( available <= 0 )
|
||||
return( 0 );
|
||||
|
||||
memcpy( data, area->data + streami->read_position, available );
|
||||
|
||||
return( available );
|
||||
}
|
||||
else if( stream->descriptor != -1 ) {
|
||||
return( read( stream->descriptor, data, length ) );
|
||||
}
|
||||
else {
|
||||
g_assert( 0 );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
static const void *
|
||||
vips_streami_map_real( VipsStreami *streami, size_t *length )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( streami );
|
||||
|
||||
const void *file_baseaddr;
|
||||
|
||||
g_assert( streami->length > 0 );
|
||||
|
||||
if( !(file_baseaddr = vips__mmap( stream->descriptor,
|
||||
FALSE, streami->length, 0 )) )
|
||||
return( NULL );
|
||||
|
||||
if( length )
|
||||
*length = streami->length;
|
||||
|
||||
return( file_baseaddr );
|
||||
return( read( stream->descriptor, data, length ) );
|
||||
}
|
||||
|
||||
static gint64
|
||||
@ -312,39 +278,9 @@ vips_streami_seek_real( VipsStreami *streami, gint64 offset, int whence )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( streami );
|
||||
|
||||
gint64 new_pos;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_seek_real:\n" );
|
||||
|
||||
if( streami->blob ) {
|
||||
switch( whence ) {
|
||||
case SEEK_SET:
|
||||
new_pos = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
new_pos = streami->read_position + offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
new_pos = streami->length + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( stream->descriptor != -1 ) {
|
||||
new_pos = vips__seek( stream->descriptor, offset, whence );
|
||||
}
|
||||
else {
|
||||
vips_error( vips_stream_name( stream ),
|
||||
"%s", _( "not seekable" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( new_pos );
|
||||
return( vips__seek( stream->descriptor, offset, whence ) );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -444,6 +380,8 @@ vips_streami_pipe_to_memory( VipsStreami *streami )
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_pipe_to_memory:\n" );
|
||||
|
||||
g_assert( streami->is_pipe );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
if( vips_streami_pipe_read_to_position( streami, -1 ) )
|
||||
@ -511,6 +449,8 @@ static void
|
||||
vips_streami_init( VipsStreami *streami )
|
||||
{
|
||||
streami->length = -1;
|
||||
streami->sniff = g_byte_array_new();
|
||||
streami->header_bytes = g_byte_array_new();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -700,6 +640,20 @@ vips_streami_read( VipsStreami *streami, void *buffer, size_t length )
|
||||
VIPS_DEBUG_MSG( " %zd bytes from cache\n", available );
|
||||
}
|
||||
|
||||
revise this:
|
||||
if( streami->blob ) {
|
||||
VipsArea *area = VIPS_AREA( streami->blob );
|
||||
ssize_t available = VIPS_MIN( length,
|
||||
area->length - streami->read_position );
|
||||
|
||||
if( available <= 0 )
|
||||
return( 0 );
|
||||
|
||||
memcpy( data, area->data + streami->read_position, available );
|
||||
|
||||
return( available );
|
||||
}
|
||||
|
||||
/* Any more bytes requested? Call the read() vfunc.
|
||||
*/
|
||||
if( length > 0 ) {
|
||||
@ -735,6 +689,32 @@ vips_streami_read( VipsStreami *streami, void *buffer, size_t length )
|
||||
return( bytes_read );
|
||||
}
|
||||
|
||||
static const void *
|
||||
vips_streami_map_real( VipsStreami *streami, size_t *length )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( streami );
|
||||
|
||||
const void *file_baseaddr;
|
||||
|
||||
g_assert( streami->length > 0 );
|
||||
|
||||
if( !(file_baseaddr = vips__mmap( stream->descriptor,
|
||||
FALSE, streami->length, 0 )) )
|
||||
return( NULL );
|
||||
|
||||
if( length )
|
||||
*length = streami->length;
|
||||
|
||||
return( file_baseaddr );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_streami_unmap_real( VipsStreami *streami, size_t *length )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( streami );
|
||||
|
||||
}
|
||||
|
||||
const void *
|
||||
vips_streami_map( VipsStreami *streami, size_t *length_out )
|
||||
{
|
||||
@ -800,6 +780,12 @@ vips_streami_seek( VipsStreami *streami, gint64 offset, int whence )
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
/* Not tagged as a pipe? Attempt to use the seek method.
|
||||
*/
|
||||
if( !streami->is_pipe ) {
|
||||
if( (new_pos = class->seek( streami, offset, whence )) == -1 )
|
||||
return( -1 );
|
||||
|
||||
switch( whence ) {
|
||||
case SEEK_SET:
|
||||
new_pos = offset;
|
||||
@ -834,6 +820,27 @@ vips_streami_seek( VipsStreami *streami, gint64 offset, int whence )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
revise this:
|
||||
if( streami->blob ) {
|
||||
switch( whence ) {
|
||||
case SEEK_SET:
|
||||
new_pos = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
new_pos = streami->read_position + offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
new_pos = streami->length + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( streami->is_pipe ) {
|
||||
if( vips_streami_pipe_read_to_position( streami, new_pos ) )
|
||||
return( -1 );
|
||||
@ -907,12 +914,15 @@ vips_streami_size( VipsStreami *streami )
|
||||
VipsStreamiClass *class = VIPS_STREAMI_GET_CLASS( streami );
|
||||
|
||||
gint64 size;
|
||||
gint64 read_position;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_size:\n" );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
size = class->size( streami );
|
||||
read_position = vips_streami_seek( streami, 0, SEEK_CUR );
|
||||
size = vips_streami_seek( streami, 0, SEEK_END );
|
||||
vips_streami_seek( streami, read_position, SEEK_SET );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
|
@ -1062,20 +1062,6 @@ vips__seek( int fd, gint64 pos, int whence )
|
||||
return( new_pos );
|
||||
}
|
||||
|
||||
/* Does an fd support seek? Pipes do not, for example.
|
||||
*/
|
||||
gboolean
|
||||
vips__can_seek( int fd )
|
||||
{
|
||||
gboolean result;
|
||||
|
||||
vips_error_freeze();
|
||||
result = vips__seek( fd, 0, SEEK_CUR ) != -1;
|
||||
vips_error_thaw();
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/* Need our own ftruncate(), since ftruncate() on win32 can't do long files.
|
||||
|
||||
DANGER ... this moves the file pointer to the end of file on win32,
|
||||
|
Loading…
x
Reference in New Issue
Block a user