fix up streamib a bit more

radiance load is almost working
This commit is contained in:
John Cupitt 2019-11-04 17:52:43 +00:00
parent 6d3b53174d
commit de94a725aa
3 changed files with 62 additions and 175 deletions

View File

@ -475,9 +475,6 @@ char *buf;
static const char FMTSTR[] = "FORMAT="; /* format identifier */
static gethfunc mycheck;
static int
formatval( /* get format value (return true if format) */
char fmt[MAXFMTLEN],
@ -507,16 +504,12 @@ getheader( /* get header from file */
)
{
for(;;) {
const char *line;
const unsigned char *line;
if( vips_streamib_get_line( streamib, &line ) )
if( !(line = vips_streamib_get_line( streamib )) )
return( -1 );
if( !line )
/* EOF.
*/
return( -1 );
if( strcmp( line, "" ) == 0 )
/* Blank line.
if( strcmp( (char *) line, "" ) == 0 )
/* Blank line. We've parsed the header successfully.
*/
break;
@ -528,117 +521,6 @@ getheader( /* get header from file */
return( 0 );
}
struct check {
char fs[MAXFMTLEN];
};
static int
mycheck( /* check a header line for format info. */
char *s,
void *cp
)
{
struct check *p = (struct check *) cp;
if (!formatval(p->fs, s) && p->fp != NULL) {
fputs(s, p->fp);
}
return(0);
}
static int
globmatch( /* check for match of s against pattern p */
const char *p,
const char *s
)
{
int setmatch;
do {
switch (*p) {
case '?': /* match any character */
if (!*s++)
return(0);
break;
case '*': /* match any string */
while (p[1] == '*') p++;
do
if ( (p[1]=='?') | (p[1]==*s) &&
globmatch(p+1,s) )
return(1);
while (*s++);
return(0);
case '[': /* character set */
setmatch = *s == *++p;
if (!*p)
return(0);
while (*++p != ']') {
if (!*p)
return(0);
if (*p == '-') {
setmatch += (p[-1] <= *s && *s <= p[1]);
if (!*++p)
break;
} else
setmatch += (*p == *s);
}
if (!setmatch)
return(0);
s++;
break;
case '\\': /* literal next */
p++;
/* fall through */
default: /* normal character */
if (*p != *s)
return(0);
s++;
break;
}
} while (*p++);
return(1);
}
/*
* Checkheader(fin,fmt,fout) returns a value of 1 if the input format
* matches the specification in fmt, 0 if no input format was found,
* and -1 if the input format does not match or there is an
* error reading the header. If fmt is empty, then -1 is returned
* if any input format is found (or there is an error), and 0 otherwise.
* If fmt contains any '*' or '?' characters, then checkheader
* does wildcard expansion and copies a matching result into fmt.
* Be sure that fmt is big enough to hold the match in such cases,
* and that it is not a static, read-only string!
*/
static int
checkheader(
VipsStreamib *streamib,
char fmt[MAXFMTLEN]
)
{
struct check cdat;
char *cp;
cdat.fs[0] = '\0';
if (getheader(streamib, mycheck, &cdat) < 0)
return(-1);
if (!cdat.fs[0])
return(0);
for (cp = fmt; *cp; cp++) /* check for globbing */
if ((*cp == '?') | (*cp == '*')) {
if (globmatch(fmt, cdat.fs)) {
strcpy(fmt, cdat.fs);
return(1);
} else
return(-1);
}
return(strcmp(fmt, cdat.fs) ? -1 : 1); /* literal match */
}
/* Read a single scanline, encoded in the old style.
*/
static int
@ -726,6 +608,8 @@ 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 );
@ -841,15 +725,17 @@ int
vips__rad_israd( VipsStreami *streami )
{
VipsStreamib *streamib;
char format[256];
const unsigned char *line;
int result;
strcpy( format, PICFMT );
/* Just test that the first line is the magic string.
*/
streamib = vips_streamib_new( streami );
result = checkheader( streamib, format );
result = (line = vips_streamib_get_line( streamib )) &&
strcmp( (char *) line, "#?RADIANCE" ) == 0;
VIPS_UNREF( streamib );
return( result == 1 );
return( result );
}
static void
@ -934,14 +820,14 @@ static int
rad2vips_get_header( Read *read, VipsImage *out )
{
VipsInterpretation interpretation;
const char *line;
const unsigned char *line;
int width;
int height;
int i, j;
if( getheader( read->streamib,
(gethfunc *) rad2vips_process_line, read ) ||
vips_streamib_get_line( read->streamib, &line ) ||
!(line = vips_streamib_get_line( read->streamib )) ||
!str2resolu( &read->rs, line ) ) {
vips_error( "rad2vips", "%s",
_( "error reading radiance header" ) );

View File

@ -249,14 +249,16 @@ typedef struct _VipsStreamib {
VipsStreami *streami;
/* The +1 means there's always a \0 byte at the end.
*
* Unsigned char, since we don't want >127 to be -ve.
*/
char input_buffer[VIPS_STREAMIB_BUFFER_SIZE + 1];
char *read_point;
unsigned char input_buffer[VIPS_STREAMIB_BUFFER_SIZE + 1];
unsigned char *read_point;
int chars_unread;
/* Build lines of text here.
*/
char line[VIPS_STREAMIB_BUFFER_SIZE + 1];
unsigned char line[VIPS_STREAMIB_BUFFER_SIZE + 1];
} VipsStreamib;
@ -285,11 +287,11 @@ int vips_streamib_require( VipsStreamib *streamib, int require );
0 : \
vips_streamib_require( (S), (R) ) \
)
#define VIPS_STREAMIB_PEEK( S ) (( S )->read_point)
#define VIPS_STREAMIB_PEEK( S ) ((S)->read_point)
#define VIPS_STREAMIB_FETCH( S ) ((S)->chars_unread--, ((S)->read_point++)[0])
int vips_streamib_get_line( VipsStreamib *streamib, const char **line );
int vips_streamib_get_line_copy( VipsStreamib *streamib, char **line );
const unsigned char *vips_streamib_get_line( VipsStreamib *streamib );
unsigned char *vips_streamib_get_line_copy( VipsStreamib *streamib );
#define VIPS_TYPE_STREAMO (vips_streamo_get_type())
#define VIPS_STREAMO( obj ) \

View File

@ -246,7 +246,7 @@ vips_streamib_require( VipsStreamib *streamib, int require )
streamib->read_point = streamib->input_buffer;
while( require > streamib->chars_unread ) {
char *q = streamib->input_buffer +
unsigned char *q = streamib->input_buffer +
streamib->chars_unread;
int space_available =
VIPS_STREAMIB_BUFFER_SIZE -
@ -304,27 +304,26 @@ vips_streamib_require( VipsStreamib *streamib, int require )
/**
* vips_streamib_get_line:
* @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 @line
* Fetch the next line of text from @streamib and return it. The end of
* line character (or characters, for DOS files) are removed, and the string
* is terminated with a null (`\0` character).
*
* @line is set to NULL on end of file.
* Returns NULL on end of file or read error.
*
* If the line is longer than some arbitrary (but large) limit, is is
* truncated. If you need to be able to read very long lines, use the
* slower vips_streamib_get_line_copy().
*
* The return value of @line is owned by @streamib and must not be freed. It
* The return value is owned by @streamib and must not be freed. It
* is valid until the next call to vips_streamib_get_line().
*
* Returns: 0 on success, -1 on error.
* Returns: the next line from the file, or NULL on EOF or read error.
*/
int
vips_streamib_get_line( VipsStreamib *streamib, const char **line )
const unsigned char *
vips_streamib_get_line( VipsStreamib *streamib )
{
char *write_point;
unsigned char *write_point;
int space_remaining;
int ch;
@ -342,10 +341,19 @@ vips_streamib_get_line( VipsStreamib *streamib, const char **line )
/* If we hit EOF immediately, return EOF.
*/
if( write_point == streamib->line ) {
*line = NULL;
return( 0 );
}
if( ch == -1 &&
write_point == streamib->line )
return( NULL );
/* If the final char in the buffer is \r, this is probably a DOS file
* and we should remove that too.
*
* 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 we filled the output line without seeing \n, keep going to the
* next \n.
@ -357,16 +365,7 @@ vips_streamib_get_line( VipsStreamib *streamib, const char **line )
;
}
/* 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( streamib->line );
}
/**
@ -382,13 +381,13 @@ vips_streamib_get_line( VipsStreamib *streamib, const char **line )
* This is slower than vips_streamib_get_line(), but can work with lines of
* any length.
*
* Returns: the next line from the file, or NULL on EOF.
*
* Returns: the next line from the file, or NULL on EOF or read error.
*/
int
vips_streamib_get_line_copy( VipsStreamib *streamib, char **line )
unsigned char *
vips_streamib_get_line_copy( VipsStreamib *streamib )
{
const unsigned char null = '\0';
static const unsigned char null = '\0';
GByteArray *buffer;
int ch;
@ -401,21 +400,21 @@ vips_streamib_get_line_copy( VipsStreamib *streamib, char **line )
g_byte_array_append( buffer, &c, 1 );
}
if( ch == -1 ) {
if( ch == -1 &&
buffer->len == 0 ) {
VIPS_FREEF( g_byte_array_unref, buffer );
return( -1 );
return( NULL );
}
/* If the character before the \n was \r, this is probably a DOS file
* and we should remove the \r.
*/
if( ch == '\n' &&
buffer->len > 0 &&
buffer->data[buffer->len - 1] == '\r' )
g_byte_array_set_size( buffer, buffer->len - 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 );
return( (unsigned char *) g_byte_array_free( buffer, FALSE ) );
}