builds
now needs testing
This commit is contained in:
parent
ee3270f8e9
commit
60ce52512c
@ -86,6 +86,8 @@ typedef struct _VipsStreamClass {
|
||||
|
||||
GType vips_stream_get_type( void );
|
||||
|
||||
int vips_stream_open( VipsStream *stream );
|
||||
int vips_stream_close( VipsStream *stream );
|
||||
const char *vips_stream_name( VipsStream *stream );
|
||||
|
||||
#define VIPS_TYPE_STREAMI (vips_streami_get_type())
|
||||
@ -201,6 +203,15 @@ typedef struct _VipsStreamiClass {
|
||||
*/
|
||||
void (*minimise)( VipsStreami * );
|
||||
|
||||
/* The opposite of minimise: restart anything that minimise shut down.
|
||||
*/
|
||||
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 );
|
||||
@ -216,6 +227,7 @@ const void *vips_streami_map( VipsStreami *streami, size_t *length );
|
||||
gint64 vips_streami_seek( VipsStreami *streami, gint64 offset, int whence );
|
||||
int vips_streami_rewind( VipsStreami *streami );
|
||||
void vips_streami_minimise( VipsStreami *streami );
|
||||
int vips_streami_unminimise( VipsStreami *streami );
|
||||
int vips_streami_decode( VipsStreami *streami );
|
||||
unsigned char *vips_streami_sniff( VipsStreami *streami, size_t length );
|
||||
gint64 vips_streami_size( VipsStreami *streami );
|
||||
|
@ -2185,8 +2185,7 @@ vips_image_new_from_buffer( const void *buf, size_t len,
|
||||
* Returns: (transfer full): the new #VipsImage, or %NULL on error.
|
||||
*/
|
||||
VipsImage *
|
||||
vips_image_new_from_stream( VipsStreamInput *input,
|
||||
const char *option_string, ... )
|
||||
vips_image_new_from_stream( VipsStreami *input, const char *option_string, ... )
|
||||
{
|
||||
const char *operation_name;
|
||||
va_list ap;
|
||||
@ -2726,7 +2725,7 @@ vips_image_write_to_buffer( VipsImage *in,
|
||||
*/
|
||||
int
|
||||
vips_image_write_to_stream( VipsImage *in,
|
||||
const char *suffix, VipsStreamOutput *output, ... )
|
||||
const char *suffix, VipsStreamo *output, ... )
|
||||
{
|
||||
char filename[VIPS_PATH_MAX];
|
||||
char option_string[VIPS_PATH_MAX];
|
||||
|
@ -330,8 +330,8 @@ vips_init( const char *argv0 )
|
||||
extern GType write_thread_state_get_type( void );
|
||||
extern GType sink_memory_thread_state_get_type( void );
|
||||
extern GType render_thread_state_get_type( void );
|
||||
extern GType vips_stream_input_get_type( void );
|
||||
extern GType vips_stream_output_get_type( void );
|
||||
extern GType vips_streami_get_type( void );
|
||||
extern GType vips_streamo_get_type( void );
|
||||
|
||||
static gboolean started = FALSE;
|
||||
static gboolean done = FALSE;
|
||||
@ -446,8 +446,8 @@ vips_init( const char *argv0 )
|
||||
(void) write_thread_state_get_type();
|
||||
(void) sink_memory_thread_state_get_type();
|
||||
(void) render_thread_state_get_type();
|
||||
(void) vips_stream_input_get_type();
|
||||
(void) vips_stream_output_get_type();
|
||||
(void) vips_streami_get_type();
|
||||
(void) vips_streamo_get_type();
|
||||
vips__meta_init_types();
|
||||
vips__interpolate_init();
|
||||
im__format_init();
|
||||
|
@ -1908,10 +1908,10 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
vips__filename_split8( value, filename, option_string );
|
||||
|
||||
if( strcmp( "stdin", filename ) == 0 ) {
|
||||
VipsStreamInput *input;
|
||||
VipsStreami *input;
|
||||
|
||||
if( !(input =
|
||||
vips_stream_input_new_from_descriptor( 0 )) )
|
||||
vips_streami_new_from_descriptor( 0 )) )
|
||||
return( -1 );
|
||||
if( !(out = vips_image_new_from_stream( input,
|
||||
option_string,
|
||||
@ -1937,18 +1937,18 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
*/
|
||||
g_object_unref( out );
|
||||
}
|
||||
else if( g_type_is_a( otype, VIPS_TYPE_STREAM_INPUT ) ) {
|
||||
VipsStreamInput *input;
|
||||
else if( g_type_is_a( otype, VIPS_TYPE_STREAMI ) ) {
|
||||
VipsStreami *input;
|
||||
|
||||
if( !value ) {
|
||||
vips_object_no_value( object, name );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( !(input = vips_stream_input_new_from_options( value )) )
|
||||
if( !(input = vips_streami_new_from_options( value )) )
|
||||
return( -1 );
|
||||
|
||||
g_value_init( &gvalue, VIPS_TYPE_STREAM_INPUT );
|
||||
g_value_init( &gvalue, VIPS_TYPE_STREAMI );
|
||||
g_value_set_object( &gvalue, input );
|
||||
|
||||
/* Setting gvalue will have upped @out's count again,
|
||||
@ -2210,10 +2210,9 @@ vips_object_get_argument_to_string( VipsObject *object,
|
||||
vips__filename_split8( arg, filename, option_string );
|
||||
|
||||
if( vips_isprefix( ".", filename ) ) {
|
||||
VipsStreamOutput *output;
|
||||
VipsStreamo *output;
|
||||
|
||||
if( !(output =
|
||||
vips_stream_output_new_from_descriptor( 1 )) )
|
||||
if( !(output = vips_streamo_new_from_descriptor( 1 )) )
|
||||
return( -1 );
|
||||
g_object_get( object, name, &in, NULL );
|
||||
if( vips_image_write_to_stream( in,
|
||||
|
@ -79,26 +79,6 @@
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE( VipsStream, vips_stream, VIPS_TYPE_OBJECT );
|
||||
|
||||
static void
|
||||
vips_stream_close( VipsStream *stream )
|
||||
{
|
||||
VIPS_DEBUG_MSG( "vips_stream_close:\n" );
|
||||
|
||||
if( stream->close_descriptor >= 0 ) {
|
||||
VIPS_DEBUG_MSG( " close()\n" );
|
||||
close( stream->close_descriptor );
|
||||
stream->close_descriptor = -1;
|
||||
}
|
||||
|
||||
if( stream->tracked_descriptor >= 0 ) {
|
||||
VIPS_DEBUG_MSG( " vips_tracked_close()\n" );
|
||||
vips_tracked_close( stream->tracked_descriptor );
|
||||
stream->tracked_descriptor = -1;
|
||||
}
|
||||
|
||||
stream->descriptor = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
vips_stream_finalize( GObject *gobject )
|
||||
{
|
||||
@ -110,7 +90,20 @@ vips_stream_finalize( GObject *gobject )
|
||||
VIPS_DEBUG_MSG( "\n" );
|
||||
#endif /*VIPS_DEBUG*/
|
||||
|
||||
vips_stream_close( stream );
|
||||
if( stream->tracked_descriptor >= 0 ) {
|
||||
VIPS_DEBUG_MSG( " tracked_close()\n" );
|
||||
vips_tracked_close( stream->tracked_descriptor );
|
||||
stream->tracked_descriptor = -1;
|
||||
stream->descriptor = -1;
|
||||
}
|
||||
|
||||
if( stream->close_descriptor >= 0 ) {
|
||||
VIPS_DEBUG_MSG( " close()\n" );
|
||||
close( stream->close_descriptor );
|
||||
stream->close_descriptor = -1;
|
||||
stream->descriptor = -1;
|
||||
}
|
||||
|
||||
VIPS_FREE( stream->filename );
|
||||
|
||||
G_OBJECT_CLASS( vips_stream_parent_class )->finalize( gobject );
|
||||
@ -156,3 +149,4 @@ vips_stream_name( VipsStream *stream )
|
||||
stream->filename :
|
||||
VIPS_OBJECT( stream )->nickname );
|
||||
}
|
||||
|
||||
|
@ -36,12 +36,6 @@
|
||||
* - filename encoding
|
||||
* - are we detecting EOF correctly? what about interrupted reads? perhaps
|
||||
* we should check errno as well
|
||||
* - _size() needs to be a vfunc too (libtiff needs it)
|
||||
* - _miminize() is a vfunc, so _open() must be as well
|
||||
* + perhaps minimise should not be a vfunc? is it really useful for
|
||||
* subclasses?
|
||||
* + perhaps make _open() / _close() into vfuncs on stream (not streami) and
|
||||
* don't expose minimise
|
||||
* - need to be able to set is_pipe via constructor
|
||||
* - test we can really change all behaviour in the subclass ... add callbacks
|
||||
* as well to make it simpler for language bindings
|
||||
@ -200,43 +194,6 @@ vips_streami_finalize( GObject *gobject )
|
||||
G_OBJECT_CLASS( vips_streami_parent_class )->finalize( gobject );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_streami_open( VipsStreami *streami )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( streami );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
if( stream->descriptor == -1 &&
|
||||
stream->tracked_descriptor == -1 &&
|
||||
stream->filename ) {
|
||||
int fd;
|
||||
|
||||
if( (fd = vips_tracked_open( stream->filename,
|
||||
MODE_READ )) == -1 ) {
|
||||
vips_error_system( errno, vips_stream_name( stream ),
|
||||
"%s", _( "unable to open for read" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
stream->tracked_descriptor = fd;
|
||||
stream->descriptor = fd;
|
||||
|
||||
if( streami->length == -1 &&
|
||||
(streami->length = vips_file_length( fd )) == -1 )
|
||||
return( -1 );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_open: "
|
||||
"restoring read position %zd\n",
|
||||
streami->read_position );
|
||||
if( vips__seek( stream->descriptor,
|
||||
streami->read_position, SEEK_SET ) == -1 )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_streami_build( VipsObject *object )
|
||||
{
|
||||
@ -257,7 +214,7 @@ vips_streami_build( VipsObject *object )
|
||||
}
|
||||
|
||||
if( vips_object_argument_isset( object, "filename" ) &&
|
||||
vips_streami_open( streami ) )
|
||||
vips_streami_unminimise( streami ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_object_argument_isset( object, "descriptor" ) ) {
|
||||
@ -360,8 +317,128 @@ vips_streami_minimise_real( VipsStreami *streami )
|
||||
|
||||
if( stream->filename &&
|
||||
stream->descriptor != -1 &&
|
||||
!streami->is_pipe )
|
||||
vips_stream_close( stream );
|
||||
stream->tracked_descriptor != -1 &&
|
||||
!streami->is_pipe ) {
|
||||
VIPS_DEBUG_MSG( " tracked_close()\n" );
|
||||
vips_tracked_close( stream->tracked_descriptor );
|
||||
stream->tracked_descriptor = -1;
|
||||
stream->descriptor = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
vips_streami_unminimise_real( VipsStreami *streami )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( streami );
|
||||
|
||||
if( stream->descriptor == -1 &&
|
||||
stream->tracked_descriptor == -1 &&
|
||||
stream->filename ) {
|
||||
int fd;
|
||||
|
||||
if( (fd = vips_tracked_open( stream->filename,
|
||||
MODE_READ )) == -1 )
|
||||
return( -1 );
|
||||
|
||||
stream->tracked_descriptor = fd;
|
||||
stream->descriptor = fd;
|
||||
|
||||
if( streami->length == -1 &&
|
||||
(streami->length = vips_file_length( fd )) == -1 )
|
||||
return( -1 );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_unminimise_real: "
|
||||
"restoring read position %zd\n",
|
||||
streami->read_position );
|
||||
if( vips__seek( stream->descriptor,
|
||||
streami->read_position, SEEK_SET ) == -1 )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Read a pipe to at least a position. -1 means read to end of stream. Does
|
||||
* not chenge read_position.
|
||||
*/
|
||||
static int
|
||||
vips_streami_pipe_read_to_position( VipsStreami *streami, gint64 target )
|
||||
{
|
||||
gint64 old_read_position;
|
||||
unsigned char buffer[4096];
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_pipe_read_position:\n" );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
if( streami->decode ) {
|
||||
vips_error( vips_stream_name( VIPS_STREAM( streami ) ),
|
||||
"%s", _( "can't seek pipe after "
|
||||
"pixel decode begins" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
old_read_position = streami->read_position;
|
||||
|
||||
/* TODO ... add something to prevent unbounded streams filling memory.
|
||||
*/
|
||||
while( target == -1 ||
|
||||
streami->read_position < target ) {
|
||||
ssize_t read;
|
||||
|
||||
read = vips_streami_read( streami, buffer, 4096 );
|
||||
if( read == -1 )
|
||||
return( -1 );
|
||||
if( read == 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
streami->read_position = old_read_position;
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Read the entire pipe into memory and turn this into a memory source stream.
|
||||
*/
|
||||
static int
|
||||
vips_streami_pipe_to_memory( VipsStreami *streami )
|
||||
{
|
||||
unsigned char *data;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_pipe_to_memory:\n" );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
if( vips_streami_pipe_read_to_position( streami, -1 ) )
|
||||
return( -1 );
|
||||
|
||||
/* Move header_bytes into the memory blob and set up as a memory
|
||||
* source.
|
||||
*/
|
||||
streami->length = streami->header_bytes->len;
|
||||
data = g_byte_array_free( streami->header_bytes, FALSE );
|
||||
streami->header_bytes = NULL;
|
||||
vips_blob_set( streami->blob,
|
||||
(VipsCallbackFn) g_free, data, streami->length );
|
||||
vips_streami_minimise( streami );
|
||||
streami->is_pipe = FALSE;
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static gint64
|
||||
vips_streami_size_real( VipsStreami *streami )
|
||||
{
|
||||
if( streami->length == -1 &&
|
||||
streami->is_pipe &&
|
||||
vips_streami_pipe_to_memory( streami ) )
|
||||
return( -1 );
|
||||
|
||||
return( streami->length );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -383,6 +460,8 @@ vips_streami_class_init( VipsStreamiClass *class )
|
||||
class->map = vips_streami_map_real;
|
||||
class->seek = vips_streami_seek_real;
|
||||
class->minimise = vips_streami_minimise_real;
|
||||
class->unminimise = vips_streami_unminimise_real;
|
||||
class->size = vips_streami_size_real;
|
||||
|
||||
VIPS_ARG_BOXED( class, "blob", 3,
|
||||
_( "Blob" ),
|
||||
@ -621,85 +700,12 @@ vips_streami_read( VipsStreami *streami, void *buffer, size_t length )
|
||||
return( bytes_read );
|
||||
}
|
||||
|
||||
/* Read a pipe to at least a position. -1 means read to end of stream. Does
|
||||
* not chenge read_position.
|
||||
*/
|
||||
static int
|
||||
vips_streami_pipe_read_to_position( VipsStreami *streami, gint64 target )
|
||||
{
|
||||
gint64 old_read_position;
|
||||
unsigned char buffer[4096];
|
||||
unsigned char *data;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_pipe_read_position:\n" );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
if( streami->decode ) {
|
||||
vips_error( vips_stream_name( VIPS_STREAM( streami ) ),
|
||||
"%s", _( "can't seek pipe after "
|
||||
"pixel decode begins" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
old_read_position = streami->read_position;
|
||||
|
||||
/* TODO ... add something to prevent unbounded streams filling memory.
|
||||
*/
|
||||
while( target == -1 ||
|
||||
streami->read_position < target ) {
|
||||
ssize_t read;
|
||||
|
||||
read = vips_streami_read( streami, buffer, 4096 );
|
||||
if( read == -1 )
|
||||
return( -1 );
|
||||
if( read == 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
streami->read_position = old_read_position;
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Read the entire pipe into memory and turn this into a memory source stream.
|
||||
*/
|
||||
static int
|
||||
vips_streami_pipe_to_memory( VipsStreami *streami )
|
||||
{
|
||||
unsigned char *data;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_pipe_to_memory:\n" );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
if( vips_streami_pipe_read_to_position( streami, -1 ) )
|
||||
return( -1 );
|
||||
|
||||
/* Move header_bytes into the memory blob and set up as a memory
|
||||
* source.
|
||||
*/
|
||||
streami->length = streami->header_bytes->len;
|
||||
data = g_byte_array_free( streami->header_bytes, FALSE );
|
||||
streami->header_bytes = NULL;
|
||||
vips_blob_set( streami->blob,
|
||||
(VipsCallbackFn) g_free, data, streami->length );
|
||||
vips_stream_close( stream );
|
||||
streami->is_pipe = FALSE;
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
const void *
|
||||
vips_streami_map( VipsStreami *streami, size_t *length_out )
|
||||
{
|
||||
VipsStreamiClass *class = VIPS_STREAMI_GET_CLASS( streami );
|
||||
|
||||
void *data;
|
||||
const void *data;
|
||||
ssize_t length;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streami_map:\n" );
|
||||
@ -715,20 +721,27 @@ vips_streami_map( VipsStreami *streami, size_t *length_out )
|
||||
/* Memory source ... easy!
|
||||
*/
|
||||
if( streami->blob ) {
|
||||
VIPS_DEBUG_MSG( " memory source\n" );
|
||||
size_t unsigned_length;
|
||||
|
||||
data = vips_blob_get( streami->blob, &length );
|
||||
/* Argh blobs are unsigned sizes.
|
||||
*/
|
||||
VIPS_DEBUG_MSG( " memory source\n" );
|
||||
data = vips_blob_get( streami->blob, &unsigned_length );
|
||||
length = VIPS_MIN( unsigned_length, G_MAXSSIZE );
|
||||
}
|
||||
else {
|
||||
size_t unsigned_length;
|
||||
|
||||
/* A streami that supports mmap.
|
||||
*/
|
||||
VIPS_DEBUG_MSG( " mmaping source\n" );
|
||||
if( !streami->baseaddr &&
|
||||
!(streami->baseaddr =
|
||||
class->map( streami, &streami->length )) )
|
||||
class->map( streami, &unsigned_length )) )
|
||||
return( NULL );
|
||||
|
||||
length = streami->length;
|
||||
length = VIPS_MIN( unsigned_length, G_MAXSSIZE );
|
||||
streami->length = length;
|
||||
data = streami->baseaddr;
|
||||
}
|
||||
|
||||
@ -828,6 +841,38 @@ vips_streami_minimise( VipsStreami *streami )
|
||||
vips_streami_sanity( streami );
|
||||
}
|
||||
|
||||
int
|
||||
vips_streami_unminimise( VipsStreami *streami )
|
||||
{
|
||||
int result;
|
||||
|
||||
VipsStreamiClass *class = VIPS_STREAMI_GET_CLASS( streami );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
result = class->unminimise( streami );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
gint64
|
||||
vips_streami_size( VipsStreami *streami )
|
||||
{
|
||||
VipsStreamiClass *class = VIPS_STREAMI_GET_CLASS( streami );
|
||||
|
||||
gint64 size;
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
size = class->size( streami );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
return( size );
|
||||
}
|
||||
|
||||
int
|
||||
vips_streami_decode( VipsStreami *streami )
|
||||
{
|
||||
@ -846,7 +891,7 @@ vips_streami_decode( VipsStreami *streami )
|
||||
|
||||
/* Make sure we are open, in case we've been minimised.
|
||||
*/
|
||||
if( vips_streami_open( streami ) )
|
||||
if( vips_streami_unminimise( streami ) )
|
||||
return( -1 );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
@ -885,22 +930,3 @@ vips_streami_sniff( VipsStreami *streami, size_t length )
|
||||
|
||||
return( streami->sniff->data );
|
||||
}
|
||||
|
||||
gint64
|
||||
vips_streami_size( VipsStreami *streami )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( streami );
|
||||
|
||||
gint64 size;
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
if( streami->length == -1 &&
|
||||
streami->is_pipe &&
|
||||
vips_streami_pipe_to_memory( streami ) )
|
||||
return( -1 );
|
||||
|
||||
vips_streami_sanity( streami );
|
||||
|
||||
return( streami->length );
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ vips_streamo_new_memory( void )
|
||||
int
|
||||
vips_streamo_write( VipsStreamo *streamo, const void *data, size_t length )
|
||||
{
|
||||
VipsStreamoClass *class = VIPS_STREAMO_GET_CLASS( stream );
|
||||
VipsStreamoClass *class = VIPS_STREAMO_GET_CLASS( streamo );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_streamo_write: %zd bytes\n", length );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user