diff --git a/libvips/foreign/tiff.c b/libvips/foreign/tiff.c index e6900cea..07720a15 100644 --- a/libvips/foreign/tiff.c +++ b/libvips/foreign/tiff.c @@ -1,4 +1,4 @@ -/* Some shared TIFF utilities. +/* Some shared TIFF utilities. * * 14/10/16 * - from vips2tiff.c @@ -10,7 +10,7 @@ /* This file is part of VIPS. - + VIPS is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -34,7 +34,7 @@ */ -/* +/* #define DEBUG */ @@ -62,7 +62,7 @@ /* Handle TIFF errors here. Shared with vips2tiff.c. These can be called from * more than one thread. */ -static void +static void vips__thandler_error( const char *module, const char *fmt, va_list ap ) { vips_verror( module, fmt, ap ); @@ -71,7 +71,7 @@ vips__thandler_error( const char *module, const char *fmt, va_list ap ) /* It'd be nice to be able to support the @fail option for the tiff loader, but * there's no easy way to do this, since libtiff has a global warning handler. */ -static void +static void vips__thandler_warning( const char *module, const char *fmt, va_list ap ) { g_logv( G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, fmt, ap ); @@ -106,22 +106,22 @@ vips__tiff_openout( const char *path, gboolean bigtiff ) GError *error = NULL; wchar_t *path16; - if( !(path16 = (wchar_t *) - g_utf8_to_utf16( path, -1, NULL, NULL, &error )) ) { + if( !(path16 = (wchar_t *) + g_utf8_to_utf16( path, -1, NULL, NULL, &error )) ) { vips_g_error( &error ); return( NULL ); } tif = TIFFOpenW( path16, mode ); - g_free( path16 ); + g_free( path16 ); } #else /*!OS_WIN32*/ tif = TIFFOpen( path, mode ); #endif /*OS_WIN32*/ if( !tif ) { - vips_error( "tiff", + vips_error( "tiff", _( "unable to open \"%s\" for output" ), path ); return( NULL ); } @@ -129,7 +129,7 @@ vips__tiff_openout( const char *path, gboolean bigtiff ) return( tif ); } -/* Open TIFF for input from a file. +/* Open TIFF for input from a file. */ TIFF * vips__tiff_openin( const char *path ) @@ -142,7 +142,7 @@ vips__tiff_openin( const char *path ) TIFF *tif; #ifdef DEBUG - printf( "vips__tiff_openin( \"%s\" )\n", path ); + printf( "vips__tiff_openin( \"%s\" )\n", path ); #endif /*DEBUG*/ /* Need the utf-16 version on Windows. @@ -152,22 +152,22 @@ vips__tiff_openin( const char *path ) GError *error = NULL; wchar_t *path16; - if( !(path16 = (wchar_t *) - g_utf8_to_utf16( path, -1, NULL, NULL, &error )) ) { + if( !(path16 = (wchar_t *) + g_utf8_to_utf16( path, -1, NULL, NULL, &error )) ) { vips_g_error( &error ); return( NULL ); } tif = TIFFOpenW( path16, mode ); - g_free( path16 ); + g_free( path16 ); } #else /*!OS_WIN32*/ tif = TIFFOpen( path, mode ); #endif /*OS_WIN32*/ if( !tif ) { - vips_error( "tiff", + vips_error( "tiff", _( "unable to open \"%s\" for input" ), path ); return( NULL ); } @@ -175,7 +175,7 @@ vips__tiff_openin( const char *path ) return( tif ); } -/* TIFF input from a memory buffer. +/* TIFF input from a memory buffer. */ typedef struct _VipsTiffOpeninBuffer { @@ -184,7 +184,7 @@ typedef struct _VipsTiffOpeninBuffer { size_t length; } VipsTiffOpeninBuffer; -static tsize_t +static tsize_t openin_buffer_read( thandle_t st, tdata_t data, tsize_t size ) { VipsTiffOpeninBuffer *buffer = (VipsTiffOpeninBuffer *) st; @@ -193,38 +193,38 @@ openin_buffer_read( thandle_t st, tdata_t data, tsize_t size ) size_t copied; if( buffer->position > buffer->length ) { - vips_error( "openin_buffer_read", + vips_error( "openin_buffer_read", "%s", _( "read beyond end of buffer" ) ); return( 0 ); } available = buffer->length - buffer->position; copied = VIPS_MIN( size, available ); - memcpy( data, + memcpy( data, (unsigned char *) buffer->data + buffer->position, copied ); buffer->position += copied; - return( copied ); + return( copied ); } -static tsize_t +static tsize_t openin_buffer_write( thandle_t st, tdata_t buffer, tsize_t size ) { - g_assert_not_reached(); + g_assert_not_reached(); - return( 0 ); + return( 0 ); } -static int +static int openin_buffer_close( thandle_t st ) { return( 0 ); } -/* After calling this, ->pos is not bound by the size of the buffer, it can +/* After calling this, ->pos is not bound by the size of the buffer, it can * have any positive value. */ -static toff_t +static toff_t openin_buffer_seek( thandle_t st, toff_t position, int whence ) { VipsTiffOpeninBuffer *buffer = (VipsTiffOpeninBuffer *) st; @@ -236,31 +236,31 @@ openin_buffer_seek( thandle_t st, toff_t position, int whence ) else if( whence == SEEK_END ) buffer->position = buffer->length + position; else - g_assert_not_reached(); + g_assert_not_reached(); - return( buffer->position ); + return( buffer->position ); } -static toff_t +static toff_t openin_buffer_size( thandle_t st ) { VipsTiffOpeninBuffer *buffer = (VipsTiffOpeninBuffer *) st; - return( buffer->length ); + return( buffer->length ); } -static int +static int openin_buffer_map( thandle_t st, tdata_t *start, toff_t *len ) { - g_assert_not_reached(); + g_assert_not_reached(); return( 0 ); } -static void +static void openin_buffer_unmap( thandle_t st, tdata_t start, toff_t len ) { - g_assert_not_reached(); + g_assert_not_reached(); return; } @@ -272,7 +272,7 @@ vips__tiff_openin_buffer( VipsImage *image, const void *data, size_t length ) TIFF *tiff; #ifdef DEBUG - printf( "vips__tiff_openin_buffer:\n" ); + printf( "vips__tiff_openin_buffer:\n" ); #endif /*DEBUG*/ buffer = VIPS_NEW( image, VipsTiffOpeninBuffer ); @@ -282,26 +282,26 @@ vips__tiff_openin_buffer( VipsImage *image, const void *data, size_t length ) if( !(tiff = TIFFClientOpen( "memory input", "rm", (thandle_t) buffer, - openin_buffer_read, - openin_buffer_write, - openin_buffer_seek, - openin_buffer_close, - openin_buffer_size, - openin_buffer_map, - openin_buffer_unmap )) ) { - vips_error( "vips__tiff_openin_buffer", "%s", + openin_buffer_read, + openin_buffer_write, + openin_buffer_seek, + openin_buffer_close, + openin_buffer_size, + openin_buffer_map, + openin_buffer_unmap )) ) { + vips_error( "vips__tiff_openin_buffer", "%s", _( "unable to open memory buffer for input" ) ); return( NULL ); } - return( tiff ); + return( tiff ); } -/* TIFF output to a memory buffer. +/* TIFF output to a memory buffer. */ typedef struct _VipsTiffOpenoutBuffer { - VipsDbuf dbuf; + VipsDbuf dbuf; /* On close, consolidate and write the output here. */ @@ -309,91 +309,96 @@ typedef struct _VipsTiffOpenoutBuffer { size_t *out_length; } VipsTiffOpenoutBuffer; -static tsize_t +static tsize_t openout_buffer_read( thandle_t st, tdata_t data, tsize_t size ) { VipsTiffOpenoutBuffer *buffer = (VipsTiffOpenoutBuffer *) st; - off_t write_point; - size_t available; - unsigned char *from; +#ifdef DEBUG + printf( "openout_buffer_read: %zd bytes\n", size ); +#endif /*DEBUG*/ - write_point = vips_dbuf_tell( &buffer->dbuf ); - from = vips_dbuf_get_write( &buffer->dbuf, &available ); - vips_dbuf_seek( &buffer->dbuf, write_point, SEEK_SET ); - - if( available < size ) { - vips_error( "openout_buffer_read", - "%s", _( "read beyond end of buffer" ) ); - return( 0 ); - } - - memcpy( data, from, size ); - - vips_dbuf_seek( &buffer->dbuf, size, SEEK_CUR ); - return( size ); + return( vips_dbuf_read( &buffer->dbuf, data, size ) ); } -static tsize_t +static tsize_t openout_buffer_write( thandle_t st, tdata_t data, tsize_t size ) { VipsTiffOpenoutBuffer *buffer = (VipsTiffOpenoutBuffer *) st; #ifdef DEBUG - printf( "openout_buffer_write: %zd bytes\n", size ); + printf( "openout_buffer_write: %zd bytes\n", size ); #endif /*DEBUG*/ - vips_dbuf_write( &buffer->dbuf, data, size ); + vips_dbuf_write( &buffer->dbuf, data, size ); - return( size ); + return( size ); } -static int +static int openout_buffer_close( thandle_t st ) { VipsTiffOpenoutBuffer *buffer = (VipsTiffOpenoutBuffer *) st; - *(buffer->out_data) = vips_dbuf_steal( &buffer->dbuf, + *(buffer->out_data) = vips_dbuf_steal( &buffer->dbuf, buffer->out_length); return( 0 ); } -static toff_t +static toff_t openout_buffer_seek( thandle_t st, toff_t position, int whence ) { VipsTiffOpenoutBuffer *buffer = (VipsTiffOpenoutBuffer *) st; #ifdef DEBUG - printf( "openout_buffer_seek: position %zd, whence %d\n", - position, whence ); + printf( "openout_buffer_seek: position %zd, whence %d ", + position, whence ); + switch( whence ) { + case SEEK_SET: + printf( "set" ); + break; + + case SEEK_END: + printf( "end" ); + break; + + case SEEK_CUR: + printf( "cur" ); + break; + + default: + printf( "unknown" ); + break; + } + printf( "\n" ); #endif /*DEBUG*/ - vips_dbuf_seek( &buffer->dbuf, position, whence ); + vips_dbuf_seek( &buffer->dbuf, position, whence ); - return( vips_dbuf_tell( &buffer->dbuf ) ); + return( vips_dbuf_tell( &buffer->dbuf ) ); } -static toff_t +static toff_t openout_buffer_size( thandle_t st ) { - g_assert_not_reached(); - - return( 0 ); -} - -static int -openout_buffer_map( thandle_t st, tdata_t *start, toff_t *len ) -{ - g_assert_not_reached(); + g_assert_not_reached(); return( 0 ); } -static void +static int +openout_buffer_map( thandle_t st, tdata_t *start, toff_t *len ) +{ + g_assert_not_reached(); + + return( 0 ); +} + +static void openout_buffer_unmap( thandle_t st, tdata_t start, toff_t len ) { - g_assert_not_reached(); + g_assert_not_reached(); return; } @@ -401,7 +406,7 @@ openout_buffer_unmap( thandle_t st, tdata_t start, toff_t len ) /* On TIFFClose(), @data and @length are set to point to the output buffer. */ TIFF * -vips__tiff_openout_buffer( VipsImage *image, +vips__tiff_openout_buffer( VipsImage *image, gboolean bigtiff, void **out_data, size_t *out_length ) { const char *mode = bigtiff ? "w8" : "w"; @@ -410,29 +415,29 @@ vips__tiff_openout_buffer( VipsImage *image, TIFF *tiff; #ifdef DEBUG - printf( "vips__tiff_openout_buffer:\n" ); + printf( "vips__tiff_openout_buffer:\n" ); #endif /*DEBUG*/ buffer = VIPS_NEW( image, VipsTiffOpenoutBuffer ); - vips_dbuf_init( &buffer->dbuf ); + vips_dbuf_init( &buffer->dbuf ); buffer->out_data = out_data; buffer->out_length = out_length; - if( !(tiff = TIFFClientOpen( "memory output", mode, + if( !(tiff = TIFFClientOpen( "memory output", mode, (thandle_t) buffer, - openout_buffer_read, - openout_buffer_write, - openout_buffer_seek, - openout_buffer_close, - openout_buffer_size, - openout_buffer_map, - openout_buffer_unmap )) ) { - vips_error( "vips__tiff_openout_buffer", "%s", + openout_buffer_read, + openout_buffer_write, + openout_buffer_seek, + openout_buffer_close, + openout_buffer_size, + openout_buffer_map, + openout_buffer_unmap )) ) { + vips_error( "vips__tiff_openout_buffer", "%s", _( "unable to open memory buffer for output" ) ); return( NULL ); } - return( tiff ); + return( tiff ); } #endif /*HAVE_TIFF*/ diff --git a/libvips/include/vips/dbuf.h b/libvips/include/vips/dbuf.h index 3234dbbe..6c8dfdcb 100644 --- a/libvips/include/vips/dbuf.h +++ b/libvips/include/vips/dbuf.h @@ -64,6 +64,7 @@ typedef struct _VipsDbuf { void vips_dbuf_destroy( VipsDbuf *buf ); void vips_dbuf_init( VipsDbuf *buf ); gboolean vips_dbuf_allocate( VipsDbuf *dbuf, size_t size ); +size_t vips_dbuf_read( VipsDbuf *dbuf, unsigned char *data, size_t size ); unsigned char *vips_dbuf_get_write( VipsDbuf *dbuf, size_t *size ); gboolean vips_dbuf_write( VipsDbuf *dbuf, const unsigned char *data, size_t size ); diff --git a/libvips/iofuncs/dbuf.c b/libvips/iofuncs/dbuf.c index aecba6da..61f78382 100644 --- a/libvips/iofuncs/dbuf.c +++ b/libvips/iofuncs/dbuf.c @@ -69,7 +69,7 @@ gboolean vips_dbuf_minimum_size( VipsDbuf *dbuf, size_t size ) { if( size > dbuf->allocated_size ) { - size_t new_allocated_size = 3 * (16 + size) / 2; + const size_t new_allocated_size = 3 * (16 + size) / 2; unsigned char *new_data; @@ -102,25 +102,26 @@ vips_dbuf_allocate( VipsDbuf *dbuf, size_t size ) } /** - * vips_dbuf_null_terminate: + * vips_dbuf_read: * @dbuf: the buffer + * @data: read to this area + * @size: read up to this many bytes * - * Make sure the byte after the last data byte is `\0`. This extra byte is not - * included in the data size and the write point is not moved. + * Up to @size bytes are read from the buffer and copied to @data. The number + * of bytes transferred is returned. * - * This makes it safe to treat the dbuf contents as a C string. - * - * Returns: %FALSE on out of memory, %TRUE otherwise. + * Returns: the number of bytes transferred. */ -static gboolean -vips_dbuf_null_terminate( VipsDbuf *dbuf ) +size_t +vips_dbuf_read( VipsDbuf *dbuf, unsigned char *data, size_t size ) { - if( !vips_dbuf_minimum_size( dbuf, dbuf->data_size + 1 ) ) - return( FALSE ); + const size_t available = dbuf->data_size - dbuf->write_point; + const size_t copied = VIPS_MIN( size, available ); - dbuf->data[dbuf->data_size] = 0; + memcpy( data, dbuf->data + dbuf->write_point, copied ); + dbuf->write_point += copied; - return( TRUE ); + return( copied ); } /** @@ -141,14 +142,14 @@ unsigned char * vips_dbuf_get_write( VipsDbuf *dbuf, size_t *size ) { unsigned char *write = dbuf->data + dbuf->write_point; - size_t length = dbuf->data + dbuf->allocated_size - write; + const size_t available = dbuf->allocated_size - dbuf->write_point; - memset( write, 0, length ); + memset( write, 0, available ); dbuf->write_point = dbuf->allocated_size; dbuf->data_size = dbuf->allocated_size; if( size ) - *size = length; + *size = available; return( write ); } @@ -310,6 +311,28 @@ vips_dbuf_tell( VipsDbuf *dbuf ) return( dbuf->write_point ); } +/** + * vips_dbuf_null_terminate: + * @dbuf: the buffer + * + * Make sure the byte after the last data byte is `\0`. This extra byte is not + * included in the data size and the write point is not moved. + * + * This makes it safe to treat the dbuf contents as a C string. + * + * Returns: %FALSE on out of memory, %TRUE otherwise. + */ +static gboolean +vips_dbuf_null_terminate( VipsDbuf *dbuf ) +{ + if( !vips_dbuf_minimum_size( dbuf, dbuf->data_size + 1 ) ) + return( FALSE ); + + dbuf->data[dbuf->data_size] = 0; + + return( TRUE ); +} + /** * vips_dbuf_steal: * @dbuf: the buffer