From becd974d4502f440c3071764c1d219c88caff286 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 9 Nov 2017 23:59:11 +0300 Subject: Add $directory(), $base(), $leaf() and $extension() functions --- build2/functions-path.cxx | 148 +++++++++++++++++++++++++++++++++++++++++ tests/function/path/testscript | 65 ++++++++++++++++++ 2 files changed, 213 insertions(+) diff --git a/build2/functions-path.cxx b/build2/functions-path.cxx index 45ec8ed..77c1464 100644 --- a/build2/functions-path.cxx +++ b/build2/functions-path.cxx @@ -63,6 +63,38 @@ namespace build2 : value (path_cast (move (l)) /= pr); } + // Return untyped value or NULL value if extension is not present. + // + static inline value + extension (path p) + { + const char* e (p.extension_cstring ()); + + if (e == nullptr) + return value (); + + names r; + r.emplace_back (e); + return value (move (r)); + } + + template + static inline P + leaf (const P& p, const optional& d) + { + if (!d) + return p.leaf (); + + try + { + return p.leaf (*d); + } + catch (const invalid_path&) + { + fail << "'" << *d << "' is not a prefix of '" << p << "'" << endf; + } + } + void path_functions () { @@ -193,6 +225,122 @@ namespace build2 return ns; }; + // directory + // + f["directory"] = &path::directory; + + f["directory"] = [](paths v) + { + dir_paths r; + for (const path& p: v) + r.push_back (p.directory ()); + return r; + }; + + f["directory"] = [](dir_paths v) + { + for (dir_path& p: v) + p = p.directory (); + return v; + }; + + f[".directory"] = [](names ns) + { + // For each path decide based on the presence of a trailing slash + // whether it is a directory. Return as list of directory names. + // + for (name& n: ns) + { + if (n.directory ()) + n.dir = n.dir.directory (); + else + n = convert (move (n)).directory (); + } + return ns; + }; + + // base + // + f["base"] = &path::base; + + f["base"] = [](paths v) + { + for (path& p: v) + p = p.base (); + return v; + }; + + f["base"] = [](dir_paths v) + { + for (dir_path& p: v) + p = p.base (); + return v; + }; + + f[".base"] = [](names ns) + { + // For each path decide based on the presence of a trailing slash + // whether it is a directory. Return as untyped list of (potentially + // mixed) paths. + // + for (name& n: ns) + { + if (n.directory ()) + n.dir = n.dir.base (); + else + n.value = convert (move (n)).base ().string (); + } + return ns; + }; + + // leaf + // + f["leaf"] = &path::leaf; + + f["leaf"] = [](path p, dir_path d) + { + return leaf (p, move (d)); + }; + + f["leaf"] = [](paths v, optional d) + { + for (path& p: v) + p = leaf (p, d); + return v; + }; + + f["leaf"] = [](dir_paths v, optional d) + { + for (dir_path& p: v) + p = leaf (p, d); + return v; + }; + + f[".leaf"] = [](names ns, optional d) + { + // For each path decide based on the presence of a trailing slash + // whether it is a directory. Return as untyped list of (potentially + // mixed) paths. + // + for (name& n: ns) + { + if (n.directory ()) + n.dir = leaf (n.dir, d); + else + n.value = leaf (convert (move (n)), d).string (); + } + return ns; + }; + + // extension + // + f["extension"] = &extension; + + f[".extension"] = [](names ns) + { + return extension (convert (move (ns))); + }; + // Path-specific overloads from builtins. // function_family b ("builtin", &path_thunk); diff --git a/tests/function/path/testscript b/tests/function/path/testscript index bfbc895..7d53807 100644 --- a/tests/function/path/testscript +++ b/tests/function/path/testscript @@ -36,6 +36,71 @@ s = ($cxx.target.class != 'windows' ? '/' : '\') } } +: directory +: +{ + $* <'print $directory([path] a/b)' >"a/" : path + $* <'print $directory([dir_path] a/b)' >"a/" : dir-path + $* <'print $directory([paths] a/b c/d/)' >"a/ c/" : paths + $* <'print $directory([dir_paths] a/b c/d/)' >"a/ c/" : dir-paths + $* <'print $path.directory(a/b c/d/)' >"a/ c/" : dir-names +} + +: base +: +{ + $* <'print $base([path] a.c)' >"a" : path + $* <'print $base([dir_path] a.tmp)' >"a$s" : dir-path + $* <'print $base([paths] a.c b.tmp/)' >"a b/" : paths + $* <'print $base([dir_paths] a.tmp b.tmp/)' >"a$s b/" : dir-paths + $* <'print $path.base(a.c b.tmp/)' >"a b/" : dir-names +} + +: leaf +: +{ + $* <'print $leaf([path] a/b)' >"b" : path + $* <'print $leaf([dir_path] a/b)' >"b$s" : dir-path + $* <'print $leaf([path] a/b/c, [dir_path] a)' >"b/c" : sub-path + $* <'print $leaf([dir_path] a/b/c, [dir_path] a)' >"b/c$s" : sub-dir-path + $* <'print $leaf([paths] a/b/c a/b/e, [dir_path] a/b)' >"c e" : sub-paths + $* <'print $leaf([dir_paths] a/b/c, [dir_path] a/b)' >"c$s" : sub-dir-paths + $* <'print $path.leaf(a/b c/d/)' >"b d/" : dir-names + $* <'print $path.leaf(a/b/c a/b/d/, [dir_path] a)' >"b/c b/d/" : sub-dir-names + + : not-prefix + : + $* <'print $leaf([path] a/b/c, [dir_path] a/d)' 2>>"EOE" != 0 + error: 'a/d$s' is not a prefix of 'a/b/c' + EOE +} + +: extension +: +{ + $* <'print $extension([path] a.c)' >"c" : path + $* <'print $extension([dir_path] a.tmp/)' >"tmp" : dir_path + $* <'print $path.extension(a.c)' >"c" : untyped + $* <'print $path.extension(a)' >"[null]" : null +} + +: combined +: +{ + mkdir -p a/b; + touch a/b/c.t.cpp; + $* <>/EOO + t = $src_base/a/b/c.t.cpp + d = $path.leaf($path.directory($t), $src_base) + n = $path.base($path.base($path.leaf($t))) + print $d/exe{$n} + print $d/{+$n*.cpp} + EOI + a/b/exe{c} + a/b/c.t.cpp + EOO +} + : invalid-path : p = ($cxx.target.class != 'windows' ? /../foo : 'c:/../foo'); -- cgit v1.1