mirror of
https://github.com/dlang/phobos.git
synced 2025-05-09 04:27:23 +03:00
Merge some functions.
This commit is contained in:
parent
722b02884b
commit
d28a4454bc
1 changed files with 240 additions and 217 deletions
457
std/conv.d
457
std/conv.d
|
@ -57,6 +57,25 @@ private void convError(S, T, string f = __FILE__, uint ln = __LINE__)(S source,
|
|||
~S.stringof~" base "~to!(string)(radix)~" to type "~T.stringof));
|
||||
}
|
||||
|
||||
private
|
||||
{
|
||||
template isImaginary(T)
|
||||
{
|
||||
enum bool isImaginary = staticIndexOf!(Unqual!(T),
|
||||
ifloat, idouble, ireal) >= 0;
|
||||
}
|
||||
template isComplex(T)
|
||||
{
|
||||
enum bool isComplex = staticIndexOf!(Unqual!(T),
|
||||
cfloat, cdouble, creal) >= 0;
|
||||
}
|
||||
template isNarrowInteger(T)
|
||||
{
|
||||
enum bool isNarrowInteger = staticIndexOf!(Unqual!(T),
|
||||
byte, ubyte, short, ushort) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown on conversion overflow errors.
|
||||
*/
|
||||
|
@ -799,15 +818,13 @@ T toImpl(T, S)(S c)
|
|||
}
|
||||
}
|
||||
|
||||
version(unittest) private alias TypeTuple!(
|
||||
char, wchar, dchar,
|
||||
const(char), const(wchar), const(dchar),
|
||||
immutable(char), immutable(wchar), immutable(dchar))
|
||||
AllChars;
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
|
||||
alias TypeTuple!(
|
||||
char, wchar, dchar,
|
||||
const(char), const(wchar), const(dchar),
|
||||
immutable(char), immutable(wchar), immutable(dchar)) AllChars;
|
||||
foreach (Char1; AllChars)
|
||||
{
|
||||
foreach (Char2; AllChars)
|
||||
|
@ -848,61 +865,62 @@ unittest
|
|||
assert(s2 == "foo");
|
||||
}
|
||||
|
||||
/// Small unsigned integers to strings.
|
||||
T toImpl(T, S)(S value)
|
||||
if (isIntegral!S && isUnsigned!S && S.sizeof < uint.sizeof &&
|
||||
isSomeString!T)
|
||||
{
|
||||
return to!T(cast(uint) value);
|
||||
}
|
||||
|
||||
/// Unsigned integers (uint and ulong) to string.
|
||||
/// Unsigned integers to strings.
|
||||
T toImpl(T, S)(S input)
|
||||
if (staticIndexOf!(Unqual!S, uint, ulong) >= 0 &&
|
||||
if (isIntegral!S && isUnsigned!S &&
|
||||
isSomeString!T)
|
||||
{
|
||||
Unqual!S value = input;
|
||||
alias Unqual!(typeof(T.init[0])) Char;
|
||||
static if (is(typeof(T.init[0]) == const) ||
|
||||
is(typeof(T.init[0]) == immutable))
|
||||
static if (S.sizeof < uint.sizeof)
|
||||
{
|
||||
if (value < 10)
|
||||
// Small unsigned integers to strings.
|
||||
return to!T(cast(uint) input);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unsigned integers (uint and ulong) to string.
|
||||
Unqual!S value = input;
|
||||
alias Unqual!(typeof(T.init[0])) Char;
|
||||
static if (is(typeof(T.init[0]) == const) ||
|
||||
is(typeof(T.init[0]) == immutable))
|
||||
{
|
||||
static immutable Char[10] digits = "0123456789";
|
||||
// Avoid storage allocation for simple stuff
|
||||
return digits[cast(size_t) value .. cast(size_t) value + 1];
|
||||
if (value < 10)
|
||||
{
|
||||
static immutable Char[10] digits = "0123456789";
|
||||
// Avoid storage allocation for simple stuff
|
||||
return digits[cast(size_t) value .. cast(size_t) value + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static if (S.sizeof == uint.sizeof)
|
||||
enum maxlength = S.sizeof * 3;
|
||||
else
|
||||
auto maxlength = (value > uint.max ? S.sizeof : uint.sizeof) * 3;
|
||||
static if (S.sizeof == uint.sizeof)
|
||||
enum maxlength = S.sizeof * 3;
|
||||
else
|
||||
auto maxlength = (value > uint.max ? S.sizeof : uint.sizeof) * 3;
|
||||
|
||||
Char[] result;
|
||||
if (__ctfe)
|
||||
{
|
||||
result = new Char[maxlength];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = cast(Char[])
|
||||
GC.malloc(Char.sizeof * maxlength, GC.BlkAttr.NO_SCAN)
|
||||
[0 .. Char.sizeof * maxlength];
|
||||
}
|
||||
Char[] result;
|
||||
if (__ctfe)
|
||||
{
|
||||
result = new Char[maxlength];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = cast(Char[])
|
||||
GC.malloc(Char.sizeof * maxlength, GC.BlkAttr.NO_SCAN)
|
||||
[0 .. Char.sizeof * maxlength];
|
||||
}
|
||||
|
||||
uint ndigits = 0;
|
||||
do
|
||||
{
|
||||
auto div = value / 10;
|
||||
auto rem = value % 10;
|
||||
const c = cast(Char) (rem + '0');
|
||||
value = div;
|
||||
++ndigits;
|
||||
result[$ - ndigits] = c;
|
||||
uint ndigits = 0;
|
||||
do
|
||||
{
|
||||
auto div = value / 10;
|
||||
auto rem = value % 10;
|
||||
const c = cast(Char) (rem + '0');
|
||||
value = div;
|
||||
++ndigits;
|
||||
result[$ - ndigits] = c;
|
||||
}
|
||||
while (value);
|
||||
return cast(T) result[$ - ndigits .. $];
|
||||
}
|
||||
while (value);
|
||||
return cast(T) result[$ - ndigits .. $];
|
||||
}
|
||||
|
||||
unittest
|
||||
|
@ -985,50 +1003,51 @@ unittest
|
|||
assert(i == 0);
|
||||
}
|
||||
|
||||
/// Small signed integers to strings.
|
||||
/// Signed integers to strings.
|
||||
T toImpl(T, S)(S value)
|
||||
if (isIntegral!S && isSigned!S && S.sizeof < int.sizeof &&
|
||||
if (isIntegral!S && isSigned!S &&
|
||||
isSomeString!T)
|
||||
{
|
||||
return to!T(cast(int) value);
|
||||
}
|
||||
|
||||
/// Signed values ($(D int) and $(D long)).
|
||||
T toImpl(T, S)(S value)
|
||||
if (staticIndexOf!(Unqual!S, int, long) >= 0 &&
|
||||
isSomeString!T)
|
||||
{
|
||||
if (value >= 0)
|
||||
return to!T(cast(Unsigned!S) value);
|
||||
alias Unqual!(typeof(T.init[0])) Char;
|
||||
|
||||
// Cache read-only data only for const and immutable; mutable
|
||||
// data is supposed to use allocation in all cases
|
||||
static if (is(ElementType!T == const) || is(ElementType!T == immutable))
|
||||
static if (S.sizeof < int.sizeof)
|
||||
{
|
||||
if (value > -10)
|
||||
// Small signed integers to strings.
|
||||
return to!T(cast(int) value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Signed values ($(D int) and $(D long)).
|
||||
if (value >= 0)
|
||||
return to!T(cast(Unsigned!S) value);
|
||||
alias Unqual!(typeof(T.init[0])) Char;
|
||||
|
||||
// Cache read-only data only for const and immutable; mutable
|
||||
// data is supposed to use allocation in all cases
|
||||
static if (is(ElementType!T == const) || is(ElementType!T == immutable))
|
||||
{
|
||||
static immutable Char[20] data =
|
||||
"00-1-2-3-4-5-6-7-8-9";
|
||||
immutable i = cast(size_t) -value * 2;
|
||||
return data[i .. i + 2];
|
||||
if (value > -10)
|
||||
{
|
||||
static immutable Char[20] data =
|
||||
"00-1-2-3-4-5-6-7-8-9";
|
||||
immutable i = cast(size_t) -value * 2;
|
||||
return data[i .. i + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Char[1 + S.sizeof * 3] buffer;
|
||||
Char[1 + S.sizeof * 3] buffer;
|
||||
|
||||
auto u = -cast(Unqual!(Unsigned!S)) value;
|
||||
uint ndigits = 1;
|
||||
while (u)
|
||||
{
|
||||
immutable c = cast(char)((u % 10) + '0');
|
||||
u /= 10;
|
||||
buffer[$ - ndigits] = c;
|
||||
++ndigits;
|
||||
auto u = -cast(Unqual!(Unsigned!S)) value;
|
||||
uint ndigits = 1;
|
||||
while (u)
|
||||
{
|
||||
immutable c = cast(char)((u % 10) + '0');
|
||||
u /= 10;
|
||||
buffer[$ - ndigits] = c;
|
||||
++ndigits;
|
||||
}
|
||||
assert(ndigits <= buffer.length);
|
||||
buffer[$ - ndigits] = '-';
|
||||
return cast(T) buffer[buffer.length - ndigits .. buffer.length].dup;
|
||||
}
|
||||
assert(ndigits <= buffer.length);
|
||||
buffer[$ - ndigits] = '-';
|
||||
return cast(T) buffer[buffer.length - ndigits .. buffer.length].dup;
|
||||
}
|
||||
|
||||
unittest
|
||||
|
@ -1141,25 +1160,14 @@ unittest
|
|||
}
|
||||
|
||||
/******************************************
|
||||
* Convert value to string in _radix radix.
|
||||
* Convert inttegral value to string in _radix radix.
|
||||
*
|
||||
* radix must be a value from 2 to 36.
|
||||
* value is treated as a signed value only if radix is 10.
|
||||
* The characters A through Z are used to represent values 10 through 36.
|
||||
*/
|
||||
T toImpl(T, S)(S value, uint radix)
|
||||
if (isIntegral!(Unqual!S) && !is(Unqual!S == ulong) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
enforce(radix >= 2 && radix <= 36, new ConvException("Radix error"));
|
||||
if (radix == 10)
|
||||
return to!string(value); // handle signed cases only for radix 10
|
||||
return to!string(cast(ulong) value, radix);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
T toImpl(T, S)(S value, uint radix)
|
||||
if (is(Unqual!S == ulong) &&
|
||||
if (isIntegral!(Unqual!S) &&
|
||||
isSomeString!T)
|
||||
in
|
||||
{
|
||||
|
@ -1167,21 +1175,31 @@ in
|
|||
}
|
||||
body
|
||||
{
|
||||
char[value.sizeof * 8] buffer;
|
||||
uint i = buffer.length;
|
||||
|
||||
if (value < radix && value < hexDigits.length)
|
||||
return hexDigits[cast(size_t)value .. cast(size_t)value + 1];
|
||||
|
||||
do
|
||||
static if (!is(Unqual!S == ulong))
|
||||
{
|
||||
ubyte c;
|
||||
c = cast(ubyte)(value % radix);
|
||||
value = value / radix;
|
||||
i--;
|
||||
buffer[i] = cast(char)((c < 10) ? c + '0' : c + 'A' - 10);
|
||||
} while (value);
|
||||
return to!T(buffer[i .. $].dup);
|
||||
enforce(radix >= 2 && radix <= 36, new ConvException("Radix error"));
|
||||
if (radix == 10)
|
||||
return to!string(value); // handle signed cases only for radix 10
|
||||
return to!string(cast(ulong) value, radix);
|
||||
}
|
||||
else
|
||||
{
|
||||
char[value.sizeof * 8] buffer;
|
||||
uint i = buffer.length;
|
||||
|
||||
if (value < radix && value < hexDigits.length)
|
||||
return hexDigits[cast(size_t)value .. cast(size_t)value + 1];
|
||||
|
||||
do
|
||||
{
|
||||
ubyte c;
|
||||
c = cast(ubyte)(value % radix);
|
||||
value = value / radix;
|
||||
i--;
|
||||
buffer[i] = cast(char)((c < 10) ? c + '0' : c + 'A' - 10);
|
||||
} while (value);
|
||||
return to!T(buffer[i .. $].dup);
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
|
@ -1239,91 +1257,79 @@ unittest
|
|||
assert(r == "1234AF");
|
||||
}
|
||||
|
||||
/// $(D float) to all string types.
|
||||
T toImpl(T, S)(S f)
|
||||
if (is(Unqual!S == float) &&
|
||||
/// All floating point types to all string types.
|
||||
T toImpl(T, S)(S value)
|
||||
if ((isFloatingPoint!S || isImaginary!S || isComplex!S) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
return to!T(cast(double) f);
|
||||
}
|
||||
/// $(D float) to all string types.
|
||||
static if (is(Unqual!S == float))
|
||||
{
|
||||
return to!T(cast(double) value);
|
||||
}
|
||||
|
||||
/// $(D double) to all string types.
|
||||
T toImpl(T, S)(S d)
|
||||
if (is(Unqual!S == double) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
//alias Unqual!(ElementType!T) Char;
|
||||
char[20] buffer;
|
||||
int len = sprintf(buffer.ptr, "%g", d);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
/// $(D double) to all string types.
|
||||
static if (is(Unqual!S == double))
|
||||
{
|
||||
//alias Unqual!(ElementType!T) Char;
|
||||
char[20] buffer;
|
||||
int len = sprintf(buffer.ptr, "%g", value);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
|
||||
/// $(D real) to all string types.
|
||||
T toImpl(T, S)(S r)
|
||||
if (is(Unqual!S == real) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
char[20] buffer;
|
||||
int len = sprintf(buffer.ptr, "%Lg", r);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
/// $(D real) to all string types.
|
||||
static if (is(Unqual!S == real))
|
||||
{
|
||||
char[20] buffer;
|
||||
int len = sprintf(buffer.ptr, "%Lg", value);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
|
||||
/// $(D ifloat) to all string types.
|
||||
T toImpl(T, S)(S f)
|
||||
if (is(Unqual!S == ifloat) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
return to!T(cast(idouble) f);
|
||||
}
|
||||
/// $(D ifloat) to all string types.
|
||||
static if (is(Unqual!S == ifloat))
|
||||
{
|
||||
return to!T(cast(idouble) value);
|
||||
}
|
||||
|
||||
/// $(D idouble) to all string types.
|
||||
T toImpl(T, S)(S d)
|
||||
if (is(Unqual!S == idouble) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
char[21] buffer;
|
||||
int len = sprintf(buffer.ptr, "%gi", d);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
/// $(D idouble) to all string types.
|
||||
static if (is(Unqual!S == idouble))
|
||||
{
|
||||
char[21] buffer;
|
||||
int len = sprintf(buffer.ptr, "%gi", value);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
|
||||
/// $(D ireal) to all string types.
|
||||
T toImpl(T, S)(S r)
|
||||
if (is(Unqual!S == ireal) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
char[21] buffer;
|
||||
int len = sprintf(buffer.ptr, "%Lgi", r);
|
||||
//assert(len < buffer.length); // written bytes is len + 1
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
/// $(D ireal) to all string types.
|
||||
static if (is(Unqual!S == ireal))
|
||||
{
|
||||
char[21] buffer;
|
||||
int len = sprintf(buffer.ptr, "%Lgi", value);
|
||||
//assert(len < buffer.length); // written bytes is len + 1
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
|
||||
/// $(D cfloat) to all string types.
|
||||
T toImpl(T, S)(S f)
|
||||
if (is(Unqual!S == cfloat) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
return to!string(cast(cdouble) f);
|
||||
}
|
||||
/// $(D cfloat) to all string types.
|
||||
static if (is(Unqual!S == cfloat))
|
||||
{
|
||||
return to!string(cast(cdouble) value);
|
||||
}
|
||||
|
||||
/// $(D cdouble) to all string types.
|
||||
T toImpl(T, S)(S d)
|
||||
if (is(Unqual!S == cdouble) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
char[20 + 1 + 20 + 1] buffer;
|
||||
/// $(D cdouble) to all string types.
|
||||
static if (is(Unqual!S == cdouble))
|
||||
{
|
||||
char[20 + 1 + 20 + 1] buffer;
|
||||
|
||||
int len = sprintf(buffer.ptr, "%g+%gi", d.re, d.im);
|
||||
return to!T(buffer[0 .. len]);
|
||||
}
|
||||
int len = sprintf(buffer.ptr, "%g+%gi", value.re, value.im);
|
||||
return to!T(buffer[0 .. len]);
|
||||
}
|
||||
|
||||
/// $(D creal) to all string types.
|
||||
T toImpl(T, S)(S r)
|
||||
if (is(Unqual!S == creal) &&
|
||||
isSomeString!T)
|
||||
{
|
||||
char[20 + 1 + 20 + 1] buffer;
|
||||
int len = sprintf(buffer.ptr, "%Lg+%Lgi", r.re, r.im);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
/// $(D creal) to all string types.
|
||||
static if (is(Unqual!S == creal))
|
||||
{
|
||||
char[20 + 1 + 20 + 1] buffer;
|
||||
int len = sprintf(buffer.ptr, "%Lg+%Lgi", value.re, value.im);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1480,7 +1486,8 @@ unittest
|
|||
assert(to!(string)(a) == "[0:1, 1:2]");
|
||||
}
|
||||
|
||||
private bool convFails(Source, Target, E)(Source src) {
|
||||
private bool convFails(Source, Target, E)(Source src)
|
||||
{
|
||||
try {
|
||||
auto t = to!(Target)(src);
|
||||
} catch (E) {
|
||||
|
@ -1489,14 +1496,16 @@ private bool convFails(Source, Target, E)(Source src) {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void testIntegralToFloating(Integral, Floating)() {
|
||||
private void testIntegralToFloating(Integral, Floating)()
|
||||
{
|
||||
Integral a = 42;
|
||||
auto b = to!(Floating)(a);
|
||||
assert(a == b);
|
||||
assert(a == to!(Integral)(b));
|
||||
}
|
||||
|
||||
private void testFloatingToIntegral(Floating, Integral)() {
|
||||
private void testFloatingToIntegral(Floating, Integral)()
|
||||
{
|
||||
// convert some value
|
||||
Floating a = 4.2e1;
|
||||
auto b = to!(Integral)(a);
|
||||
|
@ -1703,7 +1712,8 @@ Example:
|
|||
Rounded conversions do not work with non-integral target types.
|
||||
*/
|
||||
|
||||
template roundTo(Target) {
|
||||
template roundTo(Target)
|
||||
{
|
||||
Target roundTo(Source)(Source value) {
|
||||
static assert(isFloatingPoint!Source);
|
||||
static assert(isIntegral!Target);
|
||||
|
@ -1765,7 +1775,7 @@ assert(test == "");
|
|||
*/
|
||||
|
||||
Target parse(Target, Source)(ref Source s)
|
||||
if (isSomeChar!(ElementType!Source) && isIntegral!Target && !isSomeChar!Target)
|
||||
if (isSomeChar!(ElementType!Source) && isIntegral!Target && !isSomeChar!Target)
|
||||
{
|
||||
static if (Target.sizeof < int.sizeof)
|
||||
{
|
||||
|
@ -1847,7 +1857,7 @@ if (isSomeChar!(ElementType!Source) && isIntegral!Target && !isSomeChar!Target)
|
|||
|
||||
/// ditto
|
||||
Target parse(Target, Source)(ref Source s, uint radix)
|
||||
if (isSomeString!Source && isIntegral!Target)
|
||||
if (isSomeString!Source && isIntegral!Target)
|
||||
in
|
||||
{
|
||||
assert(radix >= 2 && radix <= 36);
|
||||
|
@ -1926,7 +1936,7 @@ unittest
|
|||
}
|
||||
|
||||
Target parse(Target, Source)(ref Source s)
|
||||
if (isSomeString!Source && is(Target == enum))
|
||||
if (isSomeString!Source && is(Target == enum))
|
||||
{
|
||||
// TODO: BUG4744
|
||||
foreach (i, e; EnumMembers!Target)
|
||||
|
@ -1981,7 +1991,7 @@ unittest
|
|||
}
|
||||
|
||||
Target parse(Target, Source)(ref Source p)
|
||||
if (isInputRange!Source && /*!isSomeString!Source && */isFloatingPoint!Target)
|
||||
if (isInputRange!Source && /*!isSomeString!Source && */isFloatingPoint!Target)
|
||||
{
|
||||
static immutable real negtab[14] =
|
||||
[ 1e-4096L,1e-2048L,1e-1024L,1e-512L,1e-256L,1e-128L,1e-64L,1e-32L,
|
||||
|
@ -1993,7 +2003,8 @@ if (isInputRange!Source && /*!isSomeString!Source && */isFloatingPoint!Target)
|
|||
// static immutable string nans = "nans";
|
||||
|
||||
ConvException bailOut(string f = __FILE__, size_t n = __LINE__)
|
||||
(string msg = null) {
|
||||
(string msg = null)
|
||||
{
|
||||
if (!msg) msg = "Floating point conversion error";
|
||||
return new ConvException(text(f, ":", n, ": ", msg, " for input \"", p, "\"."));
|
||||
}
|
||||
|
@ -2346,7 +2357,7 @@ Parsing one character off a string returns the character and bumps the
|
|||
string up one position.
|
||||
*/
|
||||
Target parse(Target, Source)(ref Source s)
|
||||
if (isInputRange!Source && isSomeChar!(ElementType!Source) &&
|
||||
if (isInputRange!Source && isSomeChar!(ElementType!Source) &&
|
||||
isSomeChar!Target && Target.sizeof >= ElementType!Source.sizeof)
|
||||
{
|
||||
Target result = s.front;
|
||||
|
@ -2357,7 +2368,7 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) &&
|
|||
// Special case: okay so parse a char off a char[] or a wchar off a
|
||||
// wchar[]
|
||||
Target parse(Target, Source)(ref Source s)
|
||||
if (isSomeString!Source && is(Source : const(Target)[]))
|
||||
if (isSomeString!Source && is(Source : const(Target)[]))
|
||||
{
|
||||
Target result = s[0];
|
||||
s = s[1 .. $];
|
||||
|
@ -2395,7 +2406,7 @@ Target parse(Target, Source)(ref Source s)
|
|||
|
||||
// Parsing typedefs forwards to their host types
|
||||
Target parse(Target, Source)(ref Source s)
|
||||
if (isSomeString!Source && is(Target == typedef))
|
||||
if (isSomeString!Source && is(Target == typedef))
|
||||
{
|
||||
static if (is(Target T == typedef))
|
||||
return cast(Target) parse!T(s);
|
||||
|
@ -2414,7 +2425,7 @@ private void skipWS(R)(ref R r)
|
|||
* default $(D ',')).
|
||||
*/
|
||||
Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
|
||||
if (isSomeString!Source && isDynamicArray!Target && !isSomeString!Target)
|
||||
if (isSomeString!Source && isDynamicArray!Target && !isSomeString!Target)
|
||||
{
|
||||
Target result;
|
||||
skipWS(s);
|
||||
|
@ -3923,7 +3934,8 @@ unittest
|
|||
Take a look at int.max and int.max+1 in octal and the logic for this
|
||||
function follows directly.
|
||||
*/
|
||||
template octalFitsInInt(string octalNum) {
|
||||
template octalFitsInInt(string octalNum)
|
||||
{
|
||||
// note it is important to strip the literal of all
|
||||
// non-numbers. kill the suffix and underscores lest they mess up
|
||||
// the number of digits here that we depend on.
|
||||
|
@ -3932,7 +3944,8 @@ template octalFitsInInt(string octalNum) {
|
|||
strippedOctalLiteral(octalNum)[0] == '1';
|
||||
}
|
||||
|
||||
string strippedOctalLiteral(string original) {
|
||||
string strippedOctalLiteral(string original)
|
||||
{
|
||||
string stripped = "";
|
||||
foreach (c; original)
|
||||
if (c >= '0' && c <= '7')
|
||||
|
@ -3940,7 +3953,8 @@ string strippedOctalLiteral(string original) {
|
|||
return stripped;
|
||||
}
|
||||
|
||||
template literalIsLong(string num) {
|
||||
template literalIsLong(string num)
|
||||
{
|
||||
static if (num.length > 1)
|
||||
// can be xxL or xxLu according to spec
|
||||
enum literalIsLong = (num[$-1] == 'L' || num[$-2] == 'L');
|
||||
|
@ -3948,7 +3962,8 @@ template literalIsLong(string num) {
|
|||
enum literalIsLong = false;
|
||||
}
|
||||
|
||||
template literalIsUnsigned(string num) {
|
||||
template literalIsUnsigned(string num)
|
||||
{
|
||||
static if (num.length > 1)
|
||||
// can be xxL or xxLu according to spec
|
||||
enum literalIsUnsigned = (num[$-1] == 'u' || num[$-2] == 'u')
|
||||
|
@ -3984,25 +3999,29 @@ auto z = octal!"1_000_000u";
|
|||
----
|
||||
*/
|
||||
int octal(string num)()
|
||||
if((octalFitsInInt!(num) && !literalIsLong!(num)) && !literalIsUnsigned!(num)) {
|
||||
if((octalFitsInInt!(num) && !literalIsLong!(num)) && !literalIsUnsigned!(num))
|
||||
{
|
||||
return octal!(int, num);
|
||||
}
|
||||
|
||||
/// Ditto
|
||||
long octal(string num)()
|
||||
if((!octalFitsInInt!(num) || literalIsLong!(num)) && !literalIsUnsigned!(num)) {
|
||||
if((!octalFitsInInt!(num) || literalIsLong!(num)) && !literalIsUnsigned!(num))
|
||||
{
|
||||
return octal!(long, num);
|
||||
}
|
||||
|
||||
/// Ditto
|
||||
uint octal(string num)()
|
||||
if((octalFitsInInt!(num) && !literalIsLong!(num)) && literalIsUnsigned!(num)) {
|
||||
if((octalFitsInInt!(num) && !literalIsLong!(num)) && literalIsUnsigned!(num))
|
||||
{
|
||||
return octal!(int, num);
|
||||
}
|
||||
|
||||
/// Ditto
|
||||
ulong octal(string num)()
|
||||
if((!octalFitsInInt!(num) || literalIsLong!(num)) && literalIsUnsigned!(num)) {
|
||||
if((!octalFitsInInt!(num) || literalIsLong!(num)) && literalIsUnsigned!(num))
|
||||
{
|
||||
return octal!(long, num);
|
||||
}
|
||||
|
||||
|
@ -4012,7 +4031,8 @@ Returns if the given string is a correctly formatted octal literal.
|
|||
The format is specified in lex.html. The leading zero is allowed, but
|
||||
not required.
|
||||
*/
|
||||
bool isOctalLiteralString(string num) {
|
||||
bool isOctalLiteralString(string num)
|
||||
{
|
||||
if (num.length == 0)
|
||||
return false;
|
||||
|
||||
|
@ -4048,7 +4068,8 @@ bool isOctalLiteralString(string num) {
|
|||
/*
|
||||
Returns true if the given compile time string is an octal literal.
|
||||
*/
|
||||
template isOctalLiteral(string num) {
|
||||
template isOctalLiteral(string num)
|
||||
{
|
||||
enum bool isOctalLiteral = isOctalLiteralString(num);
|
||||
}
|
||||
|
||||
|
@ -4062,7 +4083,8 @@ template isOctalLiteral(string num) {
|
|||
|
||||
assert(a == 8);
|
||||
*/
|
||||
T octal(T, string num)() {
|
||||
T octal(T, string num)()
|
||||
{
|
||||
static assert(isOctalLiteral!num, num ~ " is not a valid octal literal");
|
||||
|
||||
ulong pow = 1;
|
||||
|
@ -4083,7 +4105,8 @@ T octal(T, string num)() {
|
|||
}
|
||||
|
||||
/// Ditto
|
||||
template octal(alias s) if (isIntegral!(typeof(s))) {
|
||||
template octal(alias s) if (isIntegral!(typeof(s)))
|
||||
{
|
||||
enum auto octal = octal!(typeof(s), toStringNow!(s));
|
||||
}
|
||||
|
||||
|
@ -4161,7 +4184,7 @@ Returns: A pointer to the newly constructed object (which is the same
|
|||
as $(D chunk)).
|
||||
*/
|
||||
T* emplace(T)(T* chunk)
|
||||
if (!is(T == class))
|
||||
if (!is(T == class))
|
||||
{
|
||||
auto result = cast(typeof(return)) chunk;
|
||||
static T i;
|
||||
|
@ -4181,7 +4204,7 @@ Returns: A pointer to the newly constructed object (which is the same
|
|||
as $(D chunk)).
|
||||
*/
|
||||
T* emplace(T, Args...)(T* chunk, Args args)
|
||||
if (!is(T == class) && !is(T == struct) && Args.length == 1)
|
||||
if (!is(T == class) && !is(T == struct) && Args.length == 1)
|
||||
{
|
||||
*chunk = args[0];
|
||||
return chunk;
|
||||
|
@ -4189,7 +4212,7 @@ if (!is(T == class) && !is(T == struct) && Args.length == 1)
|
|||
|
||||
// Specialization for struct
|
||||
T* emplace(T, Args...)(T* chunk, Args args)
|
||||
if (is(T == struct))
|
||||
if (is(T == struct))
|
||||
{
|
||||
auto result = cast(typeof(return)) chunk;
|
||||
|
||||
|
@ -4275,7 +4298,7 @@ $(D T) is $(D @safe).
|
|||
Returns: A pointer to the newly constructed object.
|
||||
*/
|
||||
T* emplace(T, Args...)(void[] chunk, Args args)
|
||||
if (!is(T == class))
|
||||
if (!is(T == class))
|
||||
{
|
||||
enforce(chunk.length >= T.sizeof,
|
||||
new ConvException("emplace: chunk size too small"));
|
||||
|
@ -4352,7 +4375,7 @@ unittest
|
|||
|
||||
// Undocumented for the time being
|
||||
void toTextRange(T, W)(T value, W writer)
|
||||
if (isIntegral!T && isOutputRange!(W, char))
|
||||
if (isIntegral!T && isOutputRange!(W, char))
|
||||
{
|
||||
Unqual!(Unsigned!T) v = void;
|
||||
if (value < 0)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue