From 10e634e64b5fffaf19778d8fd3aa854118aa0d53 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 3 Nov 2021 13:08:48 +0200 Subject: Add $size() function to get size of sequence (names, strings, etc) --- libbuild2/functions-builtin.cxx | 21 +++------------ libbuild2/functions-name.cxx | 41 +++++++++++++++++++++++++++++ libbuild2/functions-path.cxx | 54 ++++++++++++++++++++++----------------- libbuild2/functions-string.cxx | 6 +++++ tests/function/builtin/testscript | 7 ++--- tests/function/name/buildfile | 4 +++ tests/function/name/testscript | 18 +++++++++++++ 7 files changed, 106 insertions(+), 45 deletions(-) create mode 100644 tests/function/name/buildfile create mode 100644 tests/function/name/testscript diff --git a/libbuild2/functions-builtin.cxx b/libbuild2/functions-builtin.cxx index d040ba8..c013c3b 100644 --- a/libbuild2/functions-builtin.cxx +++ b/libbuild2/functions-builtin.cxx @@ -100,25 +100,12 @@ namespace build2 return os.str (); }; - // $sort( [, ]) + // $size() // - // Sort names in ascending order. + // Return the number of elements in the sequence. // - // See also type-specific overloads. - // - // The following flags are supported: - // - // dedup - in addition to sorting also remove duplicates - // - f["sort"] += [] (names v, optional fs) - { - sort (v.begin (), v.end ()); - - if (functions_sort_flags (move (fs))) - v.erase (unique (v.begin(), v.end()), v.end ()); - - return v; - }; + f["size"] += [] (int64s v) {return v.size ();}; + f["size"] += [] (uint64s v) {return v.size ();}; // $sort( [, ]) // diff --git a/libbuild2/functions-name.cxx b/libbuild2/functions-name.cxx index 9ba20a8..800c377 100644 --- a/libbuild2/functions-name.cxx +++ b/libbuild2/functions-name.cxx @@ -10,6 +10,9 @@ using namespace std; namespace build2 { + extern bool + functions_sort_flags (optional); // functions-builtin.cxx + // Convert name to target'ish name (see below for the 'ish part). Return // raw/unprocessed data in case this is an unknown target type (or called // out of scope). See scope::find_target_type() for details. Allow out- @@ -174,6 +177,44 @@ namespace build2 return to_target_name (s, move (n), o).first.proj; }; + // $size() + // + // Return the number of elements in the sequence. + // + fn["size"] += [] (names ns) + { + size_t n (0); + + for (auto i (ns.begin ()); i != ns.end (); ++i) + { + ++n; + if (i->pair && !(++i)->directory ()) + fail << "name pair in names"; + } + + return n; + }; + + // $sort( [, ]) + // + // Sort names in ascending order. + // + // The following flags are supported: + // + // dedup - in addition to sorting also remove duplicates + // + fn["sort"] += [] (names ns, optional fs) + { + //@@ TODO: shouldn't we do this in a pair-aware manner? + + sort (ns.begin (), ns.end ()); + + if (functions_sort_flags (move (fs))) + ns.erase (unique (ns.begin(), ns.end()), ns.end ()); + + return ns; + }; + // Functions that can be called only on real targets. // function_family ft (m, "target"); diff --git a/libbuild2/functions-path.cxx b/libbuild2/functions-path.cxx index d6ff83f..72597ff 100644 --- a/libbuild2/functions-path.cxx +++ b/libbuild2/functions-path.cxx @@ -332,25 +332,30 @@ namespace build2 return ns; }; - // base + // leaf // - f["base"] += &path::base; + f["leaf"] += &path::leaf; - f["base"] += [](paths v) + f["leaf"] += [](path p, dir_path d) + { + return leaf (p, move (d)); + }; + + f["leaf"] += [](paths v, optional d) { for (path& p: v) - p = p.base (); + p = leaf (p, d); return v; }; - f["base"] += [](dir_paths v) + f["leaf"] += [](dir_paths v, optional d) { for (dir_path& p: v) - p = p.base (); + p = leaf (p, d); return v; }; - f[".base"] += [](names ns) + 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 @@ -359,37 +364,32 @@ namespace build2 for (name& n: ns) { if (n.directory ()) - n.dir = n.dir.base (); + n.dir = leaf (n.dir, d); else - n.value = convert (move (n)).base ().string (); + n.value = leaf (convert (move (n)), d).string (); } return ns; }; - // leaf + // base // - f["leaf"] += &path::leaf; - - f["leaf"] += [](path p, dir_path d) - { - return leaf (p, move (d)); - }; + f["base"] += &path::base; - f["leaf"] += [](paths v, optional d) + f["base"] += [](paths v) { for (path& p: v) - p = leaf (p, d); + p = p.base (); return v; }; - f["leaf"] += [](dir_paths v, optional d) + f["base"] += [](dir_paths v) { for (dir_path& p: v) - p = leaf (p, d); + p = p.base (); return v; }; - f[".leaf"] += [](names ns, optional d) + 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 @@ -398,9 +398,9 @@ namespace build2 for (name& n: ns) { if (n.directory ()) - n.dir = leaf (n.dir, d); + n.dir = n.dir.base (); else - n.value = leaf (convert (move (n)), d).string (); + n.value = convert (move (n)).base ().string (); } return ns; }; @@ -414,6 +414,14 @@ namespace build2 return extension (convert (move (ns))); }; + // $size() + // $size() + // + // Return the number of elements in the sequence. + // + f["size"] += [] (paths v) {return v.size ();}; + f["size"] += [] (dir_paths v) {return v.size ();}; + // $sort( [, ]) // $sort( [, ]) // diff --git a/libbuild2/functions-string.cxx b/libbuild2/functions-string.cxx index 6e39c44..18a4ed6 100644 --- a/libbuild2/functions-string.cxx +++ b/libbuild2/functions-string.cxx @@ -77,6 +77,12 @@ namespace build2 return names {name (ucase (convert (move (s))))}; }; + // $size() + // + // Return the number of elements in the sequence. + // + f["size"] += [] (strings v) {return v.size ();}; + // $sort( [, ]) // // Sort strings in ascending order. diff --git a/tests/function/builtin/testscript b/tests/function/builtin/testscript index 3853ec2..00d594b 100644 --- a/tests/function/builtin/testscript +++ b/tests/function/builtin/testscript @@ -80,11 +80,8 @@ : sort : { - $* <'print $sort( d/t{a} t{c b} d/t{a})' >'t{b} t{c} d/t{a} d/t{a}' : name-basics - $* <'print $sort( d/t{a} t{c b} d/t{a}, dedup)' >'t{b} t{c} d/t{a}' : name-dedup - - $* <'print $sort([uint64s] 0 2 1 000)' >'0 0 1 2' : int-basics - $* <'print $sort([uint64s] 0 2 1 000, dedup)' >'0 1 2' : int-dedup + $* <'print $sort([uint64s] 0 2 1 000)' >'0 0 1 2' : basics + $* <'print $sort([uint64s] 0 2 1 000, dedup)' >'0 1 2' : dedup } : getenv diff --git a/tests/function/name/buildfile b/tests/function/name/buildfile new file mode 100644 index 0000000..48be4c3 --- /dev/null +++ b/tests/function/name/buildfile @@ -0,0 +1,4 @@ +# file : tests/function/name/buildfile +# license : MIT; see accompanying LICENSE file + +./: testscript $b diff --git a/tests/function/name/testscript b/tests/function/name/testscript new file mode 100644 index 0000000..2fe8e24 --- /dev/null +++ b/tests/function/name/testscript @@ -0,0 +1,18 @@ +# file : tests/function/name/testscript +# license : MIT; see accompanying LICENSE file + +.include ../../common.testscript + +: size +: +{ + $* <'print $size(a b c@./)' >'3' : basics + $* <'print $type($size(a))' >'uint64' : type +} + +: sort +: +{ + $* <'print $sort( d/t{a} t{c b} d/t{a})' >'t{b} t{c} d/t{a} d/t{a}' : basics + $* <'print $sort( d/t{a} t{c b} d/t{a}, dedup)' >'t{b} t{c} d/t{a}' : dedup +} -- cgit v1.1