aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/functions-string.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/functions-string.cxx')
-rw-r--r--libbuild2/functions-string.cxx148
1 files changed, 135 insertions, 13 deletions
diff --git a/libbuild2/functions-string.cxx b/libbuild2/functions-string.cxx
index b430ebf..06fe89d 100644
--- a/libbuild2/functions-string.cxx
+++ b/libbuild2/functions-string.cxx
@@ -8,17 +8,44 @@ using namespace std;
namespace build2
{
+ static size_t
+ find_index (const strings& vs, value&& v, optional<names>&& fs)
+ {
+ bool ic (false);
+ if (fs)
+ {
+ for (name& f: *fs)
+ {
+ string s (convert<string> (move (f)));
+
+ if (s == "icase")
+ ic = true;
+ else
+ throw invalid_argument ("invalid flag '" + s + '\'');
+ }
+ }
+
+ auto i (find_if (vs.begin (), vs.end (),
+ [ic, y = convert<string> (move (v))] (const string& x)
+ {
+ return (ic ? icasecmp (x, y) : x.compare (y)) == 0;
+ }));
+
+ return i != vs.end () ? i - vs.begin () : vs.size ();
+ };
+
void
string_functions (function_map& m)
{
function_family f (m, "string");
- f["string"] += [](string s) {return s;};
-
- // @@ Shouldn't it concatenate elements into the single string?
- // @@ Doesn't seem to be used so far. Can consider removing.
+ // Note that we must handle NULL values (relied upon by the parser
+ // to provide conversion semantics consistent with untyped values).
//
- // f["string"] += [](strings v) {return v;};
+ f["string"] += [](string* s)
+ {
+ return s != nullptr ? move (*s) : string ();
+ };
// Compare ASCII strings ignoring case and returning the boolean value.
//
@@ -77,23 +104,118 @@ namespace build2
return names {name (ucase (convert<string> (move (s))))};
};
+ // $size(<strings>)
+ //
+ // Return the number of elements in the sequence.
+ //
+ f["size"] += [] (strings v) {return v.size ();};
+
+ // $size(<string>)
+ //
+ // Return the number of characters (bytes) in the string.
+ //
+ f["size"] += [] (string v) {return v.size ();};
+
+ // $sort(<strings> [, <flags>])
+ //
+ // Sort strings in ascending order.
+ //
+ // The following flags are supported:
+ //
+ // icase - sort ignoring case
+ //
+ // dedup - in addition to sorting also remove duplicates
+ //
+ f["sort"] += [](strings v, optional<names> fs)
+ {
+ bool ic (false);
+ bool dd (false);
+ if (fs)
+ {
+ for (name& f: *fs)
+ {
+ string s (convert<string> (move (f)));
+
+ if (s == "icase")
+ ic = true;
+ else if (s == "dedup")
+ dd = true;
+ else
+ throw invalid_argument ("invalid flag '" + s + '\'');
+ }
+ }
+
+ sort (v.begin (), v.end (),
+ [ic] (const string& x, const string& y)
+ {
+ return (ic ? icasecmp (x, y) : x.compare (y)) < 0;
+ });
+
+ if (dd)
+ v.erase (unique (v.begin(), v.end(),
+ [ic] (const string& x, const string& y)
+ {
+ return (ic ? icasecmp (x, y) : x.compare (y)) == 0;
+ }),
+ v.end ());
+
+ return v;
+ };
+
+ // $find(<strings>, <string>[, <flags>])
+ //
+ // Return true if the string sequence contains the specified string.
+ //
+ // The following flags are supported:
+ //
+ // icase - compare ignoring case
+ //
+ // See also $regex.find_{match,search}().
+ //
+ f["find"] += [](strings vs, value v, optional<names> fs)
+ {
+ return find_index (vs, move (v), move (fs)) != vs.size ();
+ };
+
+ // $find_index(<strings>, <string>[, <flags>])
+ //
+ // Return the index of the first element in the string sequence that
+ // is equal to the specified string or $size(<strings>) if none is
+ // found.
+ //
+ // The following flags are supported:
+ //
+ // icase - compare ignoring case
+ //
+ f["find_index"] += [](strings vs, value v, optional<names> fs)
+ {
+ return find_index (vs, move (v), move (fs));
+ };
+
// String-specific overloads from builtins.
//
function_family b (m, "builtin");
- b[".concat"] += [](string l, string r) {l += r; return l;};
+ // Note that we must handle NULL values (relied upon by the parser to
+ // provide concatenation semantics consistent with untyped values).
+ //
+ b[".concat"] += [](string* l, string* r)
+ {
+ return l != nullptr
+ ? r != nullptr ? move (*l += *r) : move (*l)
+ : r != nullptr ? move (*r) : string ();
+ };
- b[".concat"] += [](string l, names ur)
+ b[".concat"] += [](string* l, names* ur)
{
- l += convert<string> (move (ur));
- return l;
+ string r (ur != nullptr ? convert<string> (move (*ur)) : string ());
+ return l != nullptr ? move (*l += r) : move (r);
};
- b[".concat"] += [](names ul, string r)
+ b[".concat"] += [](names* ul, string* r)
{
- string l (convert<string> (move (ul)));
- l += r;
- return l;
+ string l (ul != nullptr ? convert<string> (move (*ul)) : string ());
+ return r != nullptr ? move (l += *r) : move (l);
};
}
}