mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 22:21:09 +03:00
Merge remote-tracking branch 'upstream/master' into stable
This commit is contained in:
commit
7f8034d9b7
13 changed files with 506 additions and 406 deletions
|
@ -17,7 +17,7 @@ environment:
|
|||
CIRRUS_CLONE_DEPTH: 1
|
||||
# for ci.sh:
|
||||
MODEL: 64
|
||||
HOST_DC: dmd
|
||||
HOST_DMD: dmd
|
||||
N: 4
|
||||
OS_NAME: linux
|
||||
FULL_BUILD: false
|
||||
|
|
5
changelog/deprecate-stdio-bindings.dd
Normal file
5
changelog/deprecate-stdio-bindings.dd
Normal file
|
@ -0,0 +1,5 @@
|
|||
Deprecate `std.stdio.getdelim` and `std.stdio.getline`
|
||||
|
||||
The publicly available `extern(C)` bindings for `getdelim` and `getline` in
|
||||
`std.stdio` have been deprecated. Any code that still needs it can import the
|
||||
symbol from `core.sys.posix.stdio` in druntime instead.
|
10
changelog/jsonvalue-get-integer-conv.dd
Normal file
10
changelog/jsonvalue-get-integer-conv.dd
Normal file
|
@ -0,0 +1,10 @@
|
|||
Add integer conversions in `JSONValue.get`
|
||||
|
||||
`JSONValue.get` now allows to convert a stored `uinteger` or `integer` into any
|
||||
signed or unsigned integer. The conversion is performed with `std.conv.to`, and
|
||||
throws a `ConvException` in case of an integer overflow;
|
||||
|
||||
-------
|
||||
auto json = parseJSON(`{"a": 123}`);
|
||||
writeln(json["a"].get!ubyte);
|
||||
-------
|
|
@ -3577,7 +3577,7 @@ Note:
|
|||
---
|
||||
|
||||
If you want to get NaN as a result if a NaN is present in the range,
|
||||
you can use $(REF fold, std.algorithm,iteration) and $(REF isNaN, std,math):
|
||||
you can use $(REF fold, std,algorithm,iteration) and $(REF isNaN, std,math):
|
||||
|
||||
---
|
||||
<range>.fold!((a,b)=>a.isNaN || b.isNaN ? real.nan : a < b ? a : b);
|
||||
|
|
23
std/bigint.d
23
std/bigint.d
|
@ -1286,7 +1286,7 @@ public:
|
|||
}
|
||||
assert(buff.length > 0, "Invalid buffer length");
|
||||
|
||||
char signChar = isNegative() ? '-' : 0;
|
||||
char signChar = isNegative ? '-' : 0;
|
||||
auto minw = buff.length + (signChar ? 1 : 0);
|
||||
|
||||
if (!hex && !signChar && (f.width == 0 || minw < f.width))
|
||||
|
@ -1459,10 +1459,7 @@ private:
|
|||
{
|
||||
return data.isZero();
|
||||
}
|
||||
bool isNegative() pure const nothrow @nogc @safe
|
||||
{
|
||||
return sign;
|
||||
}
|
||||
alias isNegative = sign;
|
||||
|
||||
// Generate a runtime error if division by zero occurs
|
||||
void checkDivByZero() pure const nothrow @safe
|
||||
|
@ -2160,23 +2157,23 @@ unittest
|
|||
{
|
||||
auto x = BigInt(-3);
|
||||
x %= 3;
|
||||
assert(!x.isNegative());
|
||||
assert(x.isZero());
|
||||
assert(!x.isNegative);
|
||||
assert(x.isZero);
|
||||
|
||||
x = BigInt(-3);
|
||||
x %= cast(ushort) 3;
|
||||
assert(!x.isNegative());
|
||||
assert(x.isZero());
|
||||
assert(!x.isNegative);
|
||||
assert(x.isZero);
|
||||
|
||||
x = BigInt(-3);
|
||||
x %= 3L;
|
||||
assert(!x.isNegative());
|
||||
assert(x.isZero());
|
||||
assert(!x.isNegative);
|
||||
assert(x.isZero);
|
||||
|
||||
x = BigInt(3);
|
||||
x %= -3;
|
||||
assert(!x.isNegative());
|
||||
assert(x.isZero());
|
||||
assert(!x.isNegative);
|
||||
assert(x.isZero);
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=15678
|
||||
|
|
|
@ -4537,7 +4537,7 @@ private struct BitsSet(T)
|
|||
_index = startIndex + trailingZerosCount;
|
||||
}
|
||||
|
||||
@property size_t front()
|
||||
@property size_t front() const
|
||||
{
|
||||
return _index;
|
||||
}
|
||||
|
@ -4562,12 +4562,12 @@ private struct BitsSet(T)
|
|||
_index += trailingZerosCount + 1;
|
||||
}
|
||||
|
||||
@property auto save()
|
||||
@property BitsSet save() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@property size_t length()
|
||||
@property size_t length() const
|
||||
{
|
||||
return countBitsSet(_value);
|
||||
}
|
||||
|
|
|
@ -113,6 +113,16 @@ version (StdUnittest)
|
|||
initializeTests();
|
||||
}
|
||||
|
||||
version (unittest) private bool clockSupported(ClockType c)
|
||||
{
|
||||
// Skip unsupported clocks on older linux kernels, assume that only
|
||||
// CLOCK_MONOTONIC and CLOCK_REALTIME exist, as that is the lowest
|
||||
// common denominator supported by all versions of Linux pre-2.6.12.
|
||||
version (Linux_Pre_2639)
|
||||
return c == ClockType.normal || c == ClockType.precise;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/++
|
||||
Effectively a namespace to make it clear that the methods it contains are
|
||||
|
@ -168,10 +178,13 @@ public:
|
|||
import std.meta : AliasSeq;
|
||||
static foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
|
||||
{{
|
||||
static if (clockSupported(ct))
|
||||
{
|
||||
auto value1 = Clock.currTime!ct;
|
||||
auto value2 = Clock.currTime!ct(UTC());
|
||||
assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
|
||||
assert(abs(value1 - value2) <= seconds(2), format("ClockType.%s", ct));
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -377,10 +390,13 @@ public:
|
|||
|
||||
static foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
|
||||
{{
|
||||
static if (clockSupported(ct))
|
||||
{
|
||||
auto value1 = Clock.currStdTime!ct;
|
||||
auto value2 = Clock.currStdTime!ct;
|
||||
assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
|
||||
assert(abs(value1 - value2) <= limit);
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
|
|
34
std/json.d
34
std/json.d
|
@ -368,6 +368,7 @@ struct JSONValue
|
|||
* A convenience getter that returns this `JSONValue` as the specified D type.
|
||||
* Note: only numeric, `bool`, `string`, `JSONValue[string]` and `JSONValue[]` types are accepted
|
||||
* Throws: `JSONException` if `T` cannot hold the contents of this `JSONValue`
|
||||
* `ConvException` in case of integer overflow when converting to `T`
|
||||
*/
|
||||
@property inout(T) get(T)() inout const pure @safe
|
||||
{
|
||||
|
@ -393,13 +394,17 @@ struct JSONValue
|
|||
throw new JSONException("JSONValue is not a number type");
|
||||
}
|
||||
}
|
||||
else static if (__traits(isUnsigned, T))
|
||||
else static if (isIntegral!T)
|
||||
{
|
||||
return cast(T) uinteger;
|
||||
switch (type)
|
||||
{
|
||||
case JSONType.uinteger:
|
||||
return uinteger.to!T;
|
||||
case JSONType.integer:
|
||||
return integer.to!T;
|
||||
default:
|
||||
throw new JSONException("JSONValue is not a an integral type");
|
||||
}
|
||||
else static if (isSigned!T)
|
||||
{
|
||||
return cast(T) integer;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -420,6 +425,7 @@ struct JSONValue
|
|||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
import std.conv;
|
||||
string s =
|
||||
`{
|
||||
"a": 123,
|
||||
|
@ -427,7 +433,9 @@ struct JSONValue
|
|||
"c": "text",
|
||||
"d": true,
|
||||
"e": [1, 2, 3],
|
||||
"f": { "a": 1 }
|
||||
"f": { "a": 1 },
|
||||
"g": -45,
|
||||
"h": ` ~ ulong.max.to!string ~ `,
|
||||
}`;
|
||||
|
||||
struct a { }
|
||||
|
@ -435,16 +443,22 @@ struct JSONValue
|
|||
immutable json = parseJSON(s);
|
||||
assert(json["a"].get!double == 123.0);
|
||||
assert(json["a"].get!int == 123);
|
||||
assert(json["a"].get!uint == 123);
|
||||
assert(json["b"].get!double == 3.1415);
|
||||
assertThrown(json["b"].get!int);
|
||||
assertThrown!JSONException(json["b"].get!int);
|
||||
assert(json["c"].get!string == "text");
|
||||
assert(json["d"].get!bool == true);
|
||||
assertNotThrown(json["e"].get!(JSONValue[]));
|
||||
assertNotThrown(json["f"].get!(JSONValue[string]));
|
||||
static assert(!__traits(compiles, json["a"].get!a));
|
||||
assertThrown(json["e"].get!float);
|
||||
assertThrown(json["d"].get!(JSONValue[string]));
|
||||
assertThrown(json["f"].get!(JSONValue[]));
|
||||
assertThrown!JSONException(json["e"].get!float);
|
||||
assertThrown!JSONException(json["d"].get!(JSONValue[string]));
|
||||
assertThrown!JSONException(json["f"].get!(JSONValue[]));
|
||||
assert(json["g"].get!int == -45);
|
||||
assertThrown!ConvException(json["g"].get!uint);
|
||||
assert(json["h"].get!ulong == ulong.max);
|
||||
assertThrown!ConvException(json["h"].get!uint);
|
||||
assertNotThrown(json["h"].get!float);
|
||||
}
|
||||
|
||||
private void assign(T)(T arg)
|
||||
|
|
76
std/math.d
76
std/math.d
|
@ -6883,6 +6883,43 @@ debug(UnitTest)
|
|||
real nextUp(real x) @trusted pure nothrow @nogc
|
||||
{
|
||||
alias F = floatTraits!(real);
|
||||
static if (F.realFormat != RealFormat.ieeeDouble)
|
||||
{
|
||||
if (__ctfe)
|
||||
{
|
||||
if (x == -real.infinity)
|
||||
return -real.max;
|
||||
if (!(x < real.infinity)) // Infinity or NaN.
|
||||
return x;
|
||||
real delta;
|
||||
// Start with a decent estimate of delta.
|
||||
if (x <= 0x1.ffffffffffffep+1023 && x >= -double.max)
|
||||
{
|
||||
const double d = cast(double) x;
|
||||
delta = (cast(real) nextUp(d) - cast(real) d) * 0x1p-11L;
|
||||
while (x + (delta * 0x1p-100L) > x)
|
||||
delta *= 0x1p-100L;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = 0x1p960L;
|
||||
while (!(x + delta > x) && delta < real.max * 0x1p-100L)
|
||||
delta *= 0x1p100L;
|
||||
}
|
||||
if (x + delta > x)
|
||||
{
|
||||
while (x + (delta / 2) > x)
|
||||
delta /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
do { delta += delta; } while (!(x + delta > x));
|
||||
}
|
||||
if (x < 0 && x + delta == 0)
|
||||
return -0.0L;
|
||||
return x + delta;
|
||||
}
|
||||
}
|
||||
static if (F.realFormat == RealFormat.ieeeDouble)
|
||||
{
|
||||
return nextUp(cast(double) x);
|
||||
|
@ -7082,15 +7119,21 @@ float nextDown(float x) @safe pure nothrow @nogc
|
|||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended)
|
||||
static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended ||
|
||||
floatTraits!(real).realFormat == RealFormat.ieeeDouble ||
|
||||
floatTraits!(real).realFormat == RealFormat.ieeeExtended53 ||
|
||||
floatTraits!(real).realFormat == RealFormat.ieeeQuadruple)
|
||||
{
|
||||
|
||||
// Tests for 80-bit reals
|
||||
// Tests for reals
|
||||
assert(isIdentical(nextUp(NaN(0xABC)), NaN(0xABC)));
|
||||
//static assert(isIdentical(nextUp(NaN(0xABC)), NaN(0xABC)));
|
||||
// negative numbers
|
||||
assert( nextUp(-real.infinity) == -real.max );
|
||||
assert( nextUp(-1.0L-real.epsilon) == -1.0 );
|
||||
assert( nextUp(-2.0L) == -2.0 + real.epsilon);
|
||||
static assert( nextUp(-real.infinity) == -real.max );
|
||||
static assert( nextUp(-1.0L-real.epsilon) == -1.0 );
|
||||
static assert( nextUp(-2.0L) == -2.0 + real.epsilon);
|
||||
// subnormals and zero
|
||||
assert( nextUp(-real.min_normal) == -real.min_normal*(1-real.epsilon) );
|
||||
assert( nextUp(-real.min_normal*(1-real.epsilon)) == -real.min_normal*(1-2*real.epsilon) );
|
||||
|
@ -7099,11 +7142,24 @@ float nextDown(float x) @safe pure nothrow @nogc
|
|||
assert( nextUp(0.0L) == real.min_normal*real.epsilon );
|
||||
assert( nextUp(real.min_normal*(1-real.epsilon)) == real.min_normal );
|
||||
assert( nextUp(real.min_normal) == real.min_normal*(1+real.epsilon) );
|
||||
static assert( nextUp(-real.min_normal) == -real.min_normal*(1-real.epsilon) );
|
||||
static assert( nextUp(-real.min_normal*(1-real.epsilon)) == -real.min_normal*(1-2*real.epsilon) );
|
||||
static assert( -0.0L is nextUp(-real.min_normal*real.epsilon) );
|
||||
static assert( nextUp(-0.0L) == real.min_normal*real.epsilon );
|
||||
static assert( nextUp(0.0L) == real.min_normal*real.epsilon );
|
||||
static assert( nextUp(real.min_normal*(1-real.epsilon)) == real.min_normal );
|
||||
static assert( nextUp(real.min_normal) == real.min_normal*(1+real.epsilon) );
|
||||
// positive numbers
|
||||
assert( nextUp(1.0L) == 1.0 + real.epsilon );
|
||||
assert( nextUp(2.0L-real.epsilon) == 2.0 );
|
||||
assert( nextUp(real.max) == real.infinity );
|
||||
assert( nextUp(real.infinity)==real.infinity );
|
||||
static assert( nextUp(1.0L) == 1.0 + real.epsilon );
|
||||
static assert( nextUp(2.0L-real.epsilon) == 2.0 );
|
||||
static assert( nextUp(real.max) == real.infinity );
|
||||
static assert( nextUp(real.infinity)==real.infinity );
|
||||
// ctfe near double.max boundary
|
||||
static assert(nextUp(nextDown(cast(real) double.max)) == cast(real) double.max);
|
||||
}
|
||||
|
||||
double n = NaN(0xABC);
|
||||
|
@ -7174,10 +7230,10 @@ float nextDown(float x) @safe pure nothrow @nogc
|
|||
static assert(nextUp(1.0f) == 1.0f+float.epsilon);
|
||||
static assert(nextUp(-0.0f) == float.min_normal*float.epsilon);
|
||||
static assert(nextUp(float.infinity)==float.infinity);
|
||||
//static assert(nextDown(1.0L+real.epsilon)==1.0);
|
||||
static assert(nextDown(1.0L+real.epsilon)==1.0);
|
||||
static assert(nextDown(1.0+double.epsilon)==1.0);
|
||||
static assert(nextDown(1.0f+float.epsilon)==1.0);
|
||||
//static assert(nextafter(1.0+real.epsilon, -real.infinity)==1.0);
|
||||
static assert(nextafter(1.0+real.epsilon, -real.infinity)==1.0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -7253,15 +7309,15 @@ T nextafter(T)(const T x, const T y) @safe pure nothrow @nogc
|
|||
|
||||
enum real c = 3;
|
||||
static assert(is(typeof(nextafter(c, c)) == real));
|
||||
//static assert(nextafter(c, c.infinity) > c);
|
||||
static assert(nextafter(c, c.infinity) > c);
|
||||
static assert(isNaN(nextafter(c, c.nan)));
|
||||
static assert(isNaN(nextafter(c.nan, c)));
|
||||
|
||||
enum real negZero = nextafter(+0.0L, -0.0L); // specially CTFEable
|
||||
enum real negZero = nextafter(+0.0L, -0.0L);
|
||||
static assert(negZero == -0.0L);
|
||||
static assert(signbit(negZero));
|
||||
|
||||
static assert(nextafter(c, c) == c); // ditto
|
||||
static assert(isNaN(nextafter(c, c.nan))); // ditto
|
||||
static assert(isNaN(nextafter(c.nan, c))); // ditto
|
||||
static assert(nextafter(c, c) == c);
|
||||
}
|
||||
|
||||
//real nexttoward(real x, real y) { return core.stdc.math.nexttowardl(x, y); }
|
||||
|
|
|
@ -928,14 +928,6 @@ if (Ranges.length > 0 &&
|
|||
// TODO: use a vtable (or more) instead of linear iteration
|
||||
|
||||
public:
|
||||
this(R input)
|
||||
{
|
||||
foreach (i, v; input)
|
||||
{
|
||||
source[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
import std.meta : anySatisfy;
|
||||
|
||||
static if (anySatisfy!(isInfinite, R))
|
||||
|
@ -4718,7 +4710,7 @@ if (Ranges.length && allSatisfy!(isInputRange, Ranges))
|
|||
static foreach (i, Range; Ranges)
|
||||
static if (hasLength!Range)
|
||||
{
|
||||
static if (!anySatisfy!(hasLength, Ranges[0 .. i]))
|
||||
static if (!is(typeof(minLen) == size_t))
|
||||
size_t minLen = ranges[i].length;
|
||||
else
|
||||
{{
|
||||
|
@ -4891,15 +4883,6 @@ if (Ranges.length && allSatisfy!(isInputRange, Ranges))
|
|||
private Ranges ranges;
|
||||
alias ElementType = Tuple!(staticMap!(.ElementType, Ranges));
|
||||
|
||||
/+
|
||||
Builds an object. Usually this is invoked indirectly by using the
|
||||
$(LREF zip) function.
|
||||
+/
|
||||
this(Ranges rs)
|
||||
{
|
||||
ranges[] = rs[];
|
||||
}
|
||||
|
||||
/+
|
||||
Returns `true` if the range is at end.
|
||||
+/
|
||||
|
@ -5076,30 +5059,21 @@ if (Ranges.length && allSatisfy!(isInputRange, Ranges))
|
|||
&& allSatisfy!(templateOr!(isInfinite, hasLength), Ranges)))
|
||||
{
|
||||
@property size_t length()
|
||||
{
|
||||
static if (allKnownSameLength)
|
||||
{
|
||||
static foreach (i, Range; Ranges)
|
||||
{
|
||||
static if (hasLength!Range && !anySatisfy!(hasLength, Ranges[0 .. i]))
|
||||
return ranges[i].length;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static foreach (i, Range; Ranges)
|
||||
static if (hasLength!Range)
|
||||
{
|
||||
static if (!anySatisfy!(hasLength, Ranges[0 .. i]))
|
||||
static if (!is(typeof(minLen) == size_t))
|
||||
size_t minLen = ranges[i].length;
|
||||
else
|
||||
else static if (!allKnownSameLength)
|
||||
{{
|
||||
const x = ranges[i].length;
|
||||
if (x < minLen) minLen = x;
|
||||
}}
|
||||
}
|
||||
return minLen;
|
||||
}
|
||||
return minLen;
|
||||
}
|
||||
|
||||
alias opDollar = length;
|
||||
|
@ -7725,12 +7699,6 @@ struct Indexed(Source, Indices)
|
|||
if (isRandomAccessRange!Source && isInputRange!Indices &&
|
||||
is(typeof(Source.init[ElementType!(Indices).init])))
|
||||
{
|
||||
this(Source source, Indices indices)
|
||||
{
|
||||
this._source = source;
|
||||
this._indices = indices;
|
||||
}
|
||||
|
||||
/// Range primitives
|
||||
@property auto ref front()
|
||||
{
|
||||
|
|
|
@ -209,7 +209,8 @@ $(TR $(TD Objects) $(TD
|
|||
$(REG_START Character classes )
|
||||
$(REG_TABLE
|
||||
$(REG_TITLE Pattern element, Semantics )
|
||||
$(REG_ROW Any atom, Has the same meaning as outside of a character class.)
|
||||
$(REG_ROW Any atom, Has the same meaning as outside of a character class,
|
||||
except for ] which must be written as \\])
|
||||
$(REG_ROW a-z, Includes characters a, b, c, ..., z. )
|
||||
$(REG_ROW [a||b]$(COMMA) [a--b]$(COMMA) [a~~b]$(COMMA) [a$(AMP)$(AMP)b],
|
||||
Where a, b are arbitrary classes, means union, set difference,
|
||||
|
|
51
std/stdio.d
51
std/stdio.d
|
@ -37,69 +37,55 @@ else version (CRuntime_DigitalMars)
|
|||
// Specific to the way Digital Mars C does stdio
|
||||
version = DIGITAL_MARS_STDIO;
|
||||
}
|
||||
|
||||
version (CRuntime_Glibc)
|
||||
else version (CRuntime_Glibc)
|
||||
{
|
||||
// Specific to the way Gnu C does stdio
|
||||
version = GCC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (CRuntime_Bionic)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (CRuntime_Musl)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (CRuntime_UClibc)
|
||||
{
|
||||
// uClibc supports GCC IO
|
||||
version = GCC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
|
||||
version (OSX)
|
||||
else version (OSX)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (iOS)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (TVOS)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (WatchOS)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (FreeBSD)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (NetBSD)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (DragonFlyBSD)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = HAS_GETDELIM;
|
||||
}
|
||||
else version (Solaris)
|
||||
{
|
||||
version = GENERIC_IO;
|
||||
version = NO_GETDELIM;
|
||||
}
|
||||
|
||||
// Character type used for operating system filesystem APIs
|
||||
|
@ -125,6 +111,11 @@ version (Windows)
|
|||
import core.sys.windows.basetsd : HANDLE;
|
||||
}
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
static import core.sys.posix.stdio; // getdelim
|
||||
}
|
||||
|
||||
version (DIGITAL_MARS_STDIO)
|
||||
{
|
||||
extern (C)
|
||||
|
@ -261,12 +252,20 @@ else
|
|||
static assert(0, "unsupported C I/O system");
|
||||
}
|
||||
|
||||
version (HAS_GETDELIM) extern(C) nothrow @nogc
|
||||
static if (__traits(compiles, core.sys.posix.stdio.getdelim))
|
||||
{
|
||||
extern(C) nothrow @nogc
|
||||
{
|
||||
// @@@DEPRECATED_2.104@@@
|
||||
deprecated("To be removed after 2.104. Use core.sys.posix.stdio.getdelim instead.")
|
||||
ptrdiff_t getdelim(char**, size_t*, int, FILE*);
|
||||
|
||||
// @@@DEPRECATED_2.104@@@
|
||||
// getline() always comes together with getdelim()
|
||||
deprecated("To be removed after 2.104. Use core.sys.posix.stdio.getline instead.")
|
||||
ptrdiff_t getline(char**, size_t*, FILE*);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
private struct ByRecordImpl(Fields...)
|
||||
|
@ -5267,8 +5266,9 @@ private struct ReadlnAppender
|
|||
}
|
||||
|
||||
// Private implementation of readln
|
||||
private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation)
|
||||
{
|
||||
version (DIGITAL_MARS_STDIO)
|
||||
private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation /*ignored*/)
|
||||
{
|
||||
FLOCK(fps);
|
||||
scope(exit) FUNLOCK(fps);
|
||||
|
@ -5389,9 +5389,7 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
|
|||
buf = app.data;
|
||||
return buf.length;
|
||||
}
|
||||
|
||||
version (MICROSOFT_STDIO)
|
||||
private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation /*ignored*/)
|
||||
else version (MICROSOFT_STDIO)
|
||||
{
|
||||
FLOCK(fps);
|
||||
scope(exit) FUNLOCK(fps);
|
||||
|
@ -5421,9 +5419,7 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
|
|||
buf = app.data;
|
||||
return buf.length;
|
||||
}
|
||||
|
||||
version (HAS_GETDELIM)
|
||||
private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation)
|
||||
else static if (__traits(compiles, core.sys.posix.stdio.getdelim))
|
||||
{
|
||||
import core.stdc.stdlib : free;
|
||||
import core.stdc.wchar_ : fwide;
|
||||
|
@ -5503,7 +5499,7 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
|
|||
}
|
||||
}
|
||||
|
||||
auto s = getdelim(&lineptr, &n, terminator, fps);
|
||||
auto s = core.sys.posix.stdio.getdelim(&lineptr, &n, terminator, fps);
|
||||
if (s < 0)
|
||||
{
|
||||
if (ferror(fps))
|
||||
|
@ -5523,9 +5519,7 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
|
|||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
version (NO_GETDELIM)
|
||||
private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation)
|
||||
else // version (NO_GETDELIM)
|
||||
{
|
||||
import core.stdc.wchar_ : fwide;
|
||||
|
||||
|
@ -5624,6 +5618,7 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
|
|||
StdioException();
|
||||
return buf.length;
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
|
|
56
std/traits.d
56
std/traits.d
|
@ -7402,36 +7402,74 @@ if (T.length == 1)
|
|||
Detect whether `T` is a callable object, which can be called with the
|
||||
function call operator `$(LPAREN)...$(RPAREN)`.
|
||||
*/
|
||||
template isCallable(T...)
|
||||
if (T.length == 1)
|
||||
template isCallable(alias callable)
|
||||
{
|
||||
static if (is(typeof(& T[0].opCall) == delegate))
|
||||
static if (is(typeof(&callable.opCall) == delegate))
|
||||
// T is a object which has a member function opCall().
|
||||
enum bool isCallable = true;
|
||||
else static if (is(typeof(& T[0].opCall) V : V*) && is(V == function))
|
||||
else static if (is(typeof(&callable.opCall) V : V*) && is(V == function))
|
||||
// T is a type which has a static member function opCall().
|
||||
enum bool isCallable = true;
|
||||
else static if (is(typeof(&callable!())))
|
||||
{
|
||||
alias TemplateInstanceType = typeof(&callable!());
|
||||
enum bool isCallable = isCallable!TemplateInstanceType;
|
||||
}
|
||||
else
|
||||
enum bool isCallable = isSomeFunction!T;
|
||||
{
|
||||
enum bool isCallable = isSomeFunction!callable;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Functions, lambdas, and aggregate types with (static) opCall.
|
||||
@safe unittest
|
||||
{
|
||||
interface I { real value() @property; }
|
||||
struct S { static int opCall(int) { return 0; } }
|
||||
void f() { }
|
||||
int g(int x) { return x; }
|
||||
|
||||
static assert( isCallable!f);
|
||||
static assert( isCallable!g);
|
||||
|
||||
class C { int opCall(int) { return 0; } }
|
||||
auto c = new C;
|
||||
struct S { static int opCall(int) { return 0; } }
|
||||
interface I { real value() @property; }
|
||||
|
||||
static assert( isCallable!c);
|
||||
static assert( isCallable!S);
|
||||
static assert( isCallable!(c.opCall));
|
||||
static assert( isCallable!S);
|
||||
static assert( isCallable!(I.value));
|
||||
static assert( isCallable!((int a) { return a; }));
|
||||
|
||||
static assert(!isCallable!I);
|
||||
}
|
||||
|
||||
/// Templates
|
||||
@safe unittest
|
||||
{
|
||||
void f()() { }
|
||||
T g(T = int)(T x) { return x; }
|
||||
|
||||
static assert( isCallable!f);
|
||||
static assert( isCallable!g);
|
||||
}
|
||||
|
||||
/// Overloaded functions and function templates.
|
||||
@safe unittest
|
||||
{
|
||||
static struct Wrapper
|
||||
{
|
||||
void f() { }
|
||||
int f(int x) { return x; }
|
||||
|
||||
void g()() { }
|
||||
T g(T = int)(T x) { return x; }
|
||||
}
|
||||
|
||||
static assert(isCallable!(Wrapper.f));
|
||||
static assert(isCallable!(Wrapper.g));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Detect whether `T` is an abstract function.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue