diff --git a/ChangeLog b/ChangeLog index 1bfa0670..95f4e4dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,7 +17,7 @@ - nifti load/save uses double for all floating point metadata - add vips_error_buffer_copy() - add VipsStream: a universal IO class for loaders and savers -- jpeg, png, tiff and webp use the new IO class +- jpeg, png, tiff (though not tiffsave), rad and webp use the new IO class - add @no_strip option to dzsave [kalozka1] 31/8/19 started 8.8.3 diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index c9047216..a8166262 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -27,6 +27,8 @@ * 23/7/18 * - fix a buffer overflow for incorrectly coded old-style RLE * [HongxuChen] + * 6/11/19 + * - revise for VipsStream */ /* @@ -608,8 +610,6 @@ scanline_read( VipsStreamib *streamib, COLR *scanline, int width ) run = code > 128; len = run ? code & 127 : code; - printf( "len = %d\n", len ); - if( j + len > width ) { vips_error( "rad2vips", "%s", _( "overrun" ) ); return( -1 ); @@ -953,6 +953,9 @@ vips__rad_load( VipsStreami *streami, VipsImage *out ) vips_image_write( t[1], out ) ) return( -1 ); + if( vips_streami_decode( streami ) ) + return( -1 ); + return( 0 ); } diff --git a/libvips/include/vips/stream.h b/libvips/include/vips/stream.h index b9179d69..a934bb69 100644 --- a/libvips/include/vips/stream.h +++ b/libvips/include/vips/stream.h @@ -251,10 +251,13 @@ typedef struct _VipsStreamib { /* The +1 means there's always a \0 byte at the end. * * Unsigned char, since we don't want >127 to be -ve. + * + * chars_in_buffer is how many chars we have in input_buffer, + * read_point is the current read position in that buffer. */ unsigned char input_buffer[VIPS_STREAMIB_BUFFER_SIZE + 1]; - unsigned char *read_point; - int chars_unread; + int chars_in_buffer; + int read_point; /* Build lines of text here. */ @@ -275,20 +278,20 @@ void vips_streamib_unbuffer( VipsStreamib *streamib ); int vips_streamib_getc( VipsStreamib *streamib ); #define VIPS_STREAMIB_GETC( S ) ( \ - (S)->chars_unread > 0 ? \ - ((S)->chars_unread--, ((S)->read_point++)[0]) : \ + (S)->read_point < (S)->chars_in_buffer ? \ + (S)->input_buffer[(S)->read_point++] : \ vips_streamib_getc( S ) \ ) void vips_streamib_ungetc( VipsStreamib *streamib ); int vips_streamib_require( VipsStreamib *streamib, int require ); #define VIPS_STREAMIB_REQUIRE( S, R ) ( \ - (R) > (S)->chars_unread ? \ + (S)->read_point + (R) <= (S)->chars_in_buffer ? \ 0 : \ vips_streamib_require( (S), (R) ) \ ) -#define VIPS_STREAMIB_PEEK( S ) ((S)->read_point) -#define VIPS_STREAMIB_FETCH( S ) ((S)->chars_unread--, ((S)->read_point++)[0]) +#define VIPS_STREAMIB_PEEK( S ) ((S)->input_buffer + (S)->read_point) +#define VIPS_STREAMIB_FETCH( S ) ((S)->input_buffer[(S)->read_point++]) const unsigned char *vips_streamib_get_line( VipsStreamib *streamib ); unsigned char *vips_streamib_get_line_copy( VipsStreamib *streamib ); diff --git a/libvips/iofuncs/streamib.c b/libvips/iofuncs/streamib.c index 86e8bc26..65debaed 100644 --- a/libvips/iofuncs/streamib.c +++ b/libvips/iofuncs/streamib.c @@ -90,9 +90,9 @@ vips_streamib_class_init( VipsStreamibClass *class ) static void vips_streamib_init( VipsStreamib *streamib ) { - streamib->read_point = streamib->input_buffer; - streamib->chars_unread = 0; - streamib->read_point[streamib->chars_unread] = '\0'; + streamib->read_point = 0; + streamib->chars_in_buffer = 0; + streamib->input_buffer[0] = '\0'; } /** @@ -130,12 +130,12 @@ vips_streamib_new( VipsStreami *streami ) void vips_streamib_unbuffer( VipsStreamib *streamib ) { - int bytes_in_buffer = streamib->read_point - streamib->input_buffer; - - streamib->read_point = streamib->input_buffer; - streamib->chars_unread = 0; + /* We'd read ahead a little way -- seek backwards by that amount. + */ vips_streami_seek( streamib->streami, - -bytes_in_buffer, SEEK_SET ); + streamib->read_point - streamib->chars_in_buffer, SEEK_SET ); + streamib->read_point = 0; + streamib->chars_in_buffer = 0; } /* Returns -1 on error, 0 on EOF, otherwise bytes read. @@ -147,20 +147,20 @@ vips_streamib_refill( VipsStreamib *streamib ) /* We should not discard any unread bytes. */ - g_assert( streamib->chars_unread == 0 ); + g_assert( streamib->read_point == streamib->chars_in_buffer ); bytes_read = vips_streami_read( streamib->streami, streamib->input_buffer, VIPS_STREAMIB_BUFFER_SIZE ); if( bytes_read == -1 ) return( -1 ); - streamib->read_point = streamib->input_buffer; - streamib->chars_unread = bytes_read; + streamib->read_point = 0; + streamib->chars_in_buffer = bytes_read; /* Always add a null byte so we can use strchr() etc. on lines. This is * safe because input_buffer is VIPS_STREAMIB_BUFFER_SIZE + 1 bytes. */ - streamib->read_point[bytes_read] = '\0'; + streamib->input_buffer[bytes_read] = '\0'; return( bytes_read ); } @@ -178,18 +178,13 @@ vips_streamib_refill( VipsStreamib *streamib ) int vips_streamib_getc( VipsStreamib *streamib ) { - int ch; - - if( streamib->chars_unread == 0 && + if( streamib->read_point == streamib->chars_in_buffer && vips_streamib_refill( streamib ) <= 0 ) return( -1 ); - ch = streamib->read_point[0]; + g_assert( streamib->read_point < streamib->chars_in_buffer ); - streamib->read_point += 1; - streamib->chars_unread -= 1; - - return( ch ); + return( streamib->input_buffer[streamib->read_point++] ); } /** @@ -213,10 +208,8 @@ vips_streamib_getc( VipsStreamib *streamib ) void vips_streamib_ungetc( VipsStreamib *streamib ) { - if( streamib->read_point > streamib->input_buffer ) { + if( streamib->read_point > 0 ) streamib->read_point -= 1; - streamib->chars_unread += 1; - } } /** @@ -232,31 +225,31 @@ int vips_streamib_require( VipsStreamib *streamib, int require ) { g_assert( require < VIPS_STREAMIB_BUFFER_SIZE ); - g_assert( streamib->chars_unread >= 0 ); - g_assert( streamib->chars_unread <= VIPS_STREAMIB_BUFFER_SIZE ); - g_assert( streamib->read_point >= streamib->input_buffer ); - g_assert( streamib->read_point < - streamib->input_buffer + VIPS_STREAMIB_BUFFER_SIZE ); + g_assert( streamib->chars_in_buffer >= 0 ); + g_assert( streamib->chars_in_buffer <= VIPS_STREAMIB_BUFFER_SIZE ); + g_assert( streamib->read_point >= 0 ); + g_assert( streamib->read_point <= streamib->chars_in_buffer ); - if( require > streamib->chars_unread ) { - /* Areas can overlap. + if( streamib->read_point + require > streamib->chars_in_buffer ) { + /* Areas can overlap, so we must memmove(). */ memmove( streamib->input_buffer, - streamib->read_point, streamib->chars_unread ); - streamib->read_point = streamib->input_buffer; + streamib->input_buffer + streamib->read_point, + streamib->chars_in_buffer - streamib->read_point ); + streamib->chars_in_buffer -= streamib->read_point; + streamib->read_point = 0; - while( require > streamib->chars_unread ) { - unsigned char *q = streamib->input_buffer + - streamib->chars_unread; + while( require > streamib->chars_in_buffer ) { + unsigned char *to = streamib->input_buffer + + streamib->chars_in_buffer; int space_available = VIPS_STREAMIB_BUFFER_SIZE - - streamib->chars_unread; + streamib->chars_in_buffer; size_t bytes_read; if( (bytes_read = vips_streami_read( streamib->streami, - q, space_available )) == -1 ) + to, space_available )) == -1 ) return( -1 ); - streamib->chars_unread += bytes_read; if( bytes_read == 0 ) { vips_error( vips_stream_nick( VIPS_STREAM( @@ -264,6 +257,9 @@ vips_streamib_require( VipsStreamib *streamib, int require ) "%s", _( "end of file" ) ); return( -1 ); } + + to[bytes_read] = '\0'; + streamib->chars_in_buffer += bytes_read; } } @@ -323,26 +319,26 @@ vips_streamib_require( VipsStreamib *streamib, int require ) const unsigned char * vips_streamib_get_line( VipsStreamib *streamib ) { - unsigned char *write_point; + int write_point; int space_remaining; int ch; - write_point = streamib->line; + write_point = 0; space_remaining = VIPS_STREAMIB_BUFFER_SIZE; while( (ch = VIPS_STREAMIB_GETC( streamib )) != -1 && ch != '\n' && space_remaining > 0 ) { - write_point[0] = ch; + streamib->line[write_point] = ch; write_point += 1; space_remaining -= 1; } - write_point[0] = '\0'; + streamib->line[write_point] = '\0'; /* If we hit EOF immediately, return EOF. */ if( ch == -1 && - write_point == streamib->line ) + write_point == 0 ) return( NULL ); /* If the final char in the buffer is \r, this is probably a DOS file @@ -351,9 +347,9 @@ vips_streamib_get_line( VipsStreamib *streamib ) * There's a chance this could incorrectly remove \r in very long * lines, but ignore this. */ - if( write_point - streamib->line > 0 && - write_point[-1] == '\r' ) - write_point[-1] = '\0'; + if( write_point > 0 && + streamib->line[write_point - 1] == '\r' ) + streamib->line[write_point - 1] = '\0'; /* If we filled the output line without seeing \n, keep going to the * next \n. @@ -400,6 +396,8 @@ vips_streamib_get_line_copy( VipsStreamib *streamib ) g_byte_array_append( buffer, &c, 1 ); } + /* Immediate EOF. + */ if( ch == -1 && buffer->len == 0 ) { VIPS_FREEF( g_byte_array_unref, buffer );