add streamo_steal

and start converting some old dbuf code
This commit is contained in:
John Cupitt 2019-11-19 06:47:24 +00:00
parent c7f622d646
commit a129cef9dd
4 changed files with 111 additions and 36 deletions

View File

@ -268,8 +268,7 @@ vips_g_input_stream_skip( GInputStream *stream, gsize count,
GCancellable *cancellable, GError **error ) GCancellable *cancellable, GError **error )
{ {
VipsStreami *streami; VipsStreami *streami;
goffset start; gssize position;
goffset end;
streami = VIPS_G_INPUT_STREAM( stream )->streami; streami = VIPS_G_INPUT_STREAM( stream )->streami;
@ -278,8 +277,8 @@ vips_g_input_stream_skip( GInputStream *stream, gsize count,
if( g_cancellable_set_error_if_cancelled( cancellable, error ) ) if( g_cancellable_set_error_if_cancelled( cancellable, error ) )
return( -1 ); return( -1 );
start = vips_streami_seek( streami, count, SEEK_CUR ); position = vips_streami_seek( streami, count, SEEK_CUR );
if( start == -1 ) { if( position == -1 ) {
g_set_error( error, G_IO_ERROR, g_set_error( error, G_IO_ERROR,
G_IO_ERROR_FAILED, G_IO_ERROR_FAILED,
_( "Error while seeking: %s" ), _( "Error while seeking: %s" ),
@ -287,7 +286,7 @@ vips_g_input_stream_skip( GInputStream *stream, gsize count,
return( -1 ); return( -1 );
} }
return( count ); return( position );
} }
static gboolean static gboolean

View File

@ -241,6 +241,10 @@ typedef struct _VipsStreamo {
/*< private >*/ /*< private >*/
/* The stream has been finished and can no longer be written.
*/
gboolean finished;
/* Write memory output here. /* Write memory output here.
*/ */
GByteArray *memory; GByteArray *memory;
@ -278,16 +282,19 @@ VipsStreamo *vips_streamo_new_to_filename( const char *filename );
VipsStreamo *vips_streamo_new_to_memory( void ); VipsStreamo *vips_streamo_new_to_memory( void );
int vips_streamo_write( VipsStreamo *streamo, const void *data, size_t length ); int vips_streamo_write( VipsStreamo *streamo, const void *data, size_t length );
void vips_streamo_finish( VipsStreamo *streamo ); void vips_streamo_finish( VipsStreamo *streamo );
unsigned char *vips_streamo_steal( VipsStreamo *streamo, size_t *length );
char *vips_streamo_steal_text( VipsStreamo *streamo );
int vips_streamo_putc( VipsStreamo *streamo, int ch ); int vips_streamo_putc( VipsStreamo *streamo, int ch );
#define VIPS_STREAMO_PUTC( S, C ) ( \ #define VIPS_STREAMO_PUTC( S, C ) ( \
(S)->write_point <= VIPS_STREAMO_BUFFER_SIZE ? \ (S)->write_point < VIPS_STREAMO_BUFFER_SIZE ? \
((S)->output_buffer[(S)->write_point++] = (C), 0) : \ ((S)->output_buffer[(S)->write_point++] = (C), 0) : \
vips_streamo_putc( (S), (C) ) \ vips_streamo_putc( (S), (C) ) \
) )
int vips_streamo_writes( VipsStreamo *streamo, const char *str ); int vips_streamo_writes( VipsStreamo *streamo, const char *str );
int vips_streamo_writef( VipsStreamo *streamo, const char *fmt, ... ) int vips_streamo_writef( VipsStreamo *streamo, const char *fmt, ... )
__attribute__((format(printf, 2, 3))); __attribute__((format(printf, 2, 3)));
int vips_streamo_write_amp( VipsStreamo *streamo, const char *str );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -293,6 +293,9 @@ vips_streamo_write_unbuffered( VipsStreamo *streamo,
{ {
VipsStreamoClass *class = VIPS_STREAMO_GET_CLASS( streamo ); VipsStreamoClass *class = VIPS_STREAMO_GET_CLASS( streamo );
if( streamo->finished )
return( 0 );
if( streamo->memory ) if( streamo->memory )
g_byte_array_append( streamo->memory, data, length ); g_byte_array_append( streamo->memory, data, length );
else else
@ -375,7 +378,10 @@ vips_streamo_write( VipsStreamo *streamo, const void *buffer, size_t length )
* @buffer: bytes to write * @buffer: bytes to write
* @length: length of @buffer in bytes * @length: length of @buffer in bytes
* *
* Call this at the end of write to make the stream do any cleaning up. * Call this at the end of write to make the stream do any cleaning up. You
* can call it many times.
*
* After a streamo has been finished, further writes will do nothing.
*/ */
void void
vips_streamo_finish( VipsStreamo *streamo ) vips_streamo_finish( VipsStreamo *streamo )
@ -384,6 +390,9 @@ vips_streamo_finish( VipsStreamo *streamo )
VIPS_DEBUG_MSG( "vips_streamo_finish:\n" ); VIPS_DEBUG_MSG( "vips_streamo_finish:\n" );
if( streamo->finished )
return;
(void) vips_streamo_flush( streamo ); (void) vips_streamo_flush( streamo );
/* Move the stream buffer into the blob so it can be read out. /* Move the stream buffer into the blob so it can be read out.
@ -400,6 +409,69 @@ vips_streamo_finish( VipsStreamo *streamo )
} }
else else
class->finish( streamo ); class->finish( streamo );
streamo->finished = TRUE;
}
/**
* vips_streamo_steal:
* @streamo: output stream to operate on
* @length: return number of bytes of data
*
* Memory streams only (see vips_streamo_new_to_memory()). Steal all data
* written to the stream so far, and finish it.
*
* You must free the returned pointer with g_free().
*
* The data is NOT automatically null-terminated. vips_streamo_putc() a '\0'
* before calling this to get a null-terminated string.
*
* Returns: (array length=length) (element-type guint8) (transfer full): the
* data
*/
unsigned char *
vips_streamo_steal( VipsStreamo *streamo, size_t *length )
{
unsigned char *data;
(void) vips_streamo_flush( streamo );
if( !streamo->memory ||
streamo->finished ) {
if( length )
*length = streamo->memory->len;
return( NULL );
}
if( length )
*length = streamo->memory->len;
data = g_byte_array_free( streamo->memory, FALSE );
streamo->memory = NULL;
/* We must have a valid byte array or finish will fail.
*/
streamo->memory = g_byte_array_new();
vips_streamo_finish( streamo );
return( data );
}
/**
* vips_streamo_steal_text:
* @streamo: output stream to operate on
*
* As vips_streamo_steal_text(), but return a null-terminated string.
*
* Returns: (transfer full): stream contents as a null-terminated string.
*/
char *
vips_streamo_steal_text( VipsStreamo *streamo )
{
vips_streamo_putc( streamo, '\0' );
return( (char *) vips_streamo_steal( streamo, NULL ) );
} }
/** /**
@ -417,7 +489,7 @@ vips_streamo_putc( VipsStreamo *streamo, int ch )
{ {
VIPS_DEBUG_MSG( "vips_streamo_putc: %d\n", ch ); VIPS_DEBUG_MSG( "vips_streamo_putc: %d\n", ch );
if( streamo->write_point > VIPS_STREAMO_BUFFER_SIZE && if( streamo->write_point >= VIPS_STREAMO_BUFFER_SIZE &&
vips_streamo_flush( streamo ) ) vips_streamo_flush( streamo ) )
return( -1 ); return( -1 );
@ -504,27 +576,24 @@ vips_streamo_write_amp( VipsStreamo *streamo, const char *str )
* control characters, so we can use them -- thanks * control characters, so we can use them -- thanks
* electroly. * electroly.
*/ */
if( !vips_streamo_writef( streamo, if( vips_streamo_writef( streamo,
"&#x%04x;", 0x2400 + *p ) ) "&#x%04x;", 0x2400 + *p ) )
return( -1 ); return( -1 );
} }
else if( *p == '<' ) { else if( *p == '<' ) {
if( !vips_streamo_write( streamo, if( vips_streamo_writes( streamo, "&lt;" ) )
(guchar *) "&lt;", 4 ) )
return( -1 ); return( -1 );
} }
else if( *p == '>' ) { else if( *p == '>' ) {
if( !vips_streamo_write( streamo, if( vips_streamo_writes( streamo, "&gt;" ) )
(guchar *) "&gt;", 4 ) )
return( -1 ); return( -1 );
} }
else if( *p == '&' ) { else if( *p == '&' ) {
if( !vips_streamo_write( streamo, if( vips_streamo_writes( streamo, "&amp;" ) )
(guchar *) "&amp;", 5 ) )
return( -1 ); return( -1 );
} }
else { else {
if( !vips_streamo_putc( streamo, *p ) ) if( VIPS_STREAMO_PUTC( streamo, *p ) )
return( -1 ); return( -1 );
} }

View File

@ -912,7 +912,7 @@ static void *
vips__xml_properties_meta( VipsImage *image, vips__xml_properties_meta( VipsImage *image,
const char *field, GValue *value, void *a ) const char *field, GValue *value, void *a )
{ {
VipsDbuf *dbuf = (VipsDbuf *) a; VipsStreamo *streamo = (VipsStreamo *) a;
GType type = G_VALUE_TYPE( value ); GType type = G_VALUE_TYPE( value );
const char *str; const char *str;
@ -928,19 +928,19 @@ vips__xml_properties_meta( VipsImage *image,
if( !g_value_transform( value, &save_value ) ) { if( !g_value_transform( value, &save_value ) ) {
vips_error( "VipsImage", "%s", vips_error( "VipsImage", "%s",
_( "error transforming to save format" ) ); _( "error transforming to save format" ) );
return( dbuf ); return( streamo );
} }
str = vips_value_get_save_string( &save_value ); str = vips_value_get_save_string( &save_value );
vips_dbuf_writef( dbuf, " <property>\n" ); vips_streamo_writef( streamo, " <property>\n" );
vips_dbuf_writef( dbuf, " <name>" ); vips_streamo_writef( streamo, " <name>" );
vips_dbuf_write_amp( dbuf, field ); vips_streamo_write_amp( streamo, field );
vips_dbuf_writef( dbuf, "</name>\n" ); vips_streamo_writef( streamo, "</name>\n" );
vips_dbuf_writef( dbuf, " <value type=\"%s\">", vips_streamo_writef( streamo, " <value type=\"%s\">",
g_type_name( type ) ); g_type_name( type ) );
vips_dbuf_write_amp( dbuf, str ); vips_streamo_write_amp( streamo, str );
vips_dbuf_writef( dbuf, "</value>\n" ); vips_streamo_writef( streamo, "</value>\n" );
vips_dbuf_writef( dbuf, " </property>\n" ); vips_streamo_writef( streamo, " </property>\n" );
g_value_unset( &save_value ); g_value_unset( &save_value );
} }
@ -954,31 +954,31 @@ vips__xml_properties_meta( VipsImage *image,
char * char *
vips__xml_properties( VipsImage *image ) vips__xml_properties( VipsImage *image )
{ {
VipsDbuf dbuf; VipsStreamo *streamo;
char *date; char *date;
date = vips__get_iso8601(); date = vips__get_iso8601();
vips_dbuf_init( &dbuf ); streamo = vips_streamo_new_to_memory();
vips_dbuf_writef( &dbuf, "<?xml version=\"1.0\"?>\n" ); vips_streamo_writef( streamo, "<?xml version=\"1.0\"?>\n" );
vips_dbuf_writef( &dbuf, "<image xmlns=\"%s/dzsave\" " vips_streamo_writef( streamo, "<image xmlns=\"%s/dzsave\" "
"date=\"%s\" version=\"%d.%d.%d\">\n", "date=\"%s\" version=\"%d.%d.%d\">\n",
NAMESPACE_URI, NAMESPACE_URI,
date, date,
VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION ); VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
vips_dbuf_writef( &dbuf, " <properties>\n" ); vips_streamo_writef( streamo, " <properties>\n" );
g_free( date ); g_free( date );
if( vips_image_map( image, vips__xml_properties_meta, &dbuf ) ) { if( vips_image_map( image, vips__xml_properties_meta, streamo ) ) {
vips_dbuf_destroy( &dbuf ); VIPS_UNREF( streamo );
return( NULL ); return( NULL );
} }
vips_dbuf_writef( &dbuf, " </properties>\n" ); vips_streamo_writef( streamo, " </properties>\n" );
vips_dbuf_writef( &dbuf, "</image>\n" ); vips_streamo_writef( streamo, "</image>\n" );
return( (char *) vips_dbuf_steal( &dbuf, NULL ) ); return( vips_streamo_steal_text( streamo ) );
} }
/* Append XML to output fd. /* Append XML to output fd.