diff options
-rw-r--r-- | stream.c | 32 | ||||
-rw-r--r-- | tests/018/path.tl | 26 | ||||
-rw-r--r-- | txr.1 | 46 |
3 files changed, 96 insertions, 8 deletions
@@ -5016,16 +5016,44 @@ val dir_name(val path) val short_suffix(val name, val alt_in) { + const wchar_t *psc = coerce(const wchar_t *, path_sep_chars); const wchar_t *str = c_str(name); const wchar_t *dot = wcsrchr(str, '.'); - return if3(dot, string(dot + 1), default_null_arg(alt_in)); + const wchar_t *sl = if3(dot, wcspbrk(dot + 1, psc), 0); + + if (!dot || (sl && sl[1])) { + return default_null_arg(alt_in); + } else { + wchar_t *suff = chk_strdup(dot + 1); + if (sl) + suff[sl - (dot + 1)] = 0; + return string_own(suff); + } } val long_suffix(val name, val alt_in) { + const wchar_t *psc = coerce(const wchar_t *, path_sep_chars); const wchar_t *str = c_str(name); const wchar_t *dot = wcschr(str, '.'); - return if3(dot, string(dot + 1), default_null_arg(alt_in)); + + { + const wchar_t *sl; + + while (dot && (sl = wcspbrk(dot, psc)) && sl[1]) { + dot = wcschr(sl + 1, '.'); + sl = wcspbrk(dot, psc); + } + + if (!dot || (sl && sl[1])) { + return default_null_arg(alt_in); + } else { + wchar_t *suff = chk_strdup(dot + 1); + if (sl) + suff[sl - (dot + 1)] = 0; + return string_own(suff); + } + } } val path_cat(val dir_name, val base_name) diff --git a/tests/018/path.tl b/tests/018/path.tl index be95d6c1..3dcb5eb3 100644 --- a/tests/018/path.tl +++ b/tests/018/path.tl @@ -32,3 +32,29 @@ (long-suffix "foo.txt.gz") "txt.gz" (long-suffix ".gz") "gz" (long-suffix ".txt.gz") "txt.gz") + +(mtest + (short-suffix "/") nil + (short-suffix "a/") nil + (short-suffix ".a/") "a" + (short-suffix ".a/b") nil + (short-suffix ".a/b/") nil + (short-suffix ".a/b/.b") "b" + (short-suffix ".a/b/.b/") "b" + (short-suffix ".a/b/c.b") "b" + (short-suffix ".a/b/c.b/") "b" + (short-suffix ".a/b/c.b//") nil) + +(mtest + (long-suffix "/") nil + (long-suffix "a/") nil + (long-suffix ".a/") "a" + (long-suffix ".a/b") nil + (long-suffix ".a/b/") nil + (long-suffix ".a/b/.b") "b" + (long-suffix ".a/b/.b/") "b" + (long-suffix ".a/b/c.b") "b" + (long-suffix ".a/b/c.b/") "b" + (long-suffix "a.b/c.d.e") "d.e" + (long-suffix "a.b/c.d.e/") "d.e" + (long-suffix "a.b/c.d.e//") nil) @@ -57073,26 +57073,55 @@ If .meta path does not contain any occurrences of the character .code . -(period) then it does not have a suffix. In this situation, both +(period) in the role of a suffix delimiter, then +.meta path +does not have a suffix. In this situation, both functions return the .meta alt argument, which defaults to .code nil if it is omitted. -Otherwise the long and short suffix is the substring of +What it means for +.meta path +to have a suffix delimiter is that the +.code . +character occurs somewhere in the last component of +.metn path . +What constitutes the last component is specified +in more detail below. + +If a suffix delimiter is present, then the long or short suffix is the +substring of .meta path -consisting of all the characters which follow the delimiting period. -The delimiting period for the long suffix is the leftmost period; -the delimiting period for the short suffix is the rightmost period. +consisting of all the characters which follow the delimiting period, +exclusive of +.metn path 's +trailing path separator, if any. + +If multiple periods occur in the last component of the path, +the delimiter for the long suffix is the leftmost period; +the delimiter for the short suffix is the rightmost period. If the delimiting period is the rightmost character of .metn path , +or occurs immediately before a trailing path separator, then the suffix delimited by that period is the empty string. If .meta path -contains only one period, then its long and short suffix coincide. +contains only one suffix delimiter, then its long and short suffix coincide. + +For the purpose of identifying the last component of +.meta path +if +.meta path +ends in a path separating character, that character is removed. +If the remaining string contains path-separating characters, then +the last component consists of that portion of it which follows +the rightmost path-separating character. Otherwise, the last component +is the entire string. The suffix, if present, is identified and +extracted from this last component. .TP* Examples: @@ -57104,6 +57133,9 @@ contains only one period, then its long and short suffix coincide. (short-suffix "abc.") -> "" (short-suffix "abc.tar") -> "tar" (short-suffix "abc.tar.gz") -> "gz" + (short-suffix "abc.tar.gz/") -> "gz" + (short-suffix "x.y.z/abc.tar.gz/") -> "gz" + (short-suffix "x.y.z/abc.tar.gz//") -> nil (long-suffix "") -> nil (long-suffix ".") -> "" @@ -57111,6 +57143,8 @@ contains only one period, then its long and short suffix coincide. (long-suffix "abc.") -> "" (long-suffix "abc.tar") -> "txt" (long-suffix "abc.tar.gz") -> "tar.gz" + (long-suffix "abc.tar.gz/") -> "tar.gz" + (long-suffix "x.y.z/abc.tar.gz/") -> "tar.gz" .brev .coNP Function @ path-cat |