buffered input compiles
This commit is contained in:
parent
805da46670
commit
37049af140
@ -270,6 +270,14 @@ VipsStreamib *vips_streamib_new_from_blob( VipsBlob *blob );
|
|||||||
VipsStreamib *vips_streamib_new_from_memory( const void *data, size_t size );
|
VipsStreamib *vips_streamib_new_from_memory( const void *data, size_t size );
|
||||||
VipsStreamib *vips_streamib_new_from_options( const char *options );
|
VipsStreamib *vips_streamib_new_from_options( const char *options );
|
||||||
|
|
||||||
|
int vips_streamib_getc( VipsStreamib *streamib );
|
||||||
|
void vips_streamib_ungetc( VipsStreamib *streamib );
|
||||||
|
|
||||||
|
#define VIPS_STREAMIB_GETC( S ) ( \
|
||||||
|
(S)->bytes_remaining > 0 ? \
|
||||||
|
((S)->bytes_remaining--, ((S)->read_point++)[0]) : \
|
||||||
|
vips_streamib_getc( S ))
|
||||||
|
|
||||||
int vips_streamib_get_line( VipsStreamib *streamib, const char **line );
|
int vips_streamib_get_line( VipsStreamib *streamib, const char **line );
|
||||||
int vips_streamib_get_line_copy( VipsStreamib *streamib, char **line );
|
int vips_streamib_get_line_copy( VipsStreamib *streamib, char **line );
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ vips_streami_class_init( VipsStreamiClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "streami";
|
object_class->nickname = "streami";
|
||||||
object_class->description = _( "streami stream" );
|
object_class->description = _( "input stream" );
|
||||||
|
|
||||||
object_class->build = vips_streami_build;
|
object_class->build = vips_streami_build;
|
||||||
|
|
||||||
@ -1046,43 +1046,13 @@ vips_streami_sniff( VipsStreami *streami, size_t length )
|
|||||||
|
|
||||||
G_DEFINE_TYPE( VipsStreamib, vips_streamib, VIPS_TYPE_STREAMI );
|
G_DEFINE_TYPE( VipsStreamib, vips_streamib, VIPS_TYPE_STREAMI );
|
||||||
|
|
||||||
static void
|
|
||||||
vips_streamib_finalize( GObject *gobject )
|
|
||||||
{
|
|
||||||
VipsStreamib *streamib = VIPS_STREAMIB( gobject );
|
|
||||||
|
|
||||||
G_OBJECT_CLASS( vips_streamib_parent_class )->finalize( gobject );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
vips_streamib_build( VipsObject *object )
|
|
||||||
{
|
|
||||||
VipsStream *stream = VIPS_STREAM( object );
|
|
||||||
VipsStreamib *streamib = VIPS_STREAMIB( object );
|
|
||||||
VipsStreamibClass *class = VIPS_STREAMIB_GET_CLASS( streamib );
|
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "vips_streamib_build: %p\n", streamib );
|
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_streamib_parent_class )->
|
|
||||||
build( object ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_streamib_class_init( VipsStreamibClass *class )
|
vips_streamib_class_init( VipsStreamibClass *class )
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
|
||||||
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class );
|
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class );
|
||||||
|
|
||||||
gobject_class->finalize = vips_streamib_finalize;
|
|
||||||
|
|
||||||
object_class->nickname = "streamib";
|
object_class->nickname = "streamib";
|
||||||
object_class->description = _( "streamib stream" );
|
object_class->description = _( "buffered input stream" );
|
||||||
|
|
||||||
object_class->build = vips_streamib_build;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1090,9 +1060,12 @@ vips_streamib_init( VipsStreamib *streamib )
|
|||||||
{
|
{
|
||||||
streamib->read_point = streamib->input_buffer;
|
streamib->read_point = streamib->input_buffer;
|
||||||
streamib->bytes_remaining = 0;
|
streamib->bytes_remaining = 0;
|
||||||
|
streamib->read_point[streamib->bytes_remaining] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
/* Returns -1 on error, 0 on EOF, otherwise bytes read.
|
||||||
|
*/
|
||||||
|
static ssize_t
|
||||||
vips_streamib_refill( VipsStreamib *streamib )
|
vips_streamib_refill( VipsStreamib *streamib )
|
||||||
{
|
{
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
@ -1101,33 +1074,75 @@ vips_streamib_refill( VipsStreamib *streamib )
|
|||||||
*/
|
*/
|
||||||
g_assert( streamib->bytes_remaining == 0 );
|
g_assert( streamib->bytes_remaining == 0 );
|
||||||
|
|
||||||
streamib->read_postion = streamib->input_buffer;
|
bytes_read = vips_streami_read( VIPS_STREAMI( streamib ),
|
||||||
streamib->bytes_remaining = 0;
|
streamib->input_buffer, VIPS_STREAMIB_BUFFER_SIZE );
|
||||||
if( (bytes_read = vips_streami_read( VIPS_STREAMI( streamib ),
|
if( bytes_read == -1 )
|
||||||
streamib->read_postion, VIPS_STREAMIB_BUFFER_SIZE )) == -1 )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
streamib->read_point = streamib->input_buffer;
|
||||||
streamib->bytes_remaining = bytes_read;
|
streamib->bytes_remaining = bytes_read;
|
||||||
|
|
||||||
/* Always add a nul byte so we can use strchr() etc. on lines. This is
|
/* 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.
|
* safe because input_buffer is VIPS_STREAMIB_BUFFER_SIZE + 1 bytes.
|
||||||
*/
|
*/
|
||||||
streamib->read_postion[bytes_read] = '\0';
|
streamib->read_point[bytes_read] = '\0';
|
||||||
|
|
||||||
if( bytes_read == 0 )
|
return( bytes_read );
|
||||||
streamib->eof = TRUE;
|
}
|
||||||
|
|
||||||
return( 0 );
|
/**
|
||||||
|
* vips_streamib_getc:
|
||||||
|
* @streamib: stream to operate on
|
||||||
|
*
|
||||||
|
* Fetch the next character from the stream.
|
||||||
|
*
|
||||||
|
* Use VIPS_STREAMIB_GETC() for speed.
|
||||||
|
*
|
||||||
|
* Returns: the next char from @streamib, -1 on read error or EOF.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_streamib_getc( VipsStreamib *streamib )
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if( streamib->bytes_remaining == 0 &&
|
||||||
|
vips_streamib_refill( streamib ) <= 0 )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
ch = streamib->read_point[0];
|
||||||
|
|
||||||
|
streamib->read_point += 1;
|
||||||
|
streamib->bytes_remaining -= 1;
|
||||||
|
|
||||||
|
return( ch );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_streamib_ungetc:
|
||||||
|
* @streamib: stream to operate on
|
||||||
|
*
|
||||||
|
* The opposite of vips_streamib_getc: undo the previous getc.
|
||||||
|
*
|
||||||
|
* unget more than one character is undefined. Unget at the start of the file
|
||||||
|
* does nothing.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vips_streamib_ungetc( VipsStreamib *streamib )
|
||||||
|
{
|
||||||
|
if( streamib->read_point > streamib->input_buffer ) {
|
||||||
|
streamib->read_point -= 1;
|
||||||
|
streamib->bytes_remaining += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_streamib_get_line:
|
* vips_streamib_get_line:
|
||||||
* @streamib: stream to fetch the line from
|
* @streamib: stream to operate on
|
||||||
* @line: return the next line of text here
|
* @line: return the next line of text here
|
||||||
*
|
*
|
||||||
* Fetch the next line of text from @streamib and return in @line. The end of
|
* Fetch the next line of text from @streamib and return in @line. The end of
|
||||||
* line character (or characters, for DOS files) are removed, and and the
|
* line character (or characters, for DOS files) are removed, and @line
|
||||||
* string is terminated with a null (`\0` character).
|
* is terminated with a null (`\0` character).
|
||||||
*
|
*
|
||||||
* @line is set to NULL on end of file.
|
* @line is set to NULL on end of file.
|
||||||
*
|
*
|
||||||
@ -1144,67 +1159,53 @@ int
|
|||||||
vips_streamib_get_line( VipsStreamib *streamib, const char **line )
|
vips_streamib_get_line( VipsStreamib *streamib, const char **line )
|
||||||
{
|
{
|
||||||
char *write_point;
|
char *write_point;
|
||||||
int bytes_available;
|
int space_remaining;
|
||||||
|
int ch;
|
||||||
|
|
||||||
write_point = streamib->line;
|
write_point = streamib->line;
|
||||||
bytes_available = VIPS_STREAMIB_BUFFER_SIZE;
|
space_remaining = VIPS_STREAMIB_BUFFER_SIZE;
|
||||||
|
|
||||||
for(;;) {
|
while( (ch = VIPS_STREAMIB_GETC( streamib )) != -1 &&
|
||||||
/* Is there a \n in the current buffer? It's always nul
|
ch != '\n' &&
|
||||||
* terminated, so strchr() is safe.
|
space_remaining > 0 ) {
|
||||||
*/
|
write_point[0] = ch;
|
||||||
if( (p = strchr( streamib->read_position, '\n' )) ) {
|
write_point += 1;
|
||||||
int bytes_to_copy = p - streamib->read_position;
|
space_remaining -= 1;
|
||||||
|
|
||||||
memcpy( write_point, streamib->read_position,
|
|
||||||
bytes_to_copy );
|
|
||||||
write_point[bytes_to_copy] = '\0';
|
|
||||||
|
|
||||||
/* Leave input pointing at the \n.
|
|
||||||
*/
|
|
||||||
streamib->read_position += bytes_to_copy;
|
|
||||||
streamib->bytes_remaining -= bytes_to_copy;
|
|
||||||
|
|
||||||
return( vips_streamib_next_line( streamib ) );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* No newline, so copy what we have, refill, and try
|
|
||||||
* again.
|
|
||||||
*/
|
|
||||||
int bytes_to_copy = VIPS_MIN( bytes_available,
|
|
||||||
streamib->bytes_remaining );
|
|
||||||
|
|
||||||
memcpy( write_point, streamib->read_position,
|
|
||||||
bytes_to_copy );
|
|
||||||
write_point[bytes_to_copy] = '\0';
|
|
||||||
write_point += bytes_to_copy;
|
|
||||||
bytes_available -= bytes_to_copy;
|
|
||||||
|
|
||||||
streamib->read_position += bytes_to_copy;
|
|
||||||
streamib->bytes_remaining -= bytes_to_copy;
|
|
||||||
|
|
||||||
/* If the line has filled, just skip to the next line.
|
|
||||||
*/
|
|
||||||
if( bytes_available <= 0 )
|
|
||||||
return( vips_streamib_next_line( streamib ) );
|
|
||||||
|
|
||||||
/* We must have exhausted the buffer. Refill and
|
|
||||||
* retry.
|
|
||||||
*/
|
|
||||||
if( vips_streamib_refill( streamib ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
if( streamib->eof )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
write_point[0] = '\0';
|
||||||
|
|
||||||
|
/* If we hit EOF immediately, return EOF.
|
||||||
|
*/
|
||||||
|
if( write_point == streamib->line ) {
|
||||||
|
*line = NULL;
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we filled the output line without seeing \n, keep going to the
|
||||||
|
* next \n.
|
||||||
|
*/
|
||||||
|
if( ch != '\n' &&
|
||||||
|
space_remaining == 0 ) {
|
||||||
|
while( (ch = VIPS_STREAMIB_GETC( streamib )) != -1 &&
|
||||||
|
ch != '\n' )
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we stopped on \n, try to skip any \r too.
|
||||||
|
*/
|
||||||
|
if( ch == '\n' ) {
|
||||||
|
if( VIPS_STREAMIB_GETC( streamib ) != '\r' )
|
||||||
|
vips_streamib_ungetc( streamib );
|
||||||
|
}
|
||||||
|
|
||||||
|
*line = streamib->line;
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_streamib_get_line_copy:
|
* vips_streamib_get_line_copy:
|
||||||
* @streamib: stream to fetch the line from
|
* @streamib: stream to operate on
|
||||||
*
|
*
|
||||||
* Return the next line of text from the stream. The newline character (or
|
* Return the next line of text from the stream. The newline character (or
|
||||||
* characters) are removed, and and the string is terminated with a null
|
* characters) are removed, and and the string is terminated with a null
|
||||||
@ -1218,8 +1219,38 @@ vips_streamib_get_line( VipsStreamib *streamib, const char **line )
|
|||||||
* Returns: the next line from the file, or NULL on EOF.
|
* Returns: the next line from the file, or NULL on EOF.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
char *
|
int
|
||||||
vips_streamib_get_line_copy( VipsStreamib *streamib )
|
vips_streamib_get_line_copy( VipsStreamib *streamib, char **line )
|
||||||
{
|
{
|
||||||
|
const unsigned char null = '\0';
|
||||||
|
GByteArray *buffer;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
buffer = g_byte_array_new();
|
||||||
|
|
||||||
|
while( (ch = VIPS_STREAMIB_GETC( streamib )) != -1 &&
|
||||||
|
ch != '\n' ) {
|
||||||
|
unsigned char c = ch;
|
||||||
|
|
||||||
|
g_byte_array_append( buffer, &c, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ch == -1 ) {
|
||||||
|
VIPS_FREEF( g_byte_array_unref, buffer );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
g_byte_array_append( buffer, &null, 1 );
|
||||||
|
|
||||||
|
/* If we stopped on \n, try to skip any \r too.
|
||||||
|
*/
|
||||||
|
if( ch == '\n' ) {
|
||||||
|
if( VIPS_STREAMIB_GETC( streamib ) != '\r' )
|
||||||
|
vips_streamib_ungetc( streamib );
|
||||||
|
}
|
||||||
|
|
||||||
|
*line = (char *) g_byte_array_free( buffer, FALSE );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user