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_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_copy( VipsStreamib *streamib, char **line );
|
||||
|
||||
|
|
|
@ -314,7 +314,7 @@ vips_streami_class_init( VipsStreamiClass *class )
|
|||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "streami";
|
||||
object_class->description = _( "streami stream" );
|
||||
object_class->description = _( "input stream" );
|
||||
|
||||
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 );
|
||||
|
||||
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
|
||||
vips_streamib_class_init( VipsStreamibClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class );
|
||||
|
||||
gobject_class->finalize = vips_streamib_finalize;
|
||||
|
||||
object_class->nickname = "streamib";
|
||||
object_class->description = _( "streamib stream" );
|
||||
|
||||
object_class->build = vips_streamib_build;
|
||||
|
||||
object_class->description = _( "buffered input stream" );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1090,9 +1060,12 @@ vips_streamib_init( VipsStreamib *streamib )
|
|||
{
|
||||
streamib->read_point = streamib->input_buffer;
|
||||
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 )
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
|
@ -1101,33 +1074,75 @@ vips_streamib_refill( VipsStreamib *streamib )
|
|||
*/
|
||||
g_assert( streamib->bytes_remaining == 0 );
|
||||
|
||||
streamib->read_postion = streamib->input_buffer;
|
||||
streamib->bytes_remaining = 0;
|
||||
if( (bytes_read = vips_streami_read( VIPS_STREAMI( streamib ),
|
||||
streamib->read_postion, VIPS_STREAMIB_BUFFER_SIZE )) == -1 )
|
||||
bytes_read = vips_streami_read( VIPS_STREAMI( streamib ),
|
||||
streamib->input_buffer, VIPS_STREAMIB_BUFFER_SIZE );
|
||||
if( bytes_read == -1 )
|
||||
return( -1 );
|
||||
|
||||
streamib->read_point = streamib->input_buffer;
|
||||
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.
|
||||
*/
|
||||
streamib->read_postion[bytes_read] = '\0';
|
||||
streamib->read_point[bytes_read] = '\0';
|
||||
|
||||
if( bytes_read == 0 )
|
||||
streamib->eof = TRUE;
|
||||
return( bytes_read );
|
||||
}
|
||||
|
||||
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:
|
||||
* @streamib: stream to fetch the line from
|
||||
* @streamib: stream to operate on
|
||||
* @line: return the next line of text here
|
||||
*
|
||||
* 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
|
||||
* string is terminated with a null (`\0` character).
|
||||
* line character (or characters, for DOS files) are removed, and @line
|
||||
* is terminated with a null (`\0` character).
|
||||
*
|
||||
* @line is set to NULL on end of file.
|
||||
*
|
||||
|
@ -1144,67 +1159,53 @@ int
|
|||
vips_streamib_get_line( VipsStreamib *streamib, const char **line )
|
||||
{
|
||||
char *write_point;
|
||||
int bytes_available;
|
||||
int space_remaining;
|
||||
int ch;
|
||||
|
||||
write_point = streamib->line;
|
||||
bytes_available = VIPS_STREAMIB_BUFFER_SIZE;
|
||||
space_remaining = VIPS_STREAMIB_BUFFER_SIZE;
|
||||
|
||||
for(;;) {
|
||||
/* Is there a \n in the current buffer? It's always nul
|
||||
* terminated, so strchr() is safe.
|
||||
*/
|
||||
if( (p = strchr( streamib->read_position, '\n' )) ) {
|
||||
int bytes_to_copy = p - streamib->read_position;
|
||||
|
||||
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 ) );
|
||||
while( (ch = VIPS_STREAMIB_GETC( streamib )) != -1 &&
|
||||
ch != '\n' &&
|
||||
space_remaining > 0 ) {
|
||||
write_point[0] = ch;
|
||||
write_point += 1;
|
||||
space_remaining -= 1;
|
||||
}
|
||||
else {
|
||||
/* No newline, so copy what we have, refill, and try
|
||||
* again.
|
||||
write_point[0] = '\0';
|
||||
|
||||
/* If we hit EOF immediately, return EOF.
|
||||
*/
|
||||
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;
|
||||
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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
char *
|
||||
vips_streamib_get_line_copy( VipsStreamib *streamib )
|
||||
int
|
||||
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