better options parser

now only gets the options from the very end of a filename, so this
works:

"this should work (I hope!!).tif[compression=jpeg]"
This commit is contained in:
John Cupitt 2012-01-07 14:10:02 +00:00
parent 1e3edd7b1e
commit 2dec30da2c
5 changed files with 97 additions and 29 deletions

20
TODO
View File

@ -1,24 +1,20 @@
- cache tracing is very handy, maybe make the VIPS_DEBUG macros in cache.c
into glog things, or have a --vips-cache-log flag?
test this
- Vips.Image has members like chain, __subclasshook__ etc etc, are we
really subclassing it correctly?
- get cli arg hooks working
- add support for constants
how do boxed types work? confusing
we need to be able to make a VipsArrayDouble
- add __add__ etc overloads
- vips options: lex entire string to an array of tokens, noting the position
of each
- vips__token_get() will assert(0) if a string token is too large ... it
should return an error or silently truncate
if the final token is a right-bracket, count brackets leftwards to get the
matching start bracket
parse options from that point

View File

@ -505,7 +505,7 @@ vips_foreign_find_load( const char *filename )
(VipsSListMap2Fn) vips_foreign_load_new_from_foreign_sub,
(void *) filename, NULL )) ) {
vips_error( "VipsForeignLoad",
_( "\"%s\" not a known file format" ), filename );
_( "\"%s\" is not a known file format" ), filename );
return( NULL );
}
@ -850,8 +850,7 @@ vips_foreign_find_save( const char *filename )
(VipsSListMap2Fn) vips_foreign_find_save_sub,
(void *) filename, NULL )) ) {
vips_error( "VipsForeignSave",
_( "\"%s\" is not a supported image file." ),
filename );
_( "\"%s\" is not a known file format" ), filename );
return( NULL );
}

View File

@ -242,6 +242,7 @@ 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__find_rightmost_brackets( const char *p );
int vips_ispoweroftwo( int p );
int vips_amiMSBfirst( void );

View File

@ -1662,8 +1662,8 @@ vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b )
return( object );
}
/* Set object args from a string. We've seen the '(', we need to check for the
* closing ')' and make sure there's no extra stuff.
/* Set object args from a string. @p should be the initial left bracket and
* there should be no tokens after the matching right bracket.
*/
static int
vips_object_set_args( VipsObject *object, const char *p )
@ -1675,6 +1675,9 @@ vips_object_set_args( VipsObject *object, const char *p )
VipsArgumentClass *argument_class;
VipsArgumentInstance *argument_instance;
if( !(p = vips__token_need( p, VIPS_TOKEN_LEFT, string, PATH_MAX )) )
return( -1 );
do {
if( !(p = vips__token_need( p, VIPS_TOKEN_STRING,
string, PATH_MAX )) )
@ -1742,29 +1745,30 @@ vips_object_set_args( VipsObject *object, const char *p )
VipsObject *
vips_object_new_from_string( VipsObjectClass *object_class, const char *p )
{
const char *q;
char str[PATH_MAX];
VipsObject *object;
VipsToken token;
g_assert( object_class );
g_assert( object_class->new_from_string );
/* The first string in p is the main construct arg, eg. a filename.
/* Find the start of the optional args on the end of the string, take
* everything before that as the principal arg for the constructor.
*/
if( !(p = vips__token_need( p, VIPS_TOKEN_STRING, str, PATH_MAX )) ||
!(object = object_class->new_from_string( str )) )
if( (q = vips__find_rightmost_brackets( p )) )
vips_strncpy( str, p, VIPS_MIN( PATH_MAX, q - p + 1 ) );
else
vips_strncpy( str, p, PATH_MAX );
if( !(object = object_class->new_from_string( str )) )
return( NULL );
/* More tokens there? Set any other args.
*/
if( (p = vips__token_get( p, &token, str, PATH_MAX )) ) {
if( token == VIPS_TOKEN_LEFT &&
vips_object_set_args( object, p ) ) {
vips_error( "VipsObject",
"%s", _( "bad object arguments" ) );
g_object_unref( object );
return( NULL );
}
if( q &&
vips_object_set_args( object, q ) ) {
vips_error( "VipsObject", "%s", _( "bad object arguments" ) );
g_object_unref( object );
return( NULL );
}
return( object );

View File

@ -1313,6 +1313,74 @@ vips__token_need( const char *p, VipsToken need_token,
return( p );
}
/* Maximum number of tokens we allow in a filename. Surely this will be
* plenty.
*/
#define MAX_TOKENS (1000)
/* Find the start of the right-most pair of brackets in the string.
*
* A string can be of the form:
*
* "hello world! (no really).tif[fred=12]"
*
* we need to be able to find the fred=12 at the end.
*
* We lex the whole string noting the position of each token, then, if the
* final token is a right-bracket, search left for the matching left-bracket.
*
* This can get confused if the lefts are hidden inside another token :-( But
* a fixing that would require us to write a separate right-to-left lexer,
* argh.
*/
const char *
vips__find_rightmost_brackets( const char *p )
{
const char *start[MAX_TOKENS];
VipsToken tokens[MAX_TOKENS];
char str[PATH_MAX];
int n, i;
int nest;
start[0] = p;
for( n = 0;
n < MAX_TOKENS &&
(p = vips__token_get( start[n], &tokens[n], str, PATH_MAX ));
n++, start[n] = p )
;
/* Too many tokens?
*/
if( n == MAX_TOKENS )
return( NULL );
/* No rightmost close bracket?
*/
if( n == 0 ||
tokens[n - 1] != VIPS_TOKEN_RIGHT )
return( NULL );
nest = 0;
for( i = n - 1; i >= 0; i-- ) {
if( tokens[i] == VIPS_TOKEN_RIGHT )
nest += 1;
else if( tokens[i] == VIPS_TOKEN_LEFT )
nest -= 1;
if( nest == 0 )
break;
}
/* No matching left bracket?
*/
if( nest != 0 )
return( NULL );
/* This should be the matching left.
*/
return( start[i] );
}
/* True if an int is a power of two ... 1, 2, 4, 8, 16, 32, etc. Do with just
* integer arithmetic for portability. A previous Nicos version using doubles
* and log/log failed on x86 with rounding problems. Return 0 for not