diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index aabae8e6..13e5914d 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -55,11 +55,22 @@ * FILENAME_MAX chars. * * We look for the ':' splitting the name and mode by searching for the - * rightmost occurence of the regexp ".[A-Za-z0-9]+:". Example: consider the - * horror that is + * rightmost occurrence of the regexp "\.[A-Za-z0-9]+:". The initial dot can + * be missing if there's a dirsep or start of string, meaning this is a + * filename without an extension. + * + * Examples: * * c:\silly:dir:name\fr:ed.tif:jpeg:95,,,,c:\icc\srgb.icc + * -> c:\silly:dir:name\fr:ed.tif jpeg:95,,,,c:\icc\srgb.icc + * I180: + * -> I180 "" + * c:\silly: + * -> c:\silly "" + * c:\silly + * -> c:\silly "" * + * vips8 handles this in a much better way :( */ void im_filename_split( const char *path, char *name, char *mode ) @@ -74,11 +85,15 @@ im_filename_split( const char *path, char *name, char *mode ) if( *p == ':' ) { char *q; + /* We are skipping back over the file extension, + * isalnum() is probably sufficient. + */ for( q = p - 1; isalnum( *q ) && q > name; q -= 1 ) ; - if( *q == '.' ) + if( *q == '.' ) { break; + } /* All the way back to the start? We probably have a * filename with no extension, eg. "I180:" @@ -86,9 +101,11 @@ im_filename_split( const char *path, char *name, char *mode ) if( q == name ) break; - /* .. or we could hit a dirsep. + /* .. or we could hit a dirsep. Allow win or nix + * separators. */ - if( *q == G_DIR_SEPARATOR ) + if( *q == '/' || + *q == '\\' ) break; } @@ -100,6 +117,40 @@ im_filename_split( const char *path, char *name, char *mode ) strcpy( mode, "" ); } +/** + * vips_path_filename7: + * @path: path to split + * + * Return the filename part of a vips7 path. For testing only. + */ +char * +vips_path_filename7( const char *path ) +{ + char name[FILENAME_MAX]; + char mode[FILENAME_MAX]; + + im_filename_split( path, name, mode ); + + return( g_strdup( name ) ); +} + +/** + * vips_path_mode7: + * @path: path to split + * + * Return the mode part of a vips7 path. For testing only. + */ +char * +vips_path_mode7( const char *path ) +{ + char name[FILENAME_MAX]; + char mode[FILENAME_MAX]; + + im_filename_split( path, name, mode ); + + return( g_strdup( mode ) ); +} + /* Skip any leading path stuff. Horrible: if this is a filename which came * from win32 and we're a *nix machine, it'll have '\\' not '/' as the * separator :-( diff --git a/libvips/include/vips/basic.h b/libvips/include/vips/basic.h index 8f846531..a0adf4b4 100644 --- a/libvips/include/vips/basic.h +++ b/libvips/include/vips/basic.h @@ -66,6 +66,11 @@ typedef enum { VIPS_PRECISION_LAST } VipsPrecision; +/* Just for testing. + */ +char *vips_path_filename7( const char *path ); +char *vips_path_mode7( const char *path ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/test/Makefile.am b/test/Makefile.am index ee0b0c41..bd82e2ca 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,6 +13,7 @@ EXTRA_DIST = \ test_colour.py \ test_conversion.py \ test_convolution.py \ + test_iofuncs.py \ test_create.py \ test_foreign.py \ test_draw.py \ diff --git a/test/test_all.py b/test/test_all.py index 3fefe8ef..98fcf747 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -12,6 +12,7 @@ from test_foreign import * from test_histogram import * from test_morphology import * from test_resample import * +from test_iofuncs import * if __name__ == '__main__': unittest.main() diff --git a/test/test_iofuncs.py b/test/test_iofuncs.py new file mode 100755 index 00000000..0f1bba44 --- /dev/null +++ b/test/test_iofuncs.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 + +from __future__ import division +import unittest +import math + +#import logging +#logging.basicConfig(level = logging.DEBUG) + +from gi.repository import Vips + +Vips.leak_set(True) + +# an expanding zip ... if either of the args is not a list, duplicate it down +# the other +def zip_expand(x, y): + if isinstance(x, list) and isinstance(y, list): + return list(zip(x, y)) + elif isinstance(x, list): + return [[i, y] for i in x] + elif isinstance(y, list): + return [[x, j] for j in y] + else: + return [[x, y]] + +class TestIofuncs(unittest.TestCase): + # test a pair of things which can be lists for approx. equality + def assertEqualObjects(self, a, b, msg = ''): + #print('assertEqualObjects %s = %s' % (a, b)) + for x, y in zip_expand(a, b): + self.assertEqual(x, y, msg = msg) + + # test the vips7 filename splitter ... this is very fragile and annoying + # code with lots of cases + def test_split7(self): + def split(path): + filename7 = Vips.path_filename7(path) + mode7 = Vips.path_mode7(path) + + return [filename7, mode7] + + cases = [ + ["c:\\silly:dir:name\\fr:ed.tif:jpeg:95,,,,c:\\icc\\srgb.icc", + ["c:\\silly:dir:name\\fr:ed.tif", + "jpeg:95,,,,c:\\icc\\srgb.icc"]], + ["I180:", + ["I180", + ""]], + ["c:\\silly:", + ["c:\\silly", + ""]], + ["c:\\program files\\x:hello", + ["c:\\program files\\x", + "hello"]] + ] + + for case in cases: + self.assertEqualObjects(split(case[0]), case[1]) + +if __name__ == '__main__': + unittest.main()