allow nested [] in CLI args

this now works:

	vips copy x y.dz[suffix=.jpg[Q=90]]
This commit is contained in:
John Cupitt 2016-05-16 11:09:47 +01:00
parent 70abf4efde
commit db11d3b973
5 changed files with 86 additions and 14 deletions

View File

@ -4,6 +4,7 @@
- added @n option to pdfload, thanks andris
- dzsave won't write empty tiles in google mode, thanks bverem, perog,
felixbuenemann
- allow nested [] in CLI args
15/4/16 started 8.3.1
- rename vips wrapper script, it was still vips-8.2, thanks Benjamin

5
TODO
View File

@ -1,8 +1,3 @@
- this seems to not work:
$ vips copy k2.jpg x.dz[suffix=.jpg[Q=90]]
dzsave: not , or ) after parameter
- add more webp tests to py suite
- try moving some more of the CLI tests to py

View File

@ -281,6 +281,10 @@ const char *vips__token_must( const char *buffer, VipsToken *token,
char *string, int size );
const char *vips__token_need( const char *buffer, VipsToken need_token,
char *string, int size );
const char *vips__token_segment( const char *p, VipsToken *token,
char *string, int size );
const char *vips__token_segment_need( const char *p, VipsToken need_token,
char *string, int size );
const char *vips__find_rightmost_brackets( const char *p );
void vips__filename_split8( const char *name,
char *filename, char *option_string );

View File

@ -2282,7 +2282,7 @@ vips_object_set_args( VipsObject *object, const char *p )
string, VIPS_PATH_MAX )) )
return( -1 );
if( !(p = vips__token_must( p, &token, string, VIPS_PATH_MAX )) )
if( !(p = vips__token_segment( p, &token, string, VIPS_PATH_MAX )) )
return( -1 );
for(;;) {
@ -2295,19 +2295,20 @@ vips_object_set_args( VipsObject *object, const char *p )
return( -1 );
}
/* We have to look for a '=', ')' or a ',' to see if string is
/* We have to look for a '=', ']' or a ',' to see if string is
* a param name or a value.
*/
if( !(p = vips__token_must( p, &token,
if( !(p = vips__token_segment( p, &token,
string2, VIPS_PATH_MAX )) )
return( -1 );
if( token == VIPS_TOKEN_EQUALS ) {
if( !(p = vips__token_need( p, VIPS_TOKEN_STRING,
if( !(p = vips__token_segment_need( p, VIPS_TOKEN_STRING,
string2, VIPS_PATH_MAX )) )
return( -1 );
if( vips_object_set_argument_from_string( object,
string, string2 ) )
return( -1 );
if( !(p = vips__token_must( p, &token,
string2, VIPS_PATH_MAX )) )
return( -1 );

View File

@ -1232,19 +1232,20 @@ vips__token_get( const char *p, VipsToken *token, char *string, int size )
default:
/* It's an unquoted string: read up to the next non-string
* character. We don't allow two strings next to each other,
* so the next break must be bracket, equals, comma.
* so the next break must be brackets, equals, comma.
*/
*token = VIPS_TOKEN_STRING;
n = strcspn( p, "[]=," );
i = VIPS_MIN( n, size );
q = p + strcspn( p, "[]=," );
i = VIPS_MIN( q - p, size );
vips_strncpy( string, p, i + 1 );
p += n;
p = q;
/* We remove leading whitespace, so we trim trailing
* whitespace from unquoted strings too. Only if the string
* hasn't been truncated.
*/
if( i == n )
if( i != size )
while( i > 0 && isspace( string[i - 1] ) ) {
string[i - 1] = '\0';
i--;
@ -1291,6 +1292,76 @@ vips__token_need( const char *p, VipsToken need_token,
return( p );
}
/* Fetch a token. If it's a string token terminated by a '[', fetch up to the
* matching ']' as well, for example ".jpg[Q=90]".
*
* Return NULL for end of tokens.
*/
const char *
vips__token_segment( const char *p, VipsToken *token,
char *string, int size )
{
const char *q;
if( !(q = vips__token_must( p, token, string, size )) )
return( NULL );
/* If we stopped on [, read up to the matching ].
*/
if( *token == VIPS_TOKEN_STRING &&
q[0] == '[' ) {
VipsToken sub_token;
char sub_string[VIPS_PATH_MAX];
int depth;
int i;
depth = 0;
do {
if( !(q = vips__token_must( q, &sub_token,
sub_string, VIPS_PATH_MAX )) )
return( NULL );
switch( sub_token ) {
case VIPS_TOKEN_LEFT:
depth += 1;
break;
case VIPS_TOKEN_RIGHT:
depth -= 1;
break;
default:
break;
}
} while( !(sub_token == VIPS_TOKEN_RIGHT && depth == 0) );
i = VIPS_MIN( q - p, size );
vips_strncpy( string, p, i + 1 );
}
return( q );
}
/* We expect a certain segment.
*/
const char *
vips__token_segment_need( const char *p, VipsToken need_token,
char *string, int size )
{
VipsToken token;
if( !(p = vips__token_segment( p, &token, string, size )) )
return( NULL );
if( token != need_token ) {
vips_error( "get_token", _( "expected %s, saw %s" ),
vips_enum_nick( VIPS_TYPE_TOKEN, need_token ),
vips_enum_nick( VIPS_TYPE_TOKEN, token ) );
return( NULL );
}
return( p );
}
/* Maximum number of tokens we allow in a filename. Surely this will be
* plenty.
*/