Showing with 70 additions and 15 deletions.
  1. +19 −7 std/container/rbtree.d
  2. +51 −8 std/getopt.d
26 changes: 19 additions & 7 deletions std/container/rbtree.d
Original file line number Diff line number Diff line change
Expand Up @@ -1710,13 +1710,18 @@ assert(equal(rbt[], [5]));
}

/**
Formats the RedBlackTree into a sink function. For more info see
$(D std.format.formatValue)
*/
void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const {
sink("RedBlackTree(");
sink.formatValue(this[], fmt);
sink(")");
Formats the RedBlackTree into a sink function. For more info see $(D
std.format.formatValue). Note that this only is available when the
element type can be formatted. Otherwise, the default toString from
Object is used.
*/
static if(is(typeof((){FormatSpec!(char) fmt; formatValue((const(char)[]) {}, ConstRange.init, fmt);})))
{
void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const {
sink("RedBlackTree(");
sink.formatValue(this[], fmt);
sink(")");
}
}

/**
Expand Down Expand Up @@ -2044,3 +2049,10 @@ unittest
import std.algorithm : equal;
assert(rt1.upperBound(2).equal([3, 4, 5]));
}

// issue 15941
unittest
{
class C {}
RedBlackTree!(C, "cast(void*)a < cast(void*)b") tree;
}
59 changes: 51 additions & 8 deletions std/getopt.d
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ follow this pattern:
[config override], option, [description], receiver,
- config override: a config value, optional
- option: a string
- option: a string or a char
- description: a string, optional
- receiver: a pointer or a callable
*/
Expand All @@ -541,6 +541,7 @@ private template optionValidator(A...)

enum fmt = "getopt validator: %s (at position %d)";
enum isReceiver(T) = isPointer!T || (is(T==function)) || (is(T==delegate));
enum isOptionStr(T) = isSomeString!T || isSomeChar!T;

auto validator()
{
Expand All @@ -551,24 +552,24 @@ private template optionValidator(A...)
{
msg = format(fmt, "first argument must be a string or a config", 0);
}
else static if (!isSomeString!(A[0]) && !is(A[0] == config))
else static if (!isOptionStr!(A[0]) && !is(A[0] == config))
{
msg = format(fmt, "invalid argument type " ~ A[0].stringof, 0);
msg = format(fmt, "invalid argument type: " ~ A[0].stringof, 0);
}
else foreach (i; staticIota!(1, A.length))
{
static if (!isReceiver!(A[i]) && !isSomeString!(A[i]) &&
static if (!isReceiver!(A[i]) && !isOptionStr!(A[i]) &&
!(is(A[i] == config)))
{
msg = format(fmt, "invalid argument type " ~ A[i].stringof, i);
msg = format(fmt, "invalid argument type: " ~ A[i].stringof, i);
break;
}
else static if (isReceiver!(A[i]) && !isSomeString!(A[i-1]))
else static if (isReceiver!(A[i]) && !isOptionStr!(A[i-1]))
{
msg = format(fmt, "a receiver can not be preceeded by a receiver", i);
break;
}
else static if (i > 1 && isSomeString!(A[i]) && isSomeString!(A[i-1])
else static if (i > 1 && isOptionStr!(A[i]) && isOptionStr!(A[i-1])
&& isSomeString!(A[i-2]))
{
msg = format(fmt, "a string can not be preceeded by two strings", i);
Expand All @@ -591,12 +592,31 @@ private template optionValidator(A...)
{
alias P = void*;
alias S = string;
alias A = char;
alias C = config;
alias F = void function();

static assert(optionValidator!(S,P) == "");
static assert(optionValidator!(S,F) == "");
static assert(optionValidator!(A,P) == "");
static assert(optionValidator!(A,F) == "");

static assert(optionValidator!(C,S,P) == "");
static assert(optionValidator!(C,S,F) == "");
static assert(optionValidator!(C,A,P) == "");
static assert(optionValidator!(C,A,F) == "");

static assert(optionValidator!(C,S,S,P) == "");
static assert(optionValidator!(C,S,S,F) == "");
static assert(optionValidator!(C,A,S,P) == "");
static assert(optionValidator!(C,A,S,F) == "");

static assert(optionValidator!(C,S,S,P) == "");
static assert(optionValidator!(C,S,S,P,C,S,F) == "");
static assert(optionValidator!(C,S,S,P,C,S,F) == "");
static assert(optionValidator!(C,S,P,C,S,S,F) == "");

static assert(optionValidator!(C,A,P,A,S,F) == "");
static assert(optionValidator!(C,A,P,C,A,S,F) == "");

static assert(optionValidator!(P,S,S) != "");
static assert(optionValidator!(P,P,S) != "");
Expand All @@ -605,6 +625,29 @@ private template optionValidator(A...)
static assert(optionValidator!(S,S,P,S,S,P,S) != "");
static assert(optionValidator!(S,S,P,P) != "");
static assert(optionValidator!(S,S,S,P) != "");

static assert(optionValidator!(C,A,S,P,C,A,F) == "");
static assert(optionValidator!(C,A,P,C,A,S,F) == "");
}

unittest // bugzilla 15914
{
bool opt;
string[] args = ["program", "-a"];
getopt(args, config.passThrough, 'a', &opt);
assert(opt);
opt = false;
args = ["program", "-a"];
getopt(args, 'a', &opt);
assert(opt);
opt = false;
args = ["program", "-a"];
getopt(args, 'a', "help string", &opt);
assert(opt);
opt = false;
args = ["program", "-a"];
getopt(args, config.caseSensitive, 'a', "help string", &opt);
assert(opt);
}

private void getoptImpl(T...)(ref string[] args, ref configuration cfg,
Expand Down