Skip to content

Commit 79cbde1

Browse files
authored
Fix #10680 - Instead of passing receiver into the conversion function, (#10684)
just return the value and assign it to the receiver. Renamed the conversion function and also cleaned up all the `typeof` calls, which were very verbose.
1 parent cafe864 commit 79cbde1

File tree

1 file changed

+40
-33
lines changed

1 file changed

+40
-33
lines changed

std/getopt.d

+40-33
Original file line numberDiff line numberDiff line change
@@ -610,14 +610,14 @@ private template optionValidator(A...)
610610
alias optionValidator = message;
611611
}
612612

613-
private void handleConversion(R)(string option, string value, R* receiver,
613+
private auto getoptTo(R)(string option, string value,
614614
size_t idx, string file = __FILE__, size_t line = __LINE__)
615615
{
616616
import std.conv : to, ConvException;
617617
import std.format : format;
618618
try
619619
{
620-
*receiver = to!(typeof(*receiver))(value);
620+
return to!R(value);
621621
}
622622
catch (ConvException e)
623623
{
@@ -876,12 +876,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
876876
// (and potentially args[i + 1] too, but that comes later)
877877
args = args[0 .. i] ~ args[i + 1 .. $];
878878

879-
static if (is(typeof(*receiver) == bool))
879+
static if (is(typeof(*receiver)))
880+
alias Target = typeof(*receiver);
881+
else
882+
// delegate
883+
alias Target = void;
884+
885+
static if (is(Target == bool))
880886
{
881887
if (val.length)
882888
{
883889
// parse '--b=true/false'
884-
handleConversion(option, val, receiver, i);
890+
*receiver = getoptTo!(Target)(option, val, i);
885891
}
886892
else
887893
{
@@ -894,23 +900,23 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
894900
import std.exception : enforce;
895901
// non-boolean option, which might include an argument
896902
enum isCallbackWithLessThanTwoParameters =
897-
(is(typeof(receiver) == delegate) || is(typeof(*receiver) == function)) &&
903+
(is(R == delegate) || is(Target == function)) &&
898904
!is(typeof(receiver("", "")));
899905
if (!isCallbackWithLessThanTwoParameters && !(val.length) && !incremental)
900906
{
901907
// Eat the next argument too. Check to make sure there's one
902908
// to be eaten first, though.
903909
enforce!GetOptException(i < args.length,
904-
"Missing value for argument " ~ a ~ ".");
910+
"Missing value for argument " ~ a ~ ".");
905911
val = args[i];
906912
args = args[0 .. i] ~ args[i + 1 .. $];
907913
}
908-
static if (is(typeof(*receiver) == enum) ||
909-
is(typeof(*receiver) == string))
914+
static if (is(Target == enum) ||
915+
is(Target == string))
910916
{
911-
handleConversion(option, val, receiver, i);
917+
*receiver = getoptTo!Target(option, val, i);
912918
}
913-
else static if (is(typeof(*receiver) : real))
919+
else static if (is(Target : real))
914920
{
915921
// numeric receiver
916922
if (incremental)
@@ -919,16 +925,16 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
919925
}
920926
else
921927
{
922-
handleConversion(option, val, receiver, i);
928+
*receiver = getoptTo!Target(option, val, i);
923929
}
924930
}
925-
else static if (is(typeof(*receiver) == string))
931+
else static if (is(Target == string))
926932
{
927933
// string receiver
928-
*receiver = to!(typeof(*receiver))(val);
934+
*receiver = getoptTo!(Target)(option, val, i);
929935
}
930-
else static if (is(typeof(receiver) == delegate) ||
931-
is(typeof(*receiver) == function))
936+
else static if (is(R == delegate) ||
937+
is(Target == function))
932938
{
933939
static if (is(typeof(receiver("", "")) : void))
934940
{
@@ -952,29 +958,25 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
952958
receiver();
953959
}
954960
}
955-
else static if (isArray!(typeof(*receiver)))
961+
else static if (isArray!(Target))
956962
{
957963
// array receiver
958964
import std.range : ElementEncodingType;
959-
alias E = ElementEncodingType!(typeof(*receiver));
965+
alias E = ElementEncodingType!(Target);
960966

961967
if (arraySep == "")
962968
{
963-
E tmp;
964-
handleConversion(option, val, &tmp, i);
965-
*receiver ~= tmp;
969+
*receiver ~= getoptTo!E(option, val, i);
966970
}
967971
else
968972
{
969973
foreach (elem; val.splitter(arraySep))
970974
{
971-
E tmp;
972-
handleConversion(option, elem, &tmp, i);
973-
*receiver ~= tmp;
975+
*receiver ~= getoptTo!E(option, elem, i);
974976
}
975977
}
976978
}
977-
else static if (isAssociativeArray!(typeof(*receiver)))
979+
else static if (isAssociativeArray!(Target))
978980
{
979981
// hash receiver
980982
alias K = typeof(receiver.keys[0]);
@@ -991,14 +993,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
991993
~ to!string(assignChar) ~ "' in argument '" ~ input ~ "'.");
992994
auto key = input[0 .. j];
993995
auto value = input[j + 1 .. $];
994-
995-
K k;
996-
handleConversion("", key, &k, 0);
997-
998-
V v;
999-
handleConversion("", value, &v, 0);
1000-
1001-
return tuple(k,v);
996+
return tuple(getoptTo!K("", key, 0), getoptTo!V("", value, 0));
1002997
}
1003998

1004999
static void setHash(Range)(R receiver, Range range)
@@ -1013,7 +1008,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
10131008
setHash(receiver, val.splitter(arraySep));
10141009
}
10151010
else
1016-
static assert(false, "getopt does not know how to handle the type " ~ typeof(receiver).stringof);
1011+
static assert(false, "getopt does not know how to handle the type " ~ R.stringof);
10171012
}
10181013
}
10191014

@@ -1099,6 +1094,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
10991094
assert(values == ["foo":0, "bar":1, "baz":2], to!string(values));
11001095
}
11011096

1097+
// https://github.com/dlang/phobos/issues/10680
1098+
@safe unittest
1099+
{
1100+
arraySep = ",";
1101+
scope(exit) arraySep = "";
1102+
const(string)[] s;
1103+
string[] args = ["program.name", "-s", "a", "-s", "b", "-s", "c,d,e"];
1104+
getopt(args, "values|s", &s);
1105+
assert(s == ["a", "b", "c", "d", "e"]);
1106+
}
1107+
1108+
11021109
/**
11031110
The option character (default '-').
11041111

0 commit comments

Comments
 (0)