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:
parent
1e3edd7b1e
commit
2dec30da2c
20
TODO
20
TODO
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user