1 // Written in the D programming language.
4 A one-stop shop for converting values from one type to another.
6 $(SCRIPT inhibitQuickIndex = 1;)
8 $(TR $(TH Category) $(TH Functions))
9 $(TR $(TD Generic) $(TD
10 $(LREF asOriginalType)
17 $(TR $(TD Strings) $(TD
23 $(TR $(TD Numeric) $(TD
29 $(TR $(TD Exceptions) $(TD
31 $(LREF ConvOverflowException)
35 Copyright: Copyright Digital Mars 2007-.
37 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
39 Authors: $(HTTP digitalmars.com, Walter Bright),
40 $(HTTP erdani.org, Andrei Alexandrescu),
45 Source: $(PHOBOSSRC std/_conv.d)
50 public import std.ascii : LetterCase;
53 import std.range.primitives;
56 // Same as std.string.format, but "self-importing".
57 // Helps reduce code and imports, particularly in static asserts.
58 // Also helps with missing imports errors.
59 package template convFormat()
61 import std.format : format;
62 alias convFormat = format;
65 /* ************* Exceptions *************** */
68 * Thrown on conversion errors.
70 class ConvException : Exception
72 import std.exception : basicExceptionCtors;
74 mixin basicExceptionCtors;
77 private auto convError(S, T)(S source, string fn = __FILE__, size_t ln = __LINE__)
82 msg = "Unexpected end of input when converting from type " ~ S.stringof ~ " to type " ~ T.stringof;
85 ElementType!S el = source.front;
88 msg = text("Unexpected '\\n' when converting from type " ~ S.stringof ~ " to type " ~ T.stringof);
90 msg = text("Unexpected '", el,
91 "' when converting from type " ~ S.stringof ~ " to type " ~ T.stringof);
94 return new ConvException(msg, fn, ln);
97 private auto convError(S, T)(S source, int radix, string fn = __FILE__, size_t ln = __LINE__)
102 msg = text("Unexpected end of input when converting from type " ~ S.stringof ~ " base ", radix,
103 " to type " ~ T.stringof);
105 msg = text("Unexpected '", source.front,
106 "' when converting from type " ~ S.stringof ~ " base ", radix,
107 " to type " ~ T.stringof);
109 return new ConvException(msg, fn, ln);
112 @safe pure/* nothrow*/ // lazy parameter bug
113 private auto parseError(lazy string msg, string fn = __FILE__, size_t ln = __LINE__)
115 return new ConvException(text("Can't parse string: ", msg), fn, ln);
118 private void parseCheck(alias source)(dchar c, string fn = __FILE__, size_t ln = __LINE__)
121 throw parseError(text("unexpected end of input when expecting", "\"", c, "\""));
122 if (source.front != c)
123 throw parseError(text("\"", c, "\" is missing"), fn, ln);
132 // workaround for Bugzilla 14198
133 static if (is(S == bool) && is(typeof({ T s = "string"; })))
135 return src ? "true" : "false";
139 import std.array : appender;
140 import std.format : FormatSpec, formatValue;
142 auto w = appender!T();
143 FormatSpec!(ElementEncodingType!T) f;
144 formatValue(w, src, f);
149 template isExactSomeString(T)
151 enum isExactSomeString = isSomeString!T && !is(T == enum);
154 template isEnumStrToStr(S, T)
156 enum isEnumStrToStr = isImplicitlyConvertible!(S, T) &&
157 is(S == enum) && isExactSomeString!T;
159 template isNullToStr(S, T)
161 enum isNullToStr = isImplicitlyConvertible!(S, T) &&
162 (is(Unqual!S == typeof(null))) && isExactSomeString!T;
167 * Thrown on conversion overflow errors.
169 class ConvOverflowException : ConvException
172 this(string s, string fn = __FILE__, size_t ln = __LINE__)
179 The `to` template converts a value from one type _to another.
180 The source type is deduced and the target type must be specified, for example the
181 expression `to!int(42.0)` converts the number 42 from
182 `double` _to `int`. The conversion is "safe", i.e.,
183 it checks for overflow; `to!int(4.2e10)` would throw the
184 `ConvOverflowException` exception. Overflow checks are only
185 inserted when necessary, e.g., `to!double(42)` does not do
186 any checking because any `int` fits in a `double`.
188 Conversions from string _to numeric types differ from the C equivalents
189 `atoi()` and `atol()` by checking for overflow and not allowing whitespace.
191 For conversion of strings _to signed types, the grammar recognized is:
192 $(PRE $(I Integer): $(I Sign UnsignedInteger)
198 For conversion _to unsigned types, the grammar recognized is:
199 $(PRE $(I UnsignedInteger):
201 $(I DecimalDigit) $(I UnsignedInteger))
208 return toImpl!T(args);
215 return toImpl!T(arg);
220 if (isAggregateType!S && !isCopyable!S)
222 return toImpl!T(arg);
227 * Converting a value _to its own type (useful mostly for generic code)
228 * simply returns its argument.
234 double c = to!double(3.14); // c is double with value 3.14
238 * Converting among numeric types is a safe way _to cast them around.
240 * Conversions from floating-point types _to integral types allow loss of
241 * precision (the fractional part of a floating-point number). The
242 * conversion is truncating towards zero, the same way a cast would
243 * truncate. (_To round a floating point value when casting _to an
244 * integral, use `roundTo`.)
248 import std.exception : assertThrown;
251 assert(to!long(a) == a);
252 assertThrown!ConvOverflowException(to!byte(a));
254 assert(to!int(4.2e6) == 4200000);
255 assertThrown!ConvOverflowException(to!uint(-3.14));
256 assert(to!uint(3.14) == 3);
257 assert(to!uint(3.99) == 3);
258 assert(to!int(-3.99) == -3);
262 * When converting strings _to numeric types, note that the D hexadecimal and binary
263 * literals are not handled. Neither the prefixes that indicate the base, nor the
264 * horizontal bar used _to separate groups of digits are recognized. This also
265 * applies to the suffixes that indicate the type.
267 * _To work around this, you can specify a radix for conversions involving numbers.
271 auto str = to!string(42, 16);
273 auto i = to!int(str, 16);
278 * Conversions from integral types _to floating-point types always
279 * succeed, but might lose accuracy. The largest integers with a
280 * predecessor representable in floating-point format are `2^24-1` for
281 * `float`, `2^53-1` for `double`, and `2^64-1` for `real` (when
282 * `real` is 80-bit, e.g. on Intel machines).
286 // 2^24 - 1, largest proper integer representable as float
288 assert(to!int(to!float(a)) == a);
289 assert(to!int(to!float(-a)) == -a);
293 * Converting an array _to another array type works by converting each
294 * element in turn. Associative arrays can be converted _to associative
295 * arrays as long as keys and values can in turn be converted.
299 import std.string : split;
302 auto b = to!(float[])(a);
303 assert(b == [1.0f, 2, 3]);
304 string str = "1 2 3 4 5 6";
305 auto numbers = to!(double[])(split(str));
306 assert(numbers == [1.0, 2, 3, 4, 5, 6]);
310 auto d = to!(double[wstring])(c);
311 assert(d["a"w] == 1 && d["b"w] == 2);
315 * Conversions operate transitively, meaning that they work on arrays and
316 * associative arrays of any complexity.
318 * This conversion works because `to!short` applies _to an `int`, `to!wstring`
319 * applies _to a `string`, `to!string` applies _to a `double`, and
320 * `to!(double[])` applies _to an `int[]`. The conversion might throw an
321 * exception because `to!short` might fail the range check.
325 int[string][double[int[]]] a;
326 auto b = to!(short[wstring][string[double[]]])(a);
330 * Object-to-object conversions by dynamic casting throw exception when
331 * the source is non-null and the target is null.
335 import std.exception : assertThrown;
336 // Testing object conversions
340 A a1 = new A, a2 = new B, a3 = new C;
341 assert(to!B(a2) is a2);
342 assert(to!C(a3) is a3);
343 assertThrown!ConvException(to!B(a3));
347 * Stringize conversion from all types is supported.
349 * $(LI String _to string conversion works for any two string types having
350 * ($(D char), $(D wchar), $(D dchar)) character widths and any
351 * combination of qualifiers (mutable, $(D const), or $(D immutable)).)
352 * $(LI Converts array (other than strings) _to string.
353 * Each element is converted by calling $(D to!T).)
354 * $(LI Associative array _to string conversion.
355 * Each element is printed by calling $(D to!T).)
356 * $(LI Object _to string conversion calls $(D toString) against the object or
357 * returns $(D "null") if the object is null.)
358 * $(LI Struct _to string conversion calls $(D toString) against the struct if
360 * $(LI For structs that do not define $(D toString), the conversion _to string
361 * produces the list of fields.)
362 * $(LI Enumerated types are converted _to strings as their symbolic names.)
363 * $(LI Boolean values are printed as $(D "true") or $(D "false").)
364 * $(LI $(D char), $(D wchar), $(D dchar) _to a string type.)
365 * $(LI Unsigned or signed integers _to strings.
366 * $(DL $(DT [special case])
367 * $(DD Convert integral value _to string in $(D_PARAM radix) radix.
368 * radix must be a value from 2 to 36.
369 * value is treated as a signed value only if radix is 10.
370 * The characters A through Z are used to represent values 10 through 36
371 * and their case is determined by the $(D_PARAM letterCase) parameter.)))
372 * $(LI All floating point types _to all string types.)
373 * $(LI Pointer to string conversions prints the pointer as a $(D size_t) value.
374 * If pointer is $(D char*), treat it as C-style strings.
375 * In that case, this function is $(D @system).))
377 @system pure unittest // @system due to cast and ptr
379 // Conversion representing dynamic/static array with string
380 long[] a = [ 1, 3, 5 ];
381 assert(to!string(a) == "[1, 3, 5]");
383 // Conversion representing associative array with string
384 int[string] associativeArray = ["0":1, "1":2];
385 assert(to!string(associativeArray) == `["0":1, "1":2]` ||
386 to!string(associativeArray) == `["1":2, "0":1]`);
388 // char* to string conversion
389 assert(to!string(cast(char*) null) == "");
390 assert(to!string("foo\0".ptr) == "foo");
392 // Conversion reinterpreting void array to string
395 assert(b.length == 8);
397 auto c = to!(wchar[])(b);
401 // Tests for issue 6175
402 @safe pure nothrow unittest
404 char[9] sarr = "blablabla";
405 auto darr = to!(char[])(sarr);
406 assert(sarr.ptr == darr.ptr);
407 assert(sarr.length == darr.length);
410 // Tests for issue 7348
411 @safe pure /+nothrow+/ unittest
413 assert(to!string(null) == "null");
414 assert(text(null) == "null");
417 // Tests for issue 11390
418 @safe pure /+nothrow+/ unittest
420 const(typeof(null)) ctn;
421 immutable(typeof(null)) itn;
422 assert(to!string(ctn) == "null");
423 assert(to!string(itn) == "null");
426 // Tests for issue 8729: do NOT skip leading WS
429 import std.exception;
430 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
432 assertThrown!ConvException(to!T(" 0"));
433 assertThrown!ConvException(to!T(" 0", 8));
435 foreach (T; AliasSeq!(float, double, real))
437 assertThrown!ConvException(to!T(" 0"));
440 assertThrown!ConvException(to!bool(" true"));
442 alias NullType = typeof(null);
443 assertThrown!ConvException(to!NullType(" null"));
446 assertThrown!ConvException(to!ARR(" [1]"));
449 assertThrown!ConvException(to!AA(" [1:1]"));
453 If the source type is implicitly convertible to the target type, $(D
454 to) simply performs the implicit conversion.
456 private T toImpl(T, S)(S value)
457 if (isImplicitlyConvertible!(S, T) &&
458 !isEnumStrToStr!(S, T) && !isNullToStr!(S, T))
460 template isSignedInt(T)
462 enum isSignedInt = isIntegral!T && isSigned!T;
464 alias isUnsignedInt = isUnsigned;
466 // Conversion from integer to integer, and changing its sign
467 static if (isUnsignedInt!S && isSignedInt!T && S.sizeof == T.sizeof)
468 { // unsigned to signed & same size
469 import std.exception : enforce;
470 enforce(value <= cast(S) T.max,
471 new ConvOverflowException("Conversion positive overflow"));
473 else static if (isSignedInt!S && isUnsignedInt!T)
474 { // signed to unsigned
475 import std.exception : enforce;
477 new ConvOverflowException("Conversion negative overflow"));
483 @safe pure nothrow unittest
485 enum E { a } // Issue 9523 - Allow identity enum conversion
490 @safe pure nothrow unittest
497 // Tests for issue 6377
500 import std.exception;
501 // Conversion between same size
502 foreach (S; AliasSeq!(byte, short, int, long))
503 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
504 alias U = Unsigned!S;
506 foreach (Sint; AliasSeq!(S, const S, immutable S))
507 foreach (Uint; AliasSeq!(U, const U, immutable U))
511 assertThrown!ConvOverflowException(to!Sint(un),
512 text(Sint.stringof, ' ', Uint.stringof, ' ', un));
516 assertThrown!ConvOverflowException(to!Uint(sn),
517 text(Sint.stringof, ' ', Uint.stringof, ' ', un));
521 // Conversion between different size
522 foreach (i, S1; AliasSeq!(byte, short, int, long))
523 foreach ( S2; AliasSeq!(byte, short, int, long)[i+1..$])
524 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
525 alias U1 = Unsigned!S1;
526 alias U2 = Unsigned!S2;
528 static assert(U1.sizeof < S2.sizeof);
530 // small unsigned to big signed
531 foreach (Uint; AliasSeq!(U1, const U1, immutable U1))
532 foreach (Sint; AliasSeq!(S2, const S2, immutable S2))
535 assertNotThrown(to!Sint(un));
536 assert(to!Sint(un) == un);
539 // big unsigned to small signed
540 foreach (Uint; AliasSeq!(U2, const U2, immutable U2))
541 foreach (Sint; AliasSeq!(S1, const S1, immutable S1))
544 assertThrown(to!Sint(un));
547 static assert(S1.sizeof < U2.sizeof);
549 // small signed to big unsigned
550 foreach (Sint; AliasSeq!(S1, const S1, immutable S1))
551 foreach (Uint; AliasSeq!(U2, const U2, immutable U2))
554 assertThrown!ConvOverflowException(to!Uint(sn));
557 // big signed to small unsigned
558 foreach (Sint; AliasSeq!(S2, const S2, immutable S2))
559 foreach (Uint; AliasSeq!(U1, const U1, immutable U1))
562 assertThrown!ConvOverflowException(to!Uint(sn));
568 Converting static arrays forwards to their dynamic counterparts.
570 private T toImpl(T, S)(ref S s)
573 return toImpl!(T, typeof(s[0])[])(s);
576 @safe pure nothrow unittest
578 char[4] test = ['a', 'b', 'c', 'd'];
579 static assert(!isInputRange!(Unqual!(char[4])));
580 assert(to!string(test) == test);
584 When source type supports member template function opCast, it is used.
586 private T toImpl(T, S)(S value)
587 if (!isImplicitlyConvertible!(S, T) &&
588 is(typeof(S.init.opCast!T()) : T) &&
589 !isExactSomeString!T &&
590 !is(typeof(T(value))))
592 return value.opCast!T();
601 this(S s) @safe pure { }
605 T opCast(U)() @safe pure { assert(false); }
608 cast(void) to!(Test.T)(Test.S());
610 // make sure std.conv.to is doing the same thing as initialization
619 T opCast(T)() { return 43; }
622 assert(to!int(b) == 43);
626 T opCast(T)() { return 43; }
629 assert(to!int(s) == 43);
633 When target type supports 'converting construction', it is used.
634 $(UL $(LI If target type is struct, $(D T(value)) is used.)
635 $(LI If target type is class, $(D new T(value)) is used.))
637 private T toImpl(T, S)(S value)
638 if (!isImplicitlyConvertible!(S, T) &&
639 is(T == struct) && is(typeof(T(value))))
656 this(int x) @safe pure { this.x = x; }
658 Int2 i2 = to!Int2(1);
663 static Int3 opCall(int x) @safe pure
670 Int3 i3 = to!Int3(1);
676 static struct FakeBigInt
678 this(string s) @safe pure {}
682 auto i3 = to!FakeBigInt(s);
686 private T toImpl(T, S)(S value)
687 if (!isImplicitlyConvertible!(S, T) &&
688 is(T == class) && is(typeof(new T(value))))
702 this(int x) @safe pure { this.x = x; }
708 this(S src) @safe pure { value = src.x; }
709 this(C src) @safe pure { value = src.x; }
713 auto b1 = to!B(s); // == new B(s)
714 assert(b1.value == 1);
717 auto b2 = to!B(c); // == new B(c)
718 assert(b2.value == 2);
720 auto c2 = to!C(3); // == new C(3)
730 this(B b) @safe pure {}
734 this() @safe pure { super(this); }
739 S.A a = to!(S.A)(b); // == cast(S.A) b
740 // (do not run construction conversion like new S.A(b))
743 static class C : Object
746 this(Object o) @safe pure {}
750 C a2 = to!C(oc); // == new C(a)
751 // Construction conversion overrides down-casting conversion
756 Object-to-object conversions by dynamic casting throw exception when the source is
757 non-null and the target is null.
759 private T toImpl(T, S)(S value)
760 if (!isImplicitlyConvertible!(S, T) &&
761 (is(S == class) || is(S == interface)) && !is(typeof(value.opCast!T()) : T) &&
762 (is(T == class) || is(T == interface)) && !is(typeof(new T(value))))
764 static if (is(T == immutable))
766 // immutable <- immutable
767 enum isModConvertible = is(S == immutable);
769 else static if (is(T == const))
771 static if (is(T == shared))
773 // shared const <- shared
774 // shared const <- shared const
775 // shared const <- immutable
776 enum isModConvertible = is(S == shared) || is(S == immutable);
781 // const <- immutable
782 enum isModConvertible = !is(S == shared);
787 static if (is(T == shared))
789 // shared <- shared mutable
790 enum isModConvertible = is(S == shared) && !is(S == const);
794 // (mutable) <- (mutable)
795 enum isModConvertible = is(Unqual!S == S);
798 static assert(isModConvertible, "Bad modifier conversion: "~S.stringof~" to "~T.stringof);
800 auto result = ()@trusted{ return cast(T) value; }();
801 if (!result && value)
803 throw new ConvException("Cannot convert object of static type "
804 ~S.classinfo.name~" and dynamic type "~value.classinfo.name
805 ~" to type "~T.classinfo.name);
813 import std.exception;
815 alias Identity(T) = T;
816 alias toConst(T) = const T;
817 alias toShared(T) = shared T;
818 alias toSharedConst(T) = shared const T;
819 alias toImmutable(T) = immutable T;
820 template AddModifier(int n)
823 static if (n == 0) alias AddModifier = Identity;
824 else static if (n == 1) alias AddModifier = toConst;
825 else static if (n == 2) alias AddModifier = toShared;
826 else static if (n == 3) alias AddModifier = toSharedConst;
827 else static if (n == 4) alias AddModifier = toImmutable;
838 foreach (m1; AliasSeq!(0,1,2,3,4)) // enumerate modifiers
839 foreach (m2; AliasSeq!(0,1,2,3,4)) // ditto
840 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
841 alias srcmod = AddModifier!m1;
842 alias tgtmod = AddModifier!m2;
844 // Compile time convertible equals to modifier convertible.
845 static if (isImplicitlyConvertible!(srcmod!Object, tgtmod!Object))
847 // Test runtime conversions: class to class, class to interface,
848 // interface to class, and interface to interface
850 // Check that the runtime conversion to succeed
851 srcmod!A ac = new srcmod!C();
852 srcmod!I ic = new srcmod!C();
853 assert(to!(tgtmod!C)(ac) !is null); // A(c) to C
854 assert(to!(tgtmod!I)(ac) !is null); // A(c) to I
855 assert(to!(tgtmod!C)(ic) !is null); // I(c) to C
856 assert(to!(tgtmod!J)(ic) !is null); // I(c) to J
858 // Check that the runtime conversion fails
859 srcmod!A ab = new srcmod!B();
860 srcmod!I id = new srcmod!D();
861 assertThrown(to!(tgtmod!C)(ab)); // A(b) to C
862 assertThrown(to!(tgtmod!I)(ab)); // A(b) to I
863 assertThrown(to!(tgtmod!C)(id)); // I(d) to C
864 assertThrown(to!(tgtmod!J)(id)); // I(d) to J
868 // Check that the conversion is rejected statically
869 static assert(!is(typeof(to!(tgtmod!C)(srcmod!A.init)))); // A to C
870 static assert(!is(typeof(to!(tgtmod!I)(srcmod!A.init)))); // A to I
871 static assert(!is(typeof(to!(tgtmod!C)(srcmod!I.init)))); // I to C
872 static assert(!is(typeof(to!(tgtmod!J)(srcmod!I.init)))); // I to J
878 Handles type _to string conversions
880 private T toImpl(T, S)(S value)
881 if (!(isImplicitlyConvertible!(S, T) &&
882 !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
883 !isInfinite!S && isExactSomeString!T)
885 static if (isExactSomeString!S && value[0].sizeof == ElementEncodingType!T.sizeof)
887 // string-to-string with incompatible qualifier conversion
888 static if (is(ElementEncodingType!T == immutable))
890 // conversion (mutable|const) -> immutable
895 // conversion (immutable|const) -> mutable
899 else static if (isExactSomeString!S)
901 import std.array : appender;
902 // other string-to-string
903 //Use Appender directly instead of toStr, which also uses a formatedWrite
904 auto w = appender!T();
908 else static if (isIntegral!S && !is(S == enum))
910 // other integral-to-string conversions with default radix
911 return toImpl!(T, S)(value, 10);
913 else static if (is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[]))
915 import core.stdc.string : memcpy;
916 import std.exception : enforce;
917 // Converting void array to string
918 alias Char = Unqual!(ElementEncodingType!T);
919 auto raw = cast(const(ubyte)[]) value;
920 enforce(raw.length % Char.sizeof == 0,
921 new ConvException("Alignment mismatch in converting a "
922 ~ S.stringof ~ " to a "
924 auto result = new Char[raw.length / Char.sizeof];
925 ()@trusted{ memcpy(result.ptr, value.ptr, value.length); }();
926 return cast(T) result;
928 else static if (isPointer!S && isSomeChar!(PointerTarget!S))
930 // This is unsafe because we cannot guarantee that the pointer is null terminated.
932 static if (is(S : const(char)*))
933 import core.stdc.string : strlen;
935 size_t strlen(S s) nothrow
941 return toImpl!T(value ? value[0 .. strlen(value)].dup : null);
944 else static if (isSomeString!T && is(S == enum))
946 static if (isSwitchable!(OriginalType!S) && EnumMembers!S.length <= 50)
950 foreach (member; NoDuplicates!(EnumMembers!S))
953 return to!T(enumRep!(immutable(T), S, member));
960 foreach (member; EnumMembers!S)
963 return to!T(enumRep!(immutable(T), S, member));
967 import std.array : appender;
968 import std.format : FormatSpec, formatValue;
970 //Default case, delegate to format
971 //Note: we don't call toStr directly, to avoid duplicate work.
972 auto app = appender!T();
973 app.put("cast(" ~ S.stringof ~ ")");
975 formatValue(app, cast(OriginalType!S) value, f);
980 // other non-string values runs formatting
981 return toStr!T(value);
988 immutable(char)* ptr = "hello".ptr;
989 auto result = ptr.to!(char[]);
994 void test1(T)(T lp, string cmp)
996 foreach (e; AliasSeq!(char, wchar, dchar))
998 test2!(e[])(lp, cmp);
999 test2!(const(e)[])(lp, cmp);
1000 test2!(immutable(e)[])(lp, cmp);
1004 void test2(D, S)(S lp, string cmp)
1006 assert(to!string(to!D(lp)) == cmp);
1009 foreach (e; AliasSeq!("Hello, world!", "Hello, world!"w, "Hello, world!"d))
1011 test1(e, "Hello, world!");
1012 test1(e.ptr, "Hello, world!");
1014 foreach (e; AliasSeq!("", ""w, ""d))
1022 To string conversion for non copy-able structs
1024 private T toImpl(T, S)(ref S value)
1025 if (!(isImplicitlyConvertible!(S, T) &&
1026 !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
1027 !isInfinite!S && isExactSomeString!T && !isCopyable!S)
1029 import std.array : appender;
1030 import std.format : FormatSpec, formatValue;
1032 auto w = appender!T();
1033 FormatSpec!(ElementEncodingType!T) f;
1034 formatValue(w, value, f);
1046 string toString() { return text(val, ":", flag); }
1048 @disable this(this);
1052 assert(to!string(a) == "0:false");
1059 @disable this(this);
1063 assert(to!string(b) == "B(0, false)");
1067 Check whether type $(D T) can be used in a switch statement.
1068 This is useful for compile-time generation of switch case statements.
1070 private template isSwitchable(E)
1072 enum bool isSwitchable = is(typeof({
1073 switch (E.init) { default: }
1080 static assert(isSwitchable!int);
1081 static assert(!isSwitchable!double);
1082 static assert(!isSwitchable!real);
1085 //Static representation of the index I of the enum S,
1086 //In representation T.
1087 //T must be an immutable string (avoids un-necessary initializations).
1088 private template enumRep(T, S, S value)
1089 if (is (T == immutable) && isExactSomeString!T && is(S == enum))
1091 static T enumRep = toStr!T(value);
1096 import std.exception;
1099 // string to string conversion
1100 alias Chars = AliasSeq!(char, wchar, dchar);
1101 foreach (LhsC; Chars)
1103 alias LhStrings = AliasSeq!(LhsC[], const(LhsC)[], immutable(LhsC)[]);
1104 foreach (Lhs; LhStrings)
1106 foreach (RhsC; Chars)
1108 alias RhStrings = AliasSeq!(RhsC[], const(RhsC)[], immutable(RhsC)[]);
1109 foreach (Rhs; RhStrings)
1111 Lhs s1 = to!Lhs("wyda");
1112 Rhs s2 = to!Rhs(s1);
1113 //writeln(Lhs.stringof, " -> ", Rhs.stringof);
1114 assert(s1 == to!Lhs(s2));
1124 T[] s1 = to!(T[])("Hello, world!");
1125 auto s2 = to!(U[])(s1);
1126 assert(s1 == to!(T[])(s2));
1127 auto s3 = to!(const(U)[])(s1);
1128 assert(s1 == to!(T[])(s3));
1129 auto s4 = to!(immutable(U)[])(s1);
1130 assert(s1 == to!(T[])(s4));
1140 // Conversion representing bool value with string
1142 assert(to!string(b) == "false");
1144 assert(to!string(b) == "true");
1149 // Conversion representing character value with string
1151 AliasSeq!( char, const( char), immutable( char),
1152 wchar, const(wchar), immutable(wchar),
1153 dchar, const(dchar), immutable(dchar));
1154 foreach (Char1; AllChars)
1156 foreach (Char2; AllChars)
1159 assert(to!(Char2[])(c)[0] == c);
1162 assert(to!(Char1[])(x) == "4");
1171 assert(s2 == "foo");
1174 @safe pure nothrow unittest
1176 import std.exception;
1177 // Conversion representing integer values with string
1179 foreach (Int; AliasSeq!(ubyte, ushort, uint, ulong))
1181 assert(to!string(Int(0)) == "0");
1182 assert(to!string(Int(9)) == "9");
1183 assert(to!string(Int(123)) == "123");
1186 foreach (Int; AliasSeq!(byte, short, int, long))
1188 assert(to!string(Int(0)) == "0");
1189 assert(to!string(Int(9)) == "9");
1190 assert(to!string(Int(123)) == "123");
1191 assert(to!string(Int(-0)) == "0");
1192 assert(to!string(Int(-9)) == "-9");
1193 assert(to!string(Int(-123)) == "-123");
1194 assert(to!string(const(Int)(6)) == "6");
1197 assert(wtext(int.max) == "2147483647"w);
1198 assert(wtext(int.min) == "-2147483648"w);
1199 assert(to!string(0L) == "0");
1203 assert(to!string(1uL << 62) == "4611686018427387904");
1204 assert(to!string(0x100000000) == "4294967296");
1205 assert(to!string(-138L) == "-138");
1209 @safe unittest // sprintf issue
1211 double[2] a = [ 1.5, 2.5 ];
1212 assert(to!string(a) == "[1.5, 2.5]");
1217 // Conversion representing class object with string
1220 override string toString() const { return "an A"; }
1223 assert(to!string(a) == "null");
1225 assert(to!string(a) == "an A");
1228 class C { override string toString() const { return "C"; } }
1229 struct S { C c; alias c this; }
1231 assert(to!string(s) == "C");
1236 // Conversion representing struct object with string
1239 string toString() { return "wyda"; }
1241 assert(to!string(S1()) == "wyda");
1249 assert(to!string(s2) == "S2(42, 43.5)");
1251 // Test for issue 8080
1256 string toString() { return "<S>"; }
1259 assert(to!string(s8080) == "<S>");
1264 // Conversion representing enum value with string
1265 enum EB : bool { a = true }
1266 enum EU : uint { a = 0, b = 1, c = 2 } // base type is unsigned
1267 enum EI : int { a = -1, b = 0, c = 1 } // base type is signed (bug 7909)
1268 enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
1269 enum EC : char { a = 'x', b = 'y' }
1270 enum ES : string { a = "aaa", b = "bbb" }
1272 foreach (E; AliasSeq!(EB, EU, EI, EF, EC, ES))
1274 assert(to! string(E.a) == "a"c);
1275 assert(to!wstring(E.a) == "a"w);
1276 assert(to!dstring(E.a) == "a"d);
1279 // Test an value not corresponding to an enum member.
1280 auto o = cast(EU) 5;
1281 assert(to! string(o) == "cast(EU)5"c);
1282 assert(to!wstring(o) == "cast(EU)5"w);
1283 assert(to!dstring(o) == "cast(EU)5"d);
1291 doo = foo, // check duplicate switch statements
1295 //Test regression 12494
1296 assert(to!string(E.foo) == "foo");
1297 assert(to!string(E.doo) == "foo");
1298 assert(to!string(E.bar) == "bar");
1300 foreach (S; AliasSeq!(string, wstring, dstring, const(char[]), const(wchar[]), const(dchar[])))
1302 auto s1 = to!S(E.foo);
1303 auto s2 = to!S(E.foo);
1305 // ensure we don't allocate when it's unnecessary
1309 foreach (S; AliasSeq!(char[], wchar[], dchar[]))
1311 auto s1 = to!S(E.foo);
1312 auto s2 = to!S(E.foo);
1314 // ensure each mutable array is unique
1320 @trusted pure private T toImpl(T, S)(S value, uint radix, LetterCase letterCase = LetterCase.upper)
1322 isExactSomeString!T)
1325 assert(radix >= 2 && radix <= 36);
1329 alias EEType = Unqual!(ElementEncodingType!T);
1331 T toStringRadixConvert(size_t bufLen)(uint runtimeRadix = 0)
1333 Unsigned!(Unqual!S) div = void, mValue = unsigned(value);
1335 size_t index = bufLen;
1336 EEType[bufLen] buffer = void;
1337 char baseChar = letterCase == LetterCase.lower ? 'a' : 'A';
1342 div = cast(S)(mValue / runtimeRadix );
1343 mod = cast(ubyte)(mValue % runtimeRadix);
1344 mod += mod < 10 ? '0' : baseChar - 10;
1345 buffer[--index] = cast(char) mod;
1349 return cast(T) buffer[index .. $].dup;
1352 import std.array : array;
1356 // The (value+0) is so integral promotions happen to the type
1357 return toChars!(10, EEType)(value + 0).array;
1359 // The unsigned(unsigned(value)+0) is so unsigned integral promotions happen to the type
1360 if (letterCase == letterCase.upper)
1361 return toChars!(16, EEType, LetterCase.upper)(unsigned(unsigned(value) + 0)).array;
1363 return toChars!(16, EEType, LetterCase.lower)(unsigned(unsigned(value) + 0)).array;
1365 return toChars!(2, EEType)(unsigned(unsigned(value) + 0)).array;
1367 return toChars!(8, EEType)(unsigned(unsigned(value) + 0)).array;
1370 return toStringRadixConvert!(S.sizeof * 6)(radix);
1374 @safe pure nothrow unittest
1376 foreach (Int; AliasSeq!(uint, ulong))
1378 assert(to!string(Int(16), 16) == "10");
1379 assert(to!string(Int(15), 2u) == "1111");
1380 assert(to!string(Int(1), 2u) == "1");
1381 assert(to!string(Int(0x1234AF), 16u) == "1234AF");
1382 assert(to!string(Int(0x1234BCD), 16u, LetterCase.upper) == "1234BCD");
1383 assert(to!string(Int(0x1234AF), 16u, LetterCase.lower) == "1234af");
1386 foreach (Int; AliasSeq!(int, long))
1388 assert(to!string(Int(-10), 10u) == "-10");
1391 assert(to!string(byte(-10), 16) == "F6");
1392 assert(to!string(long.min) == "-9223372036854775808");
1393 assert(to!string(long.max) == "9223372036854775807");
1397 Narrowing numeric-numeric conversions throw when the value does not
1398 fit in the narrower type.
1400 private T toImpl(T, S)(S value)
1401 if (!isImplicitlyConvertible!(S, T) &&
1402 (isNumeric!S || isSomeChar!S || isBoolean!S) &&
1403 (isNumeric!T || isSomeChar!T || isBoolean!T) && !is(T == enum))
1405 enum sSmallest = mostNegative!S;
1406 enum tSmallest = mostNegative!T;
1407 static if (sSmallest < 0)
1409 // possible underflow converting from a signed
1410 static if (tSmallest == 0)
1412 immutable good = value >= 0;
1416 static assert(tSmallest < 0);
1417 immutable good = value >= tSmallest;
1420 throw new ConvOverflowException("Conversion negative overflow");
1422 static if (S.max > T.max)
1424 // possible overflow
1426 throw new ConvOverflowException("Conversion positive overflow");
1428 return (ref value)@trusted{ return cast(T) value; }(value);
1433 import std.exception;
1436 assert(to!char(a) == ' ');
1438 assert(collectException(to!char(a)));
1441 char to0 = to!char(from0);
1444 char to1 = to!char(from1);
1447 char to2 = to!char(from2);
1450 wchar to3 = to!wchar(from3);
1453 dchar to4 = to!dchar(from4);
1458 import std.exception;
1460 // Narrowing conversions from enum -> integral should be allowed, but they
1461 // should throw at runtime if the enum value doesn't fit in the target
1463 enum E1 : ulong { A = 1, B = 1UL << 48, C = 0 }
1464 assert(to!int(E1.A) == 1);
1465 assert(to!bool(E1.A) == true);
1466 assertThrown!ConvOverflowException(to!int(E1.B)); // E1.B overflows int
1467 assertThrown!ConvOverflowException(to!bool(E1.B)); // E1.B overflows bool
1468 assert(to!bool(E1.C) == false);
1470 enum E2 : long { A = -1L << 48, B = -1 << 31, C = 1 << 31 }
1471 assertThrown!ConvOverflowException(to!int(E2.A)); // E2.A overflows int
1472 assertThrown!ConvOverflowException(to!uint(E2.B)); // E2.B overflows uint
1473 assert(to!int(E2.B) == -1 << 31); // but does not overflow int
1474 assert(to!int(E2.C) == 1 << 31); // E2.C does not overflow int
1476 enum E3 : int { A = -1, B = 1, C = 255, D = 0 }
1477 assertThrown!ConvOverflowException(to!ubyte(E3.A));
1478 assertThrown!ConvOverflowException(to!bool(E3.A));
1479 assert(to!byte(E3.A) == -1);
1480 assert(to!byte(E3.B) == 1);
1481 assert(to!ubyte(E3.C) == 255);
1482 assert(to!bool(E3.B) == true);
1483 assertThrown!ConvOverflowException(to!byte(E3.C));
1484 assertThrown!ConvOverflowException(to!bool(E3.C));
1485 assert(to!bool(E3.D) == false);
1490 Array-to-array conversion (except when target is a string type)
1491 converts each element in turn by using $(D to).
1493 private T toImpl(T, S)(S value)
1494 if (!isImplicitlyConvertible!(S, T) &&
1495 !isSomeString!S && isDynamicArray!S &&
1496 !isExactSomeString!T && isArray!T)
1498 alias E = typeof(T.init[0]);
1500 static if (isStaticArray!T)
1502 import std.exception : enforce;
1503 auto res = to!(E[])(value);
1504 enforce!ConvException(T.length == res.length,
1505 convFormat("Length mismatch when converting to static array: %s vs %s", T.length, res.length));
1506 return res[0 .. T.length];
1510 import std.array : appender;
1511 auto w = appender!(E[])();
1512 w.reserve(value.length);
1513 foreach (i, ref e; value)
1523 import std.exception;
1525 // array to array conversions
1526 uint[] a = [ 1u, 2, 3 ];
1527 auto b = to!(float[])(a);
1528 assert(b == [ 1.0f, 2, 3 ]);
1530 immutable(int)[3] d = [ 1, 2, 3 ];
1531 b = to!(float[])(d);
1532 assert(b == [ 1.0f, 2, 3 ]);
1534 uint[][] e = [ a, a ];
1535 auto f = to!(float[][])(e);
1536 assert(f[0] == b && f[1] == b);
1538 // Test for bug 8264
1544 Wrap[] warr = to!(Wrap[])(["foo", "bar"]); // should work
1547 import std.conv : to;
1548 const s2 = ["10", "20"];
1550 immutable int[2] a3 = s2.to!(int[2]);
1551 assert(a3 == [10, 20]);
1553 // verify length mismatches are caught
1554 immutable s4 = [1, 2, 3, 4];
1557 auto ex = collectException(s4[0 .. i].to!(int[2]));
1558 assert(ex && ex.msg == "Length mismatch when converting to static array: 2 vs " ~ [cast(char)(i + '0')],
1559 ex ? ex.msg : "Exception was not thrown!");
1565 auto b = [ 1.0f, 2, 3 ];
1567 auto c = to!(string[])(b);
1568 assert(c[0] == "1" && c[1] == "2" && c[2] == "3");
1572 Associative array to associative array conversion converts each key
1573 and each value in turn.
1575 private T toImpl(T, S)(S value)
1576 if (isAssociativeArray!S &&
1577 isAssociativeArray!T && !is(T == enum))
1579 /* This code is potentially unsafe.
1581 alias K2 = KeyType!T;
1582 alias V2 = ValueType!T;
1584 // While we are "building" the AA, we need to unqualify its values, and only re-qualify at the end
1585 Unqual!V2[K2] result;
1587 foreach (k1, v1; value)
1589 // Cast values temporarily to Unqual!V2 to store them to result variable
1590 result[to!K2(k1)] = cast(Unqual!V2) to!V2(v1);
1592 // Cast back to original type
1593 return cast(T) result;
1598 // hash to hash conversions
1602 auto b = to!(double[dstring])(a);
1603 assert(b["0"d] == 1 && b["1"d] == 2);
1605 @safe unittest // Bugzilla 8705, from doc
1607 import std.exception;
1608 int[string][double[int[]]] a;
1609 auto b = to!(short[wstring][string[double[]]])(a);
1610 a = [null:["hello":int.max]];
1611 assertThrown!ConvOverflowException(to!(short[wstring][string[double[]]])(a));
1613 @system unittest // Extra cases for AA with qualifiers conversion
1615 int[][int[]] a;// = [[], []];
1616 auto b = to!(immutable(short[])[immutable short[]])(a);
1618 double[dstring][int[long[]]] c;
1619 auto d = to!(immutable(short[immutable wstring])[immutable string[double[]]])(c);
1622 private void testIntegralToFloating(Integral, Floating)()
1625 auto b = to!Floating(a);
1627 assert(a == to!Integral(b));
1630 private void testFloatingToIntegral(Floating, Integral)()
1632 bool convFails(Source, Target, E)(Source src)
1635 auto t = to!Target(src);
1641 // convert some value
1643 auto b = to!Integral(a);
1644 assert(is(typeof(b) == Integral) && b == 42);
1645 // convert some negative value (if applicable)
1647 static if (Integral.min < 0)
1650 assert(is(typeof(b) == Integral) && b == -42);
1654 // no go for unsigned types
1655 assert(convFails!(Floating, Integral, ConvOverflowException)(a));
1657 // convert to the smallest integral value
1658 a = 0.0 + Integral.min;
1659 static if (Integral.min < 0)
1661 a = -a; // -Integral.min not representable as an Integral
1662 assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1663 || Floating.sizeof <= Integral.sizeof);
1665 a = 0.0 + Integral.min;
1666 assert(to!Integral(a) == Integral.min);
1667 --a; // no more representable as an Integral
1668 assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1669 || Floating.sizeof <= Integral.sizeof);
1670 a = 0.0 + Integral.max;
1671 assert(to!Integral(a) == Integral.max || Floating.sizeof <= Integral.sizeof);
1672 ++a; // no more representable as an Integral
1673 assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1674 || Floating.sizeof <= Integral.sizeof);
1675 // convert a value with a fractional part
1677 assert(to!Integral(a) == 3);
1679 assert(to!Integral(a) == 3);
1680 static if (Integral.min < 0)
1683 assert(to!Integral(a) == -3);
1685 assert(to!Integral(a) == -3);
1691 alias AllInts = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong);
1692 alias AllFloats = AliasSeq!(float, double, real);
1693 alias AllNumerics = AliasSeq!(AllInts, AllFloats);
1694 // test with same type
1696 foreach (T; AllNumerics)
1700 assert(is(typeof(a) == typeof(b)) && a == b);
1703 // test that floating-point numbers convert properly to largest ints
1704 // see http://oregonstate.edu/~peterseb/mth351/docs/351s2001_fp80x87.html
1705 // look for "largest fp integer with a predecessor"
1708 int a = 16_777_215; // 2^24 - 1
1709 assert(to!int(to!float(a)) == a);
1710 assert(to!int(to!float(-a)) == -a);
1712 long b = 9_007_199_254_740_991; // 2^53 - 1
1713 assert(to!long(to!double(b)) == b);
1714 assert(to!long(to!double(-b)) == -b);
1716 static if (real.mant_dig >= 64)
1718 ulong c = 18_446_744_073_709_551_615UL; // 2^64 - 1
1719 assert(to!ulong(to!real(c)) == c);
1722 // test conversions floating => integral
1724 // AllInts[0 .. $ - 1] should be AllInts
1725 // @@@ BUG IN COMPILER @@@
1726 foreach (Integral; AllInts[0 .. $ - 1])
1728 foreach (Floating; AllFloats)
1730 testFloatingToIntegral!(Floating, Integral)();
1734 // test conversion integral => floating
1736 foreach (Integral; AllInts[0 .. $ - 1])
1738 foreach (Floating; AllFloats)
1740 testIntegralToFloating!(Integral, Floating)();
1746 foreach (T; AllNumerics)
1748 // from type immutable(char)[2]
1749 auto a = to!T("42");
1752 char[] s1 = "42".dup;
1755 // from type char[2]
1760 // from type immutable(wchar)[2]
1769 alias AllInts = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong);
1770 alias AllFloats = AliasSeq!(float, double, real);
1771 alias AllNumerics = AliasSeq!(AllInts, AllFloats);
1772 // test conversions to string
1774 foreach (T; AllNumerics)
1777 assert(to!string(a) == "42");
1778 assert(to!wstring(a) == "42"w);
1779 assert(to!dstring(a) == "42"d);
1784 assert(to!string(b) == "[42, 33]");
1787 // test array to string conversion
1788 foreach (T ; AllNumerics)
1790 auto a = [to!T(1), 2, 3];
1791 assert(to!string(a) == "[1, 2, 3]");
1793 // test enum to int conversion
1794 enum Testing { Test1, Test2 }
1796 auto a = to!string(t);
1797 assert(a == "Test1");
1802 String, or string-like input range, to non-string conversion runs parsing.
1804 $(LI When the source is a wide string, it is first converted to a narrow
1805 string and then parsed.)
1806 $(LI When the source is a narrow string, normal text parsing occurs.))
1808 private T toImpl(T, S)(S value)
1809 if (isInputRange!S && isSomeChar!(ElementEncodingType!S) &&
1810 !isExactSomeString!T && is(typeof(parse!T(value))))
1816 throw convError!(S, T)(value);
1819 return parse!T(value);
1823 private T toImpl(T, S)(S value, uint radix)
1824 if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S) &&
1825 isIntegral!T && is(typeof(parse!T(value, radix))))
1831 throw convError!(S, T)(value);
1834 return parse!T(value, radix);
1839 // Issue 6668 - ensure no collaterals thrown
1840 try { to!uint("-1"); }
1841 catch (ConvException e) { assert(e.next is null); }
1846 foreach (Str; AliasSeq!(string, wstring, dstring))
1849 assert(to!int(a) == 123);
1850 assert(to!double(a) == 123);
1854 auto n = to!int("FF", 16);
1861 import std.utf : byCodeUnit, byChar, byWchar, byDchar;
1863 assert(to!int(byCodeUnit("10")) == 10);
1864 assert(to!int(byCodeUnit("10"), 10) == 10);
1865 assert(to!int(byCodeUnit("10"w)) == 10);
1866 assert(to!int(byCodeUnit("10"w), 10) == 10);
1868 assert(to!int(byChar("10")) == 10);
1869 assert(to!int(byChar("10"), 10) == 10);
1870 assert(to!int(byWchar("10")) == 10);
1871 assert(to!int(byWchar("10"), 10) == 10);
1872 assert(to!int(byDchar("10")) == 10);
1873 assert(to!int(byDchar("10"), 10) == 10);
1877 Convert a value that is implicitly convertible to the enum base type
1878 into an Enum value. If the value does not match any enum member values
1879 a ConvException is thrown.
1880 Enums with floating-point or string base types are not supported.
1882 private T toImpl(T, S)(S value)
1883 if (is(T == enum) && !is(S == enum)
1884 && is(typeof(value == OriginalType!T.init))
1885 && !isFloatingPoint!(OriginalType!T) && !isSomeString!(OriginalType!T))
1887 foreach (Member; EnumMembers!T)
1889 if (Member == value)
1892 throw new ConvException(convFormat("Value (%s) does not match any member value of enum '%s'", value, T.stringof));
1897 import std.exception;
1898 enum En8143 : int { A = 10, B = 20, C = 30, D = 20 }
1899 enum En8143[][] m3 = to!(En8143[][])([[10, 30], [30, 10]]);
1900 static assert(m3 == [[En8143.A, En8143.C], [En8143.C, En8143.A]]);
1902 En8143 en1 = to!En8143(10);
1903 assert(en1 == En8143.A);
1904 assertThrown!ConvException(to!En8143(5)); // matches none
1905 En8143[][] m1 = to!(En8143[][])([[10, 30], [30, 10]]);
1906 assert(m1 == [[En8143.A, En8143.C], [En8143.C, En8143.A]]);
1909 /***************************************************************
1910 Rounded conversion from floating point to integral.
1912 Rounded conversions do not work with non-integral target types.
1915 template roundTo(Target)
1917 Target roundTo(Source)(Source value)
1919 import std.math : trunc;
1921 static assert(isFloatingPoint!Source);
1922 static assert(isIntegral!Target);
1923 return to!Target(trunc(value + (value < 0 ? -0.5L : 0.5L)));
1930 assert(roundTo!int(3.14) == 3);
1931 assert(roundTo!int(3.49) == 3);
1932 assert(roundTo!int(3.5) == 4);
1933 assert(roundTo!int(3.999) == 4);
1934 assert(roundTo!int(-3.14) == -3);
1935 assert(roundTo!int(-3.49) == -3);
1936 assert(roundTo!int(-3.5) == -4);
1937 assert(roundTo!int(-3.999) == -4);
1938 assert(roundTo!(const int)(to!(const double)(-3.999)) == -4);
1943 import std.exception;
1945 foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint))
1947 assert(roundTo!Int(Int.min - 0.4L) == Int.min);
1948 assert(roundTo!Int(Int.max + 0.4L) == Int.max);
1949 assertThrown!ConvOverflowException(roundTo!Int(Int.min - 0.5L));
1950 assertThrown!ConvOverflowException(roundTo!Int(Int.max + 0.5L));
1955 The $(D parse) family of functions works quite like the $(D to)
1956 family, except that:
1958 $(LI It only works with character ranges as input.)
1959 $(LI It takes the input by reference. (This means that rvalues - such
1960 as string literals - are not accepted: use $(D to) instead.))
1961 $(LI It advances the input to the position following the conversion.)
1962 $(LI It does not throw if it could not convert the entire input.))
1964 This overload converts an character input range to a `bool`.
1967 Target = the type to convert to
1968 source = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
1974 A $(LREF ConvException) if the range does not represent a `bool`.
1977 All character input range conversions using $(LREF to) are forwarded
1978 to `parse` and do not require lvalues.
1980 Target parse(Target, Source)(ref Source source)
1981 if (isInputRange!Source &&
1982 isSomeChar!(ElementType!Source) &&
1983 is(Unqual!Target == bool))
1985 import std.ascii : toLower;
1987 static if (isNarrowString!Source)
1989 import std.string : representation;
1990 auto s = source.representation;
1999 auto c1 = toLower(s.front);
2000 bool result = c1 == 't';
2001 if (result || c1 == 'f')
2004 foreach (c; result ? "rue" : "alse")
2006 if (s.empty || toLower(s.front) != c)
2011 static if (isNarrowString!Source)
2012 source = cast(Source) s;
2018 throw parseError("bool should be case-insensitive 'true' or 'false'");
2025 bool b = parse!bool(s);
2031 import std.algorithm.comparison : equal;
2032 import std.exception;
2036 @property auto front() { return _s.front; }
2037 @property bool empty() { return _s.empty; }
2038 void popFront() { _s.popFront(); }
2041 auto s = InputString("trueFALSETrueFalsetRUEfALSE");
2042 assert(parse!bool(s) == true);
2043 assert(s.equal("FALSETrueFalsetRUEfALSE"));
2044 assert(parse!bool(s) == false);
2045 assert(s.equal("TrueFalsetRUEfALSE"));
2046 assert(parse!bool(s) == true);
2047 assert(s.equal("FalsetRUEfALSE"));
2048 assert(parse!bool(s) == false);
2049 assert(s.equal("tRUEfALSE"));
2050 assert(parse!bool(s) == true);
2051 assert(s.equal("fALSE"));
2052 assert(parse!bool(s) == false);
2055 foreach (ss; ["tfalse", "ftrue", "t", "f", "tru", "fals", ""])
2057 s = InputString(ss);
2058 assertThrown!ConvException(parse!bool(s));
2063 Parses a character $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
2064 to an integral value.
2067 Target = the integral type to convert to
2068 s = the lvalue of an input range
2071 A number of type `Target`
2074 A $(LREF ConvException) If an overflow occurred during conversion or
2075 if no character of the input was meaningfully converted.
2077 Target parse(Target, Source)(ref Source s)
2078 if (isSomeChar!(ElementType!Source) &&
2079 isIntegral!Target && !is(Target == enum))
2081 static if (Target.sizeof < int.sizeof)
2083 // smaller types are handled like integers
2084 auto v = .parse!(Select!(Target.min < 0, int, uint))(s);
2085 auto result = ()@trusted{ return cast(Target) v; }();
2088 throw new ConvOverflowException("Overflow in integral conversion");
2092 // int or larger types
2094 static if (Target.min < 0)
2097 enum bool sign = false;
2099 enum char maxLastDigit = Target.min < 0 ? 7 : 5;
2102 static if (isNarrowString!Source)
2104 import std.string : representation;
2105 auto source = s.representation;
2117 static if (Target.min < 0)
2141 Target v = cast(Target) c;
2145 while (!source.empty)
2147 c = cast(typeof(c)) (source.front - '0');
2152 if (v >= 0 && (v < Target.max/10 ||
2153 (v == Target.max/10 && c <= maxLastDigit + sign)))
2155 // Note: `v` can become negative here in case of parsing
2156 // the most negative value:
2157 v = cast(Target) (v * 10 + c);
2162 throw new ConvOverflowException("Overflow in integral conversion");
2168 static if (isNarrowString!Source)
2169 s = cast(Source) source;
2174 static if (isNarrowString!Source)
2175 throw convError!(Source, Target)(cast(Source) source);
2177 throw convError!(Source, Target)(source);
2185 auto a = parse!int(s);
2188 // parse only accepts lvalues
2189 static assert(!__traits(compiles, parse!int("123")));
2195 import std.string : tr;
2196 string test = "123 \t 76.14";
2197 auto a = parse!uint(test);
2199 assert(test == " \t 76.14"); // parse bumps string
2200 test = tr(test, " \t\n\r", "", "d"); // skip ws
2201 assert(test == "76.14");
2202 auto b = parse!double(test);
2209 foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2212 assert(to!Int("0") == 0);
2214 static if (isSigned!Int)
2216 assert(to!Int("+0") == 0);
2217 assert(to!Int("-0") == 0);
2221 static if (Int.sizeof >= byte.sizeof)
2223 assert(to!Int("6") == 6);
2224 assert(to!Int("23") == 23);
2225 assert(to!Int("68") == 68);
2226 assert(to!Int("127") == 0x7F);
2228 static if (isUnsigned!Int)
2230 assert(to!Int("255") == 0xFF);
2232 static if (isSigned!Int)
2234 assert(to!Int("+6") == 6);
2235 assert(to!Int("+23") == 23);
2236 assert(to!Int("+68") == 68);
2237 assert(to!Int("+127") == 0x7F);
2239 assert(to!Int("-6") == -6);
2240 assert(to!Int("-23") == -23);
2241 assert(to!Int("-68") == -68);
2242 assert(to!Int("-128") == -128);
2246 static if (Int.sizeof >= short.sizeof)
2248 assert(to!Int("468") == 468);
2249 assert(to!Int("32767") == 0x7FFF);
2251 static if (isUnsigned!Int)
2253 assert(to!Int("65535") == 0xFFFF);
2255 static if (isSigned!Int)
2257 assert(to!Int("+468") == 468);
2258 assert(to!Int("+32767") == 0x7FFF);
2260 assert(to!Int("-468") == -468);
2261 assert(to!Int("-32768") == -32768);
2265 static if (Int.sizeof >= int.sizeof)
2267 assert(to!Int("2147483647") == 0x7FFFFFFF);
2269 static if (isUnsigned!Int)
2271 assert(to!Int("4294967295") == 0xFFFFFFFF);
2274 static if (isSigned!Int)
2276 assert(to!Int("+2147483647") == 0x7FFFFFFF);
2278 assert(to!Int("-2147483648") == -2147483648);
2282 static if (Int.sizeof >= long.sizeof)
2284 assert(to!Int("9223372036854775807") == 0x7FFFFFFFFFFFFFFF);
2286 static if (isUnsigned!Int)
2288 assert(to!Int("18446744073709551615") == 0xFFFFFFFFFFFFFFFF);
2291 static if (isSigned!Int)
2293 assert(to!Int("+9223372036854775807") == 0x7FFFFFFFFFFFFFFF);
2295 assert(to!Int("-9223372036854775808") == 0x8000000000000000);
2303 import std.exception;
2304 // parsing error check
2305 foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2308 immutable string[] errors1 =
2326 foreach (j, s; errors1)
2327 assertThrown!ConvException(to!Int(s));
2330 // parse!SomeUnsigned cannot parse head sign.
2331 static if (isUnsigned!Int)
2333 immutable string[] errors2 =
2338 foreach (j, s; errors2)
2339 assertThrown!ConvException(to!Int(s));
2343 // positive overflow check
2344 foreach (i, Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2346 immutable string[] errors =
2348 "128", // > byte.max
2349 "256", // > ubyte.max
2350 "32768", // > short.max
2351 "65536", // > ushort.max
2352 "2147483648", // > int.max
2353 "4294967296", // > uint.max
2354 "9223372036854775808", // > long.max
2355 "18446744073709551616", // > ulong.max
2357 foreach (j, s; errors[i..$])
2358 assertThrown!ConvOverflowException(to!Int(s));
2361 // negative overflow check
2362 foreach (i, Int; AliasSeq!(byte, short, int, long))
2364 immutable string[] errors =
2366 "-129", // < byte.min
2367 "-32769", // < short.min
2368 "-2147483649", // < int.min
2369 "-9223372036854775809", // < long.min
2371 foreach (j, s; errors[i..$])
2372 assertThrown!ConvOverflowException(to!Int(s));
2378 void checkErrMsg(string input, dchar charInMsg, dchar charNotInMsg)
2382 int x = input.to!int();
2383 assert(false, "Invalid conversion did not throw");
2385 catch (ConvException e)
2387 // Ensure error message contains failing character, not the character
2389 import std.algorithm.searching : canFind;
2390 assert( e.msg.canFind(charInMsg) &&
2391 !e.msg.canFind(charNotInMsg));
2395 assert(false, "Did not throw ConvException");
2398 checkErrMsg("@$", '@', '$');
2399 checkErrMsg("@$123", '@', '$');
2400 checkErrMsg("1@$23", '@', '$');
2401 checkErrMsg("1@$", '@', '$');
2402 checkErrMsg("1@$2", '@', '$');
2403 checkErrMsg("12@$", '@', '$');
2408 import std.exception;
2409 assertCTFEable!({ string s = "1234abc"; assert(parse! int(s) == 1234 && s == "abc"); });
2410 assertCTFEable!({ string s = "-1234abc"; assert(parse! int(s) == -1234 && s == "abc"); });
2411 assertCTFEable!({ string s = "1234abc"; assert(parse!uint(s) == 1234 && s == "abc"); });
2417 import std.exception;
2419 assertThrown!ConvOverflowException("-21474836480".to!int());
2420 assertThrown!ConvOverflowException("-92233720368547758080".to!long());
2426 struct StrInputRange
2428 this (string s) { str = s; }
2429 char front() const @property { return str[front_index]; }
2430 char popFront() { return str[front_index++]; }
2431 bool empty() const @property { return str.length <= front_index; }
2433 size_t front_index = 0;
2435 auto input = StrInputRange("777");
2436 assert(parse!int(input) == 777);
2440 Target parse(Target, Source)(ref Source source, uint radix)
2441 if (isSomeChar!(ElementType!Source) &&
2442 isIntegral!Target && !is(Target == enum))
2445 assert(radix >= 2 && radix <= 36);
2449 import core.checkedint : mulu, addu;
2450 import std.exception : enforce;
2453 return parse!Target(source);
2455 enforce!ConvException(!source.empty, "s must not be empty in integral parse");
2457 immutable uint beyond = (radix < 10 ? '0' : 'a'-10) + radix;
2460 static if (isNarrowString!Source)
2462 import std.string : representation;
2463 auto s = source.representation;
2484 c |= 0x20;//poorman's tolower
2485 if (c < 'a' || c >= beyond)
2491 bool overflow = false;
2492 auto nextv = v.mulu(radix, overflow).addu(c - '0', overflow);
2493 enforce!ConvOverflowException(!overflow && nextv <= Target.max, "Overflow in integral conversion");
2494 v = cast(Target) nextv;
2498 static if (isNarrowString!Source)
2499 source = cast(Source) s;
2506 string s; // parse doesn't accept rvalues
2507 foreach (i; 2 .. 37)
2509 assert(parse!int(s = "0", i) == 0);
2510 assert(parse!int(s = "1", i) == 1);
2511 assert(parse!byte(s = "10", i) == i);
2514 assert(parse!int(s = "0011001101101", 2) == 0b0011001101101);
2515 assert(parse!int(s = "765", 8) == octal!765);
2516 assert(parse!int(s = "fCDe", 16) == 0xfcde);
2519 assert(parse!int(s = "-42", 10) == -42);
2521 assert(parse!ubyte(s = "ff", 16) == 0xFF);
2524 @safe pure unittest // bugzilla 7302
2526 import std.range : cycle;
2527 auto r = cycle("2A!");
2528 auto u = parse!uint(r, 16);
2530 assert(r.front == '!');
2533 @safe pure unittest // bugzilla 13163
2535 import std.exception;
2536 foreach (s; ["fff", "123"])
2537 assertThrown!ConvOverflowException(s.parse!ubyte(16));
2540 @safe pure unittest // bugzilla 17282
2542 auto str = "0=\x00\x02\x55\x40&\xff\xf0\n\x00\x04\x55\x40\xff\xf0~4+10\n";
2543 assert(parse!uint(str) == 0);
2547 * Takes a string representing an `enum` type and returns that type.
2550 * Target = the `enum` type to convert to
2551 * s = the lvalue of the range to _parse
2554 * An `enum` of type `Target`
2557 * A $(LREF ConvException) if type `Target` does not have a member
2558 * represented by `s`.
2560 Target parse(Target, Source)(ref Source s)
2561 if (isSomeString!Source && !is(Source == enum) &&
2564 import std.algorithm.searching : startsWith;
2566 size_t longest_match = 0;
2568 foreach (i, e; EnumMembers!Target)
2570 auto ident = __traits(allMembers, Target)[i];
2571 if (longest_match < ident.length && s.startsWith(ident))
2574 longest_match = ident.length ;
2578 if (longest_match > 0)
2580 s = s[longest_match .. $];
2584 throw new ConvException(
2585 Target.stringof ~ " does not have a member named '"
2586 ~ to!string(s) ~ "'");
2592 enum EnumType : bool { a = true, b = false, c = a }
2595 assert(parse!EnumType(str) == EnumType.a);
2600 import std.exception;
2602 enum EB : bool { a = true, b = false, c = a }
2604 enum EI { a = -1, b = 0, c = 1 }
2605 enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
2606 enum EC : char { a = 'a', b = 'b', c = 'c' }
2607 enum ES : string { a = "aaa", b = "bbb", c = "ccc" }
2609 foreach (E; AliasSeq!(EB, EU, EI, EF, EC, ES))
2611 assert(to!E("a"c) == E.a);
2612 assert(to!E("b"w) == E.b);
2613 assert(to!E("c"d) == E.c);
2615 assertThrown!ConvException(to!E("d"));
2619 @safe pure unittest // bugzilla 4744
2621 enum A { member1, member11, member111 }
2622 assert(to!A("member1" ) == A.member1 );
2623 assert(to!A("member11" ) == A.member11 );
2624 assert(to!A("member111") == A.member111);
2625 auto s = "member1111";
2626 assert(parse!A(s) == A.member111 && s == "1");
2630 * Parses a character range to a floating point number.
2633 * Target = a floating point type
2634 * source = the lvalue of the range to _parse
2637 * A floating point number of type `Target`
2640 * A $(LREF ConvException) if `p` is empty, if no number could be
2641 * parsed, or if an overflow occurred.
2643 Target parse(Target, Source)(ref Source source)
2644 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
2645 isFloatingPoint!Target && !is(Target == enum))
2647 import core.stdc.math : HUGE_VAL;
2648 import std.ascii : isDigit, isAlpha, toLower, toUpper, isHexDigit;
2649 import std.exception : enforce;
2651 static if (isNarrowString!Source)
2653 import std.string : representation;
2654 auto p = source.representation;
2661 static immutable real[14] negtab =
2662 [ 1e-4096L,1e-2048L,1e-1024L,1e-512L,1e-256L,1e-128L,1e-64L,1e-32L,
2663 1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L ];
2664 static immutable real[13] postab =
2665 [ 1e+4096L,1e+2048L,1e+1024L,1e+512L,1e+256L,1e+128L,1e+64L,1e+32L,
2666 1e+16L,1e+8L,1e+4L,1e+2L,1e+1L ];
2668 ConvException bailOut()(string msg = null, string fn = __FILE__, size_t ln = __LINE__)
2671 msg = "Floating point conversion error";
2672 return new ConvException(text(msg, " for input \"", p, "\"."), fn, ln);
2676 enforce(!p.empty, bailOut());
2684 enforce(!p.empty, bailOut());
2685 if (toLower(p.front) == 'i')
2687 enforce(!p.empty, bailOut());
2691 enforce(!p.empty, bailOut());
2695 enforce(!p.empty, bailOut());
2696 if (toLower(p.front) == 'n')
2699 enforce(!p.empty, bailOut());
2700 if (toLower(p.front) == 'f')
2704 static if (isNarrowString!Source)
2705 source = cast(Source) p;
2706 return sign ? -Target.infinity : Target.infinity;
2714 bool startsWithZero = p.front == '0';
2720 static if (isNarrowString!Source)
2721 source = cast(Source) p;
2722 return sign ? -0.0 : 0.0;
2725 isHex = p.front == 'x' || p.front == 'X';
2729 char dot = 0; /* if decimal point has been seen */
2731 long msdec = 0, lsdec = 0;
2744 while (isHexDigit(i))
2747 i = isAlpha(i) ? ((i & ~0x20) - ('A' - 10)) : i - '0';
2750 msdec = msdec * 16 + i;
2754 else if (ndigits == 16)
2786 if (i == '.' && !dot)
2795 // Round up if (guard && (sticky || odd))
2796 if (guard & 0x80 && (guard & 0x7F || msdec & 1))
2799 if (msdec == 0) // overflow
2801 msdec = 0x8000000000000000L;
2806 enforce(anydigits, bailOut());
2807 enforce(!p.empty && (p.front == 'p' || p.front == 'P'),
2808 bailOut("Floating point parsing: exponent is required"));
2820 case '+': p.popFront(); enforce(!p.empty,
2821 new ConvException("Error converting input"~
2822 " to floating point"));
2829 while (!p.empty && isDigit(p.front))
2831 if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow
2833 e = e * 10 + p.front - '0';
2838 exp += (sexp) ? -e : e;
2839 enforce(ndigits, new ConvException("Error converting input"~
2840 " to floating point"));
2842 static if (real.mant_dig == 64)
2846 int e2 = 0x3FFF + 63;
2848 // left justify mantissa
2855 // Stuff mantissa directly into real
2856 ()@trusted{ *cast(long*)&ldval = msdec; }();
2857 ()@trusted{ (cast(ushort*)&ldval)[4] = cast(ushort) e2; }();
2859 import std.math : ldexp;
2861 // Exponent is power of 2, not power of 10
2862 ldval = ldexp(ldval,exp);
2865 else static if (real.mant_dig == 53)
2869 //Exponent bias + 52:
2870 //After shifting 52 times left, exp must be 1
2871 int e2 = 0x3FF + 52;
2873 // right justify mantissa
2874 // first 11 bits must be zero, rest is implied bit + mantissa
2875 // shift one time less, do rounding, shift again
2876 while ((msdec & 0xFFC0_0000_0000_0000) != 0)
2878 msdec = ((cast(ulong) msdec) >> 1);
2882 //Have to shift one more time
2884 if ((msdec & 0xFFE0_0000_0000_0000) != 0)
2886 auto roundUp = (msdec & 0x1);
2888 msdec = ((cast(ulong) msdec) >> 1);
2893 //If mantissa was 0b1111... and we added +1
2894 //the mantissa should be 0b10000 (think of implicit bit)
2895 //and the exponent increased
2896 if ((msdec & 0x0020_0000_0000_0000) != 0)
2898 msdec = 0x0010_0000_0000_0000;
2905 // left justify mantissa
2907 while ((msdec & 0x0010_0000_0000_0000) == 0)
2913 // Stuff mantissa directly into double
2914 // (first including implicit bit)
2915 ()@trusted{ *cast(long *)&ldval = msdec; }();
2916 //Store exponent, now overwriting implicit bit
2917 ()@trusted{ *cast(long *)&ldval &= 0x000F_FFFF_FFFF_FFFF; }();
2918 ()@trusted{ *cast(long *)&ldval |= ((e2 & 0xFFFUL) << 52); }();
2920 import std.math : ldexp;
2922 // Exponent is power of 2, not power of 10
2923 ldval = ldexp(ldval,exp);
2927 static assert(false, "Floating point format of real type not supported");
2933 if (toUpper(p.front) == 'N' && !startsWithZero)
2937 enforce(!p.empty && toUpper(p.front) == 'A',
2938 new ConvException("error converting input to floating point"));
2940 enforce(!p.empty && toUpper(p.front) == 'N',
2941 new ConvException("error converting input to floating point"));
2942 // skip past the last 'n'
2944 static if (isNarrowString!Source)
2945 source = cast(Source) p;
2946 return typeof(return).nan;
2949 bool sawDigits = startsWithZero;
2956 sawDigits = true; /* must have at least 1 digit */
2957 if (msdec < (0x7FFFFFFFFFFFL-10)/10)
2958 msdec = msdec * 10 + (i - '0');
2959 else if (msscale < (0xFFFFFFFF-10)/10)
2961 lsdec = lsdec * 10 + (i - '0');
2981 if (i == '.' && !dot)
2991 enforce(sawDigits, new ConvException("no digits seen"));
2993 if (!p.empty && (p.front == 'e' || p.front == 'E'))
3000 enforce(!p.empty, new ConvException("Unexpected end of input"));
3005 case '+': p.popFront();
3011 while (!p.empty && isDigit(p.front))
3013 if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow
3015 e = e * 10 + p.front - '0';
3020 exp += (sexp) ? -e : e;
3021 enforce(sawDigits, new ConvException("No digits seen."));
3025 if (msscale != 1) /* if stuff was accumulated in lsdec */
3026 ldval = ldval * msscale + lsdec;
3047 enforce(ldval != 0, new ConvException("Range error"));
3054 L6: // if overflow occurred
3055 enforce(ldval != HUGE_VAL, new ConvException("Range error"));
3058 static if (isNarrowString!Source)
3059 source = cast(Source) p;
3060 return sign ? -ldval : ldval;
3066 import std.math : approxEqual;
3067 auto str = "123.456";
3069 assert(parse!double(str).approxEqual(123.456));
3074 import std.exception;
3075 import std.math : isNaN, fabs;
3077 // Compare reals with given precision
3078 bool feq(in real rx, in real ry, in real precision = 0.000001L)
3084 return cast(bool) isNaN(ry);
3089 return cast(bool)(fabs(rx - ry) <= precision);
3092 // Make given typed literal
3098 foreach (Float; AliasSeq!(float, double, real))
3100 assert(to!Float("123") == Literal!Float(123));
3101 assert(to!Float("+123") == Literal!Float(+123));
3102 assert(to!Float("-123") == Literal!Float(-123));
3103 assert(to!Float("123e2") == Literal!Float(123e2));
3104 assert(to!Float("123e+2") == Literal!Float(123e+2));
3105 assert(to!Float("123e-2") == Literal!Float(123e-2));
3106 assert(to!Float("123.") == Literal!Float(123.0));
3107 assert(to!Float(".375") == Literal!Float(.375));
3109 assert(to!Float("1.23375E+2") == Literal!Float(1.23375E+2));
3111 assert(to!Float("0") is 0.0);
3112 assert(to!Float("-0") is -0.0);
3114 assert(isNaN(to!Float("nan")));
3116 assertThrown!ConvException(to!Float("\x00"));
3120 float f = to!float("1.17549e-38");
3121 assert(feq(cast(real) f, cast(real) 1.17549e-38));
3122 assert(feq(cast(real) f, cast(real) float.min_normal));
3123 f = to!float("3.40282e+38");
3124 assert(to!string(f) == to!string(3.40282e+38));
3127 double d = to!double("2.22508e-308");
3128 assert(feq(cast(real) d, cast(real) 2.22508e-308));
3129 assert(feq(cast(real) d, cast(real) double.min_normal));
3130 d = to!double("1.79769e+308");
3131 assert(to!string(d) == to!string(1.79769e+308));
3132 assert(to!string(d) == to!string(double.max));
3134 assert(to!string(to!real(to!string(real.max / 2L))) == to!string(real.max / 2L));
3137 real r = to!real(to!string(real.min_normal));
3141 // to!string returns 3.3621e-4932L. It is less than real.min_normal and it is subnormal value
3143 // long double rd = 3.3621e-4932L;
3144 // printf("%Le\n", rd);
3145 // has unexpected result: 1.681050e-4932
3147 // Bug report: http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=50937
3151 assert(to!string(r) == to!string(real.min_normal));
3153 r = to!real(to!string(real.max));
3154 assert(to!string(r) == to!string(real.max));
3157 // Tests for the double implementation
3160 // @system because strtod is not @safe.
3161 static if (real.mant_dig == 53)
3163 import core.stdc.stdlib, std.exception, std.math;
3165 //Should be parsed exactly: 53 bit mantissa
3166 string s = "0x1A_BCDE_F012_3456p10";
3167 auto x = parse!real(s);
3168 assert(x == 0x1A_BCDE_F012_3456p10L);
3170 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0xA_BCDE_F012_3456);
3171 assert(strtod("0x1ABCDEF0123456p10", null) == x);
3173 //Should be parsed exactly: 10 bit mantissa
3176 assert(x == 0x03FFp10);
3178 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_F800_0000_0000);
3179 assert(strtod("0x3FFp10", null) == x);
3181 //60 bit mantissa, round up
3182 s = "0xFFF_FFFF_FFFF_FFFFp10";
3184 assert(approxEqual(x, 0xFFF_FFFF_FFFF_FFFFp10));
3186 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x0000_0000_0000_0000);
3187 assert(strtod("0xFFFFFFFFFFFFFFFp10", null) == x);
3189 //60 bit mantissa, round down
3190 s = "0xFFF_FFFF_FFFF_FF90p10";
3192 assert(approxEqual(x, 0xFFF_FFFF_FFFF_FF90p10));
3194 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_FFFF_FFFF_FFFF);
3195 assert(strtod("0xFFFFFFFFFFFFF90p10", null) == x);
3197 //61 bit mantissa, round up 2
3198 s = "0x1F0F_FFFF_FFFF_FFFFp10";
3200 assert(approxEqual(x, 0x1F0F_FFFF_FFFF_FFFFp10));
3202 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_1000_0000_0000);
3203 assert(strtod("0x1F0FFFFFFFFFFFFFp10", null) == x);
3205 //61 bit mantissa, round down 2
3206 s = "0x1F0F_FFFF_FFFF_FF10p10";
3208 assert(approxEqual(x, 0x1F0F_FFFF_FFFF_FF10p10));
3210 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_0FFF_FFFF_FFFF);
3211 assert(strtod("0x1F0FFFFFFFFFFF10p10", null) == x);
3214 s = "0x1F_FFFF_FFFF_FFFFp900";
3216 assert(strtod("0x1FFFFFFFFFFFFFp900", null) == x);
3218 //exponent too big -> converror
3220 assertThrown!ConvException(x = parse!real(s));
3221 assert(strtod("0x1FFFFFFFFFFFFFp1024", null) == real.infinity);
3223 //-exponent too big -> 0
3224 s = "0x1FFFFFFFFFFFFFp-2000";
3227 assert(strtod("0x1FFFFFFFFFFFFFp-2000", null) == x);
3233 import core.stdc.errno;
3234 import core.stdc.stdlib;
3236 errno = 0; // In case it was set by another unittest in a different module.
3239 static if (real.mant_dig == 64)
3243 else static if (real.mant_dig == 53)
3248 static assert(false, "Not implemented");
3257 static if (real.mant_dig == 64)
3258 enum s = "0x1.FFFFFFFFFFFFFFFEp-16382";
3259 else static if (real.mant_dig == 53)
3260 enum s = "0x1.FFFFFFFFFFFFFFFEp-1000";
3262 static assert(false, "Floating point format for real not supported");
3265 ld = parse!real(s2);
3267 x = *cast(longdouble *)&ld;
3269 static if (real.mant_dig == 64)
3271 version (CRuntime_Microsoft)
3272 ld1 = 0x1.FFFFFFFFFFFFFFFEp-16382L; // strtold currently mapped to strtod
3273 else version (CRuntime_Bionic)
3274 ld1 = 0x1.FFFFFFFFFFFFFFFEp-16382L; // strtold currently mapped to strtod
3276 ld1 = strtold(s.ptr, null);
3279 ld1 = strtold(s.ptr, null);
3281 x1 = *cast(longdouble *)&ld1;
3282 assert(x1 == x && ld1 == ld);
3287 ld = parse!real(s2);
3289 x = *cast(longdouble *)&ld;
3290 ld1 = strtold("1.0e5", null);
3291 x1 = *cast(longdouble *)&ld1;
3296 import std.exception;
3301 auto x = parse!double(s);
3307 assert(to!float("inf") == float.infinity);
3308 assert(to!float("-inf") == -float.infinity);
3311 assert(6_5.536e3L == to!real("6_5.536e3")); // 2^16
3312 assert(0x1000_000_000_p10 == to!real("0x1000_000_000_p10")); // 7.03687e+13
3315 assertThrown!ConvException(to!real("-"));
3316 assertThrown!ConvException(to!real("in"));
3319 assertThrown!ConvException(to!float("INF2"));
3321 //extra stress testing
3322 auto ssOK = ["1.", "1.1.1", "1.e5", "2e1e", "2a", "2e1_1",
3323 "inf", "-inf", "infa", "-infa", "inf2e2", "-inf2e2"];
3324 auto ssKO = ["", " ", "2e", "2e+", "2e-", "2ee", "2e++1", "2e--1", "2e_1", "+inf"];
3328 assertThrown!ConvException(parse!double(s));
3332 Parsing one character off a range returns the first element and calls `popFront`.
3335 Target = the type to convert to
3336 s = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3339 A character of type `Target`
3342 A $(LREF ConvException) if the range is empty.
3344 Target parse(Target, Source)(ref Source s)
3345 if (isSomeString!Source && !is(Source == enum) &&
3346 staticIndexOf!(Unqual!Target, dchar, Unqual!(ElementEncodingType!Source)) >= 0)
3349 throw convError!(Source, Target)(s);
3350 static if (is(Unqual!Target == dchar))
3352 Target result = s.front;
3358 // Special case: okay so parse a Char off a Char[]
3359 Target result = s[0];
3367 foreach (Str; AliasSeq!(string, wstring, dstring))
3369 foreach (Char; AliasSeq!(char, wchar, dchar))
3371 static if (is(Unqual!Char == dchar) ||
3372 Char.sizeof == ElementEncodingType!Str.sizeof)
3375 assert(parse!Char(s) == 'a');
3383 Target parse(Target, Source)(ref Source s)
3384 if (!isSomeString!Source && isInputRange!Source && isSomeChar!(ElementType!Source) &&
3385 isSomeChar!Target && Target.sizeof >= ElementType!Source.sizeof && !is(Target == enum))
3388 throw convError!(Source, Target)(s);
3389 Target result = s.front;
3397 auto s = "Hello, World!";
3398 char first = parse!char(s);
3399 assert(first == 'H');
3400 assert(s == "ello, World!");
3405 Tests for to!bool and parse!bool
3409 import std.exception;
3411 assert(to!bool("TruE") == true);
3412 assert(to!bool("faLse"d) == false);
3413 assertThrown!ConvException(to!bool("maybe"));
3415 auto t = "TrueType";
3416 assert(parse!bool(t) == true);
3417 assert(t == "Type");
3419 auto f = "False killer whale"d;
3420 assert(parse!bool(f) == false);
3421 assert(f == " killer whale"d);
3424 assertThrown!ConvException(parse!bool(m));
3425 assert(m == "maybe"); // m shouldn't change on failure
3428 auto b = parse!(const(bool))(s);
3433 Parsing a character range to `typeof(null)` returns `null` if the range
3434 spells `"null"`. This function is case insensitive.
3437 Target = the type to convert to
3438 s = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3444 A $(LREF ConvException) if the range doesn't represent `null`.
3446 Target parse(Target, Source)(ref Source s)
3447 if (isInputRange!Source &&
3448 isSomeChar!(ElementType!Source) &&
3449 is(Unqual!Target == typeof(null)))
3451 import std.ascii : toLower;
3454 if (s.empty || toLower(s.front) != c)
3455 throw parseError("null should be case-insensitive 'null'");
3464 import std.exception : assertThrown;
3466 alias NullType = typeof(null);
3468 assert(parse!NullType(s1) is null);
3472 assert(parse!NullType(s2) is null);
3476 assertThrown!ConvException(parse!NullType(m));
3477 assert(m == "maybe"); // m shouldn't change on failure
3480 assert(parse!(const NullType)(s) is null);
3483 //Used internally by parse Array/AA, to remove ascii whites
3484 package void skipWS(R)(ref R r)
3486 import std.ascii : isWhite;
3487 static if (isSomeString!R)
3489 //Implementation inspired from stripLeft.
3498 r = r[0 .. 0]; //Empty string with correct type.
3503 for (; !r.empty && isWhite(r.front); r.popFront())
3509 * Parses an array from a string given the left bracket (default $(D
3510 * '[')), right bracket (default $(D ']')), and element separator (by
3511 * default $(D ',')). A trailing separator is allowed.
3514 * s = The string to parse
3515 * lbracket = the character that starts the array
3516 * rbracket = the character that ends the array
3517 * comma = the character that separates the elements of the array
3520 * An array of type `Target`
3522 Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
3523 if (isSomeString!Source && !is(Source == enum) &&
3524 isDynamicArray!Target && !is(Target == enum))
3526 import std.array : appender;
3528 auto result = appender!Target();
3530 parseCheck!s(lbracket);
3533 throw convError!(Source, Target)(s);
3534 if (s.front == rbracket)
3539 for (;; s.popFront(), skipWS(s))
3541 if (!s.empty && s.front == rbracket)
3543 result ~= parseElement!(ElementType!Target)(s);
3546 throw convError!(Source, Target)(s);
3547 if (s.front != comma)
3550 parseCheck!s(rbracket);
3558 auto s1 = `[['h', 'e', 'l', 'l', 'o'], "world"]`;
3559 auto a1 = parse!(string[])(s1);
3560 assert(a1 == ["hello", "world"]);
3562 auto s2 = `["aaa", "bbb", "ccc"]`;
3563 auto a2 = parse!(string[])(s2);
3564 assert(a2 == ["aaa", "bbb", "ccc"]);
3567 @safe unittest // Bugzilla 9615
3569 string s0 = "[1,2, ]";
3570 string s1 = "[1,2, \t\v\r\n]";
3571 string s2 = "[1,2]";
3572 assert(s0.parse!(int[]) == [1,2]);
3573 assert(s1.parse!(int[]) == [1,2]);
3574 assert(s2.parse!(int[]) == [1,2]);
3576 string s3 = `["a","b",]`;
3577 string s4 = `["a","b"]`;
3578 assert(s3.parse!(string[]) == ["a","b"]);
3579 assert(s4.parse!(string[]) == ["a","b"]);
3581 import std.exception : assertThrown;
3583 string s6 = "[, \t,]";
3584 assertThrown!ConvException(parse!(string[])(s5));
3585 assertThrown!ConvException(parse!(int[])(s6));
3590 int[] a = [1, 2, 3, 4, 5];
3591 auto s = to!string(a);
3592 assert(to!(int[])(s) == a);
3597 int[][] a = [ [1, 2] , [3], [4, 5] ];
3598 auto s = to!string(a);
3599 assert(to!(int[][])(s) == a);
3604 int[][][] ia = [ [[1,2],[3,4],[5]] , [[6],[],[7,8,9]] , [[]] ];
3606 char[] s = to!(char[])(ia);
3609 ia2 = to!(typeof(ia2))(s);
3615 import std.exception;
3617 //Check proper failure
3618 auto s = "[ 1 , 2 , 3 ]";
3619 foreach (i ; 0 .. s.length-1)
3621 auto ss = s[0 .. i];
3622 assertThrown!ConvException(parse!(int[])(ss));
3624 int[] arr = parse!(int[])(s);
3629 //Checks parsing of strings with escaped characters
3631 "Contains a\0null!",
3634 "backslash \\ slash / question \?",
3636 "unicode \u65E5 sun",
3637 "very long \U000065E5 sun"
3640 //Note: escaped characters purposefully replaced and isolated to guarantee
3641 //there are no typos in the escape syntax
3643 "Contains a" ~ '\0' ~ "null!",
3644 "tab" ~ '\t' ~ "here",
3645 "line" ~ '\n' ~ "break",
3646 "backslash " ~ '\\' ~ " slash / question ?",
3651 assert(s2 == parse!(string[])(s1));
3656 Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
3657 if (isExactSomeString!Source &&
3658 isStaticArray!Target && !is(Target == enum))
3660 static if (hasIndirections!Target)
3661 Target result = Target.init[0].init;
3663 Target result = void;
3665 parseCheck!s(lbracket);
3668 throw convError!(Source, Target)(s);
3669 if (s.front == rbracket)
3671 static if (result.length != 0)
3679 for (size_t i = 0; ; s.popFront(), skipWS(s))
3681 if (i == result.length)
3683 result[i++] = parseElement!(ElementType!Target)(s);
3686 throw convError!(Source, Target)(s);
3687 if (s.front != comma)
3689 if (i != result.length)
3694 parseCheck!s(rbracket);
3699 throw parseError(text("Too many elements in input, ", result.length, " elements expected."));
3702 throw parseError(text("Too few elements in input, ", result.length, " elements expected."));
3707 import std.exception;
3709 auto s1 = "[1,2,3,4]";
3710 auto sa1 = parse!(int[4])(s1);
3711 assert(sa1 == [1,2,3,4]);
3713 auto s2 = "[[1],[2,3],[4]]";
3714 auto sa2 = parse!(int[][3])(s2);
3715 assert(sa2 == [[1],[2,3],[4]]);
3717 auto s3 = "[1,2,3]";
3718 assertThrown!ConvException(parse!(int[4])(s3));
3720 auto s4 = "[1,2,3,4,5]";
3721 assertThrown!ConvException(parse!(int[4])(s4));
3725 * Parses an associative array from a string given the left bracket (default $(D
3726 * '[')), right bracket (default $(D ']')), key-value separator (default $(D
3727 * ':')), and element seprator (by default $(D ',')).
3730 * s = the string to parse
3731 * lbracket = the character that starts the associative array
3732 * rbracket = the character that ends the associative array
3733 * keyval = the character that associates the key with the value
3734 * comma = the character that separates the elements of the associative array
3737 * An associative array of type `Target`
3739 Target parse(Target, Source)(ref Source s, dchar lbracket = '[',
3740 dchar rbracket = ']', dchar keyval = ':', dchar comma = ',')
3741 if (isSomeString!Source && !is(Source == enum) &&
3742 isAssociativeArray!Target && !is(Target == enum))
3744 alias KeyType = typeof(Target.init.keys[0]);
3745 alias ValType = typeof(Target.init.values[0]);
3749 parseCheck!s(lbracket);
3752 throw convError!(Source, Target)(s);
3753 if (s.front == rbracket)
3758 for (;; s.popFront(), skipWS(s))
3760 auto key = parseElement!KeyType(s);
3762 parseCheck!s(keyval);
3764 auto val = parseElement!ValType(s);
3768 throw convError!(Source, Target)(s);
3769 if (s.front != comma)
3772 parseCheck!s(rbracket);
3780 auto s1 = "[1:10, 2:20, 3:30]";
3781 auto aa1 = parse!(int[int])(s1);
3782 assert(aa1 == [1:10, 2:20, 3:30]);
3784 auto s2 = `["aaa":10, "bbb":20, "ccc":30]`;
3785 auto aa2 = parse!(int[string])(s2);
3786 assert(aa2 == ["aaa":10, "bbb":20, "ccc":30]);
3788 auto s3 = `["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]`;
3789 auto aa3 = parse!(int[][string])(s3);
3790 assert(aa3 == ["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]);
3795 import std.exception;
3797 //Check proper failure
3798 auto s = "[1:10, 2:20, 3:30]";
3799 foreach (i ; 0 .. s.length-1)
3801 auto ss = s[0 .. i];
3802 assertThrown!ConvException(parse!(int[int])(ss));
3804 int[int] aa = parse!(int[int])(s);
3807 private dchar parseEscape(Source)(ref Source s)
3808 if (isInputRange!Source && isSomeChar!(ElementType!Source))
3812 throw parseError("Unterminated escape sequence");
3814 dchar getHexDigit()(ref Source s_ = s) // workaround
3816 import std.ascii : isAlpha, isHexDigit;
3818 throw parseError("Unterminated escape sequence");
3821 throw parseError("Unterminated escape sequence");
3824 throw parseError("Hex digit is missing");
3825 return isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0';
3832 case '"': result = '\"'; break;
3833 case '\'': result = '\''; break;
3834 case '0': result = '\0'; break;
3835 case '?': result = '\?'; break;
3836 case '\\': result = '\\'; break;
3837 case 'a': result = '\a'; break;
3838 case 'b': result = '\b'; break;
3839 case 'f': result = '\f'; break;
3840 case 'n': result = '\n'; break;
3841 case 'r': result = '\r'; break;
3842 case 't': result = '\t'; break;
3843 case 'v': result = '\v'; break;
3845 result = getHexDigit() << 4;
3846 result |= getHexDigit();
3849 result = getHexDigit() << 12;
3850 result |= getHexDigit() << 8;
3851 result |= getHexDigit() << 4;
3852 result |= getHexDigit();
3855 result = getHexDigit() << 28;
3856 result |= getHexDigit() << 24;
3857 result |= getHexDigit() << 20;
3858 result |= getHexDigit() << 16;
3859 result |= getHexDigit() << 12;
3860 result |= getHexDigit() << 8;
3861 result |= getHexDigit() << 4;
3862 result |= getHexDigit();
3865 throw parseError("Unknown escape character " ~ to!string(s.front));
3868 throw parseError("Unterminated escape sequence");
3878 `\"`, `\'`, `\?`, `\\`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v`, //Normal escapes
3879 //`\141`, //@@@9621@@@ Octal escapes.
3881 `\u65E5`, `\U00012456`
3882 //`\&`, `\"`, //@@@9621@@@ Named Character Entities.
3885 const(dchar)[] s2 = [
3886 '\"', '\'', '\?', '\\', '\a', '\b', '\f', '\n', '\r', '\t', '\v', //Normal escapes
3887 //'\141', //@@@9621@@@ Octal escapes.
3889 '\u65E5', '\U00012456'
3890 //'\&', '\"', //@@@9621@@@ Named Character Entities.
3893 foreach (i ; 0 .. s1.length)
3895 assert(s2[i] == parseEscape(s1[i]));
3896 assert(s1[i].empty);
3902 import std.exception;
3905 `hello!`, //Not an escape
3906 `\`, //Premature termination
3907 `\/`, //Not an escape
3908 `\gggg`, //Not an escape
3909 `\xzz`, //Not an hex
3910 `\x0`, //Premature hex end
3911 `\XB9`, //Not legal hex syntax
3912 `\u!!`, //Not a unicode hex
3913 `\777`, //Octal is larger than a byte //Note: Throws, but simply because octals are unsupported
3914 `\u123`, //Premature hex end
3915 `\U123123` //Premature hex end
3918 assertThrown!ConvException(parseEscape(s));
3922 Target parseElement(Target, Source)(ref Source s)
3923 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
3924 isExactSomeString!Target)
3926 import std.array : appender;
3927 auto result = appender!Target();
3929 // parse array of chars
3931 throw convError!(Source, Target)(s);
3933 return parse!Target(s);
3937 throw convError!(Source, Target)(s);
3938 if (s.front == '\"')
3946 throw parseError("Unterminated quoted string");
3953 result.put(parseEscape(s));
3956 result.put(s.front);
3965 Target parseElement(Target, Source)(ref Source s)
3966 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
3967 isSomeChar!Target && !is(Target == enum))
3973 throw convError!(Source, Target)(s);
3974 if (s.front != '\\')
3987 Target parseElement(Target, Source)(ref Source s)
3988 if (isInputRange!Source && isSomeChar!(ElementType!Source) &&
3989 !isSomeString!Target && !isSomeChar!Target)
3991 return parse!Target(s);
3995 /***************************************************************
3996 * Convenience functions for converting one or more arguments
3997 * of any type into _text (the three character widths).
3999 string text(T...)(T args)
4000 if (T.length > 0) { return textImpl!string(args); }
4002 // @@@DEPRECATED_2018-06@@@
4003 deprecated("Calling `text` with 0 arguments is deprecated")
4004 string text(T...)(T args)
4005 if (T.length == 0) { return textImpl!string(args); }
4008 wstring wtext(T...)(T args)
4009 if (T.length > 0) { return textImpl!wstring(args); }
4011 // @@@DEPRECATED_2018-06@@@
4012 deprecated("Calling `wtext` with 0 arguments is deprecated")
4013 wstring wtext(T...)(T args)
4014 if (T.length == 0) { return textImpl!wstring(args); }
4017 dstring dtext(T...)(T args)
4018 if (T.length > 0) { return textImpl!dstring(args); }
4023 assert( text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"c);
4024 assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w);
4025 assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d);
4028 // @@@DEPRECATED_2018-06@@@
4029 deprecated("Calling `dtext` with 0 arguments is deprecated")
4030 dstring dtext(T...)(T args)
4031 if (T.length == 0) { return textImpl!dstring(args); }
4033 private S textImpl(S, U...)(U args)
4035 static if (U.length == 0)
4039 else static if (U.length == 1)
4041 return to!S(args[0]);
4045 import std.array : appender;
4047 auto app = appender!S();
4056 /***************************************************************
4057 The $(D octal) facility provides a means to declare a number in base 8.
4058 Using $(D octal!177) or $(D octal!"177") for 127 represented in octal
4059 (same as 0177 in C).
4061 The rules for strings are the usual for literals: If it can fit in an
4062 $(D int), it is an $(D int). Otherwise, it is a $(D long). But, if the
4063 user specifically asks for a $(D long) with the $(D L) suffix, always
4064 give the $(D long). Give an unsigned iff it is asked for with the $(D
4065 U) or $(D u) suffix. _Octals created from integers preserve the type
4066 of the passed-in integral.
4069 $(LREF parse) for parsing octal strings at runtime.
4071 template octal(string num)
4072 if (isOctalLiteral(num))
4074 static if ((octalFitsInInt!num && !literalIsLong!num) && !literalIsUnsigned!num)
4075 enum octal = octal!int(num);
4076 else static if ((!octalFitsInInt!num || literalIsLong!num) && !literalIsUnsigned!num)
4077 enum octal = octal!long(num);
4078 else static if ((octalFitsInInt!num && !literalIsLong!num) && literalIsUnsigned!num)
4079 enum octal = octal!uint(num);
4080 else static if ((!octalFitsInInt!(num) || literalIsLong!(num)) && literalIsUnsigned!(num))
4081 enum octal = octal!ulong(num);
4083 static assert(false);
4087 template octal(alias decimalInteger)
4088 if (isIntegral!(typeof(decimalInteger)))
4090 enum octal = octal!(typeof(decimalInteger))(to!string(decimalInteger));
4098 // octal is a compile-time device
4100 // Create an unsigned octal
4101 auto z = octal!"1_000_000u";
4105 Takes a string, num, which is an octal literal, and returns its
4106 value, in the type T specified.
4108 private T octal(T)(const string num)
4110 assert(isOctalLiteral(num));
4114 foreach (const char s; num)
4116 if (s < '0' || s > '7') // we only care about digits; skip the rest
4117 // safe to skip - this is checked out in the assert so these
4118 // are just suffixes
4130 int a = octal!int("10");
4135 Take a look at int.max and int.max+1 in octal and the logic for this
4136 function follows directly.
4138 private template octalFitsInInt(string octalNum)
4140 // note it is important to strip the literal of all
4141 // non-numbers. kill the suffix and underscores lest they mess up
4142 // the number of digits here that we depend on.
4143 enum bool octalFitsInInt = strippedOctalLiteral(octalNum).length < 11 ||
4144 strippedOctalLiteral(octalNum).length == 11 &&
4145 strippedOctalLiteral(octalNum)[0] == '1';
4148 private string strippedOctalLiteral(string original)
4150 string stripped = "";
4151 foreach (c; original)
4152 if (c >= '0' && c <= '7')
4157 private template literalIsLong(string num)
4159 static if (num.length > 1)
4160 // can be xxL or xxLu according to spec
4161 enum literalIsLong = (num[$-1] == 'L' || num[$-2] == 'L');
4163 enum literalIsLong = false;
4166 private template literalIsUnsigned(string num)
4168 static if (num.length > 1)
4169 // can be xxU or xxUL according to spec
4170 enum literalIsUnsigned = (num[$-1] == 'u' || num[$-2] == 'u')
4171 // both cases are allowed too
4172 || (num[$-1] == 'U' || num[$-2] == 'U');
4174 enum literalIsUnsigned = false;
4178 Returns if the given string is a correctly formatted octal literal.
4180 The format is specified in spec/lex.html. The leading zero is allowed, but
4183 @safe pure nothrow @nogc
4184 private bool isOctalLiteral(const string num)
4186 if (num.length == 0)
4189 // Must start with a number. To avoid confusion, literals that
4190 // start with a '0' are not allowed
4191 if (num[0] == '0' && num.length > 1)
4193 if (num[0] < '0' || num[0] > '7')
4198 if ((c < '0' || c > '7') && c != '_') // not a legal character
4200 if (i < num.length - 2)
4202 else // gotta check for those suffixes
4204 if (c != 'U' && c != 'u' && c != 'L')
4206 if (i != num.length - 1)
4208 // if we're not the last one, the next one must
4209 // also be a suffix to be valid
4211 if (c2 != 'U' && c2 != 'u' && c2 != 'L')
4212 return false; // spam at the end of the string
4214 return false; // repeats are disallowed
4225 // ensure that you get the right types, even with embedded underscores
4226 auto w = octal!"100_000_000_000";
4227 static assert(!is(typeof(w) == int));
4228 auto w2 = octal!"1_000_000_000";
4229 static assert(is(typeof(w2) == int));
4231 static assert(octal!"45" == 37);
4232 static assert(octal!"0" == 0);
4233 static assert(octal!"7" == 7);
4234 static assert(octal!"10" == 8);
4235 static assert(octal!"666" == 438);
4237 static assert(octal!45 == 37);
4238 static assert(octal!0 == 0);
4239 static assert(octal!7 == 7);
4240 static assert(octal!10 == 8);
4241 static assert(octal!666 == 438);
4243 static assert(octal!"66_6" == 438);
4245 static assert(octal!2520046213 == 356535435);
4246 static assert(octal!"2520046213" == 356535435);
4248 static assert(octal!17777777777 == int.max);
4250 static assert(!__traits(compiles, octal!823));
4252 static assert(!__traits(compiles, octal!"823"));
4254 static assert(!__traits(compiles, octal!"_823"));
4255 static assert(!__traits(compiles, octal!"spam"));
4256 static assert(!__traits(compiles, octal!"77%"));
4258 static assert(is(typeof(octal!"17777777777") == int));
4259 static assert(octal!"17777777777" == int.max);
4261 static assert(is(typeof(octal!"20000000000U") == ulong)); // Shouldn't this be uint?
4262 static assert(octal!"20000000000" == uint(int.max) + 1);
4264 static assert(is(typeof(octal!"777777777777777777777") == long));
4265 static assert(octal!"777777777777777777777" == long.max);
4267 static assert(is(typeof(octal!"1000000000000000000000U") == ulong));
4268 static assert(octal!"1000000000000000000000" == ulong(long.max) + 1);
4273 // biggest value that should fit in an it
4274 a = octal!"17777777777";
4275 assert(a == int.max);
4276 // should not fit in the int
4277 static assert(!__traits(compiles, a = octal!"20000000000"));
4278 // ... but should fit in a long
4279 b = octal!"20000000000";
4280 assert(b == 1L + int.max);
4289 emplaceRef is a package function for phobos internal use. It works like
4290 emplace, but takes its argument by ref (as opposed to "by pointer").
4292 This makes it easier to use, easier to be safe, and faster in a non-inline
4295 Furthermore, emplaceRef optionally takes a type paremeter, which specifies
4296 the type we want to build. This helps to build qualified objects on mutable
4297 buffer, without breaking the type system with unsafe casts.
4299 package void emplaceRef(T, UT, Args...)(ref UT chunk, auto ref Args args)
4301 static if (args.length == 0)
4303 static assert(is(typeof({static T i;})),
4304 convFormat("Cannot emplace a %1$s because %1$s.this() is annotated with @disable.", T.stringof));
4305 static if (is(T == class)) static assert(!isAbstractClass!T,
4306 T.stringof ~ " is abstract and it can't be emplaced");
4307 emplaceInitializer(chunk);
4310 !is(T == struct) && Args.length == 1 /* primitives, enums, arrays */
4312 Args.length == 1 && is(typeof({T t = args[0];})) /* conversions */
4314 is(typeof(T(args))) /* general constructors */)
4321 static if (Args.length == 1)
4322 static if (is(typeof(payload = x[0])))
4332 static if (is(typeof(chunk = T(args))))
4334 else static if (args.length == 1 && is(typeof(chunk = args[0])))
4336 else assert(0, "CTFE emplace doesn't support "
4337 ~ T.stringof ~ " from " ~ Args.stringof);
4341 S* p = () @trusted { return cast(S*) &chunk; }();
4342 emplaceInitializer(*p);
4346 else static if (is(typeof(chunk.__ctor(args))))
4348 // This catches the rare case of local types that keep a frame pointer
4349 emplaceInitializer(chunk);
4354 //We can't emplace. Try to diagnose a disabled postblit.
4355 static assert(!(Args.length == 1 && is(Args[0] : T)),
4356 convFormat("Cannot emplace a %1$s because %1$s.this(this) is annotated with @disable.", T.stringof));
4359 static assert(false,
4360 convFormat("%s cannot be emplaced from %s.", T.stringof, Args[].stringof));
4364 package void emplaceRef(UT, Args...)(ref UT chunk, auto ref Args args)
4365 if (is(UT == Unqual!UT))
4367 emplaceRef!(UT, UT)(chunk, args);
4370 //emplace helper functions
4371 private void emplaceInitializer(T)(ref T chunk) @trusted pure nothrow
4373 static if (!hasElaborateAssign!T && isAssignable!T)
4377 import core.stdc.string : memcpy;
4378 static immutable T init = T.init;
4379 memcpy(&chunk, &init, T.sizeof);
4385 Given a pointer $(D chunk) to uninitialized memory (but already typed
4386 as $(D T)), constructs an object of non-$(D class) type $(D T) at that
4387 address. If `T` is a class, initializes the class reference to null.
4389 Returns: A pointer to the newly constructed object (which is the same
4392 T* emplace(T)(T* chunk) @safe pure nothrow
4394 emplaceRef!T(*chunk);
4407 assert(s2[0].i == 42 && s2[1].i == 42);
4426 Given a pointer $(D chunk) to uninitialized memory (but already typed
4427 as a non-class type $(D T)), constructs an object of type $(D T) at
4428 that address from arguments $(D args). If `T` is a class, initializes
4429 the class reference to `args[0]`.
4431 This function can be $(D @trusted) if the corresponding constructor of
4432 $(D T) is $(D @safe).
4434 Returns: A pointer to the newly constructed object (which is the same
4437 T* emplace(T, Args...)(T* chunk, auto ref Args args)
4438 if (is(T == struct) || Args.length == 1)
4440 emplaceRef!T(*chunk, args);
4449 assert(*emplace!int(&a, b) == 42);
4459 private void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment, string typeName) @nogc pure nothrow
4461 assert(chunk.length >= typeSize, "emplace: Chunk size too small.");
4462 assert((cast(size_t) chunk.ptr) % typeAlignment == 0, "emplace: Chunk is not aligned.");
4466 Given a raw memory area $(D chunk), constructs an object of $(D class)
4467 type $(D T) at that address. The constructor is passed the arguments
4470 If `T` is an inner class whose `outer` field can be used to access an instance
4471 of the enclosing class, then `Args` must not be empty, and the first member of it
4472 must be a valid initializer for that `outer` field. Correct initialization of
4473 this field is essential to access members of the outer class inside `T` methods.
4476 $(D chunk) must be at least as large as $(D T) needs
4477 and should have an alignment multiple of $(D T)'s alignment. (The size
4478 of a $(D class) instance is obtained by using $(D
4479 __traits(classInstanceSize, T))).
4482 This function can be $(D @trusted) if the corresponding constructor of
4483 $(D T) is $(D @safe).
4485 Returns: The newly constructed object.
4487 T emplace(T, Args...)(void[] chunk, auto ref Args args)
4490 static assert(!isAbstractClass!T, T.stringof ~
4491 " is abstract and it can't be emplaced");
4493 enum classSize = __traits(classInstanceSize, T);
4494 testEmplaceChunk(chunk, classSize, classInstanceAlignment!T, T.stringof);
4495 auto result = cast(T) chunk.ptr;
4497 // Initialize the object in its pre-ctor state
4498 chunk[0 .. classSize] = typeid(T).initializer[];
4500 static if (isInnerClass!T)
4502 static assert(Args.length > 0,
4503 "Initializing an inner class requires a pointer to the outer class");
4504 static assert(is(Args[0] : typeof(T.outer)),
4505 "The first argument must be a pointer to the outer class");
4507 result.outer = args[0];
4508 alias args1 = args[1..$];
4510 else alias args1 = args;
4512 // Call the ctor if any
4513 static if (is(typeof(result.__ctor(args1))))
4515 // T defines a genuine constructor accepting args
4516 // Go the classic route: write .init first, then call ctor
4517 result.__ctor(args1);
4521 static assert(args1.length == 0 && !is(typeof(&T.__ctor)),
4522 "Don't know how to initialize an object of type "
4523 ~ T.stringof ~ " with arguments " ~ typeof(args1).stringof);
4534 this(int i){this.i = i;}
4536 auto buf = new void[__traits(classInstanceSize, C)];
4537 auto c = emplace!C(buf, 5);
4548 auto getI() { return i; }
4551 auto outerBuf = new void[__traits(classInstanceSize, Outer)];
4552 auto innerBuf = new void[__traits(classInstanceSize, Outer.Inner)];
4553 auto inner = innerBuf.emplace!(Outer.Inner)(outerBuf.emplace!Outer);
4554 assert(inner.getI == 3);
4557 @nogc pure nothrow @system unittest
4560 align(__conv_EmplaceTestClass.alignof) ubyte[__traits(classInstanceSize, __conv_EmplaceTestClass)] buf;
4561 auto k = emplace!__conv_EmplaceTestClass(buf, 5, var);
4567 Given a raw memory area $(D chunk), constructs an object of non-$(D
4568 class) type $(D T) at that address. The constructor is passed the
4569 arguments $(D args), if any.
4572 $(D chunk) must be at least as large
4573 as $(D T) needs and should have an alignment multiple of $(D T)'s
4577 This function can be $(D @trusted) if the corresponding constructor of
4578 $(D T) is $(D @safe).
4580 Returns: A pointer to the newly constructed object.
4582 T* emplace(T, Args...)(void[] chunk, auto ref Args args)
4583 if (!is(T == class))
4585 testEmplaceChunk(chunk, T.sizeof, T.alignof, T.stringof);
4586 emplaceRef!(T, Unqual!T)(*cast(Unqual!T*) chunk.ptr, args);
4587 return cast(T*) chunk.ptr;
4597 auto buf = new void[S.sizeof];
4601 auto s1 = emplace!S(buf, s);
4602 assert(s1.a == 42 && s1.b == 43);
4605 // Bulk of emplace unittests starts here
4607 @system unittest /* unions */
4622 assert(u1.a == "hello");
4625 version (unittest) private struct __conv_EmplaceTest
4630 assert(this.i == 3 && i == 5);
4633 this(int i, ref int j)
4635 assert(i == 5 && j == 6);
4646 version (unittest) private class __conv_EmplaceTestClass
4649 this(int i) @nogc @safe pure nothrow
4651 assert(this.i == 3 && i == 5);
4654 this(int i, ref int j) @nogc @safe pure nothrow
4656 assert(i == 5 && j == 6);
4662 @system unittest // bugzilla 15772
4664 abstract class Foo {}
4667 // test in emplaceInitializer
4668 static assert(!is(typeof(emplace!Foo(cast(Foo*) memory.ptr))));
4669 static assert( is(typeof(emplace!Bar(cast(Bar*) memory.ptr))));
4670 // test in the emplace overload that takes void[]
4671 static assert(!is(typeof(emplace!Foo(memory))));
4672 static assert( is(typeof(emplace!Bar(memory))));
4677 struct S { @disable this(); }
4679 static assert(!__traits(compiles, emplace(&s)));
4680 emplace(&s, S.init);
4707 this(this) @disable;
4716 static assert(!__traits(compiles, emplace(&ss2)));
4719 static assert(!__traits(compiles, emplace(&ss1, s1)));
4735 assert(ss1[0].i == 5 && ss1[1].i == 5);
4740 //Start testing emplace-args here
4747 K k = null, k2 = new K;
4763 void opAssign(S){assert(0);}
4768 assert(sa[0].i == 5 && sa[1].i == 5);
4771 //Start testing emplace-struct here
4773 // Test constructor branch
4778 double x = 5, y = 6;
4781 assert(x == 5 && y == 6);
4787 auto s1 = new void[S.sizeof];
4788 auto s2 = S(42, 43);
4789 assert(*emplace!S(cast(S*) s1.ptr, s2) == s2);
4790 assert(*emplace!S(cast(S*) s1, 44, 45) == S(44, 45));
4795 __conv_EmplaceTest k = void;
4803 __conv_EmplaceTest k = void;
4804 emplace(&k, 5, var);
4809 // Test matching fields branch
4812 struct S { uint n; }
4820 struct S { int a, b; this(int){} }
4822 static assert(!__traits(compiles, emplace!S(&s, 2, 3)));
4827 struct S { int a, b = 7; }
4828 S s1 = void, s2 = void;
4831 assert(s1.a == 2 && s1.b == 7);
4833 emplace!S(&s2, 2, 3);
4834 assert(s2.a == 2 && s2.b == 3);
4843 void opAssign(int){assert(0);}
4844 void opAssign(S){assert(0);}
4855 //postblit precedence
4858 //Works, but breaks in "-w -O" because of @@@9332@@@.
4859 //Uncomment test when 9332 is fixed.
4864 this(S other){assert(false);}
4865 this(int i){this.i = i;}
4869 assert(is(typeof({S b = a;}))); //Postblit
4870 assert(is(typeof({S b = S(a);}))); //Constructor
4880 static assert(!is(immutable S2 : S2));
4882 immutable is2 = (immutable S2).init;
4886 //nested structs and postblit
4892 this(int i){p = [i].ptr;}
4902 void opAssign(const SS)
4910 assert(*ssa.s.p == 5);
4911 assert(ssa.s.p != ssb.s.p);
4920 @disable this(this);
4925 static assert(!__traits(compiles, emplace(&s1, S1.init)));
4930 @disable this(this);
4934 static assert(!__traits(compiles, emplace(&s2, 1)));
4935 emplace(&s2, S2.init);
4943 static assert(!__traits(compiles, emplace(&ss1, SS1.init)));
4951 static assert(!__traits(compiles, emplace(&ss2, SS2.init)));
4954 // SS1 sss1 = s1; //This doesn't compile
4955 // SS1 sss1 = SS1(s1); //This doesn't compile
4956 // So emplace shouldn't compile either
4957 static assert(!__traits(compiles, emplace(&sss1, s1)));
4958 static assert(!__traits(compiles, emplace(&sss2, s2)));
4964 //Castable immutability
4970 static assert(is( immutable(S1) : S1));
4972 auto sb = immutable(S1)(5);
4976 //Un-castable immutability
4982 static assert(!is(immutable(S2) : S2));
4984 auto sb = immutable(S2)(null);
4985 assert(!__traits(compiles, emplace(&sa, sb)));
4997 emplace(&s, 1, null);
4998 emplace(&s, 2, &s.i);
4999 assert(s is S(2, &s.i));
5047 SS1 ss = SS1(1, S(2));
5057 S foo() @property{return s;}
5061 SS2 ss = SS2(1, S(2));
5072 this(__std_conv_SS ss) {assert(0);}
5073 static opCall(__std_conv_SS ss)
5075 __std_conv_S s; s.i = ss.j;
5079 struct __std_conv_SS
5083 ref __std_conv_S foo() return @property {s.i = j; return s;}
5086 static assert(is(__std_conv_SS : __std_conv_S));
5089 __std_conv_S s = void;
5090 __std_conv_SS ss = __std_conv_SS(1);
5092 __std_conv_S sTest1 = ss; //this calls "SS alias this" (and not "S.this(SS)")
5093 emplace(&s, ss); //"alias this" should take precedence in emplace over "opCall"
5109 assert(s1.a is s2.a);
5112 //safety & nothrow & CTFE
5115 //emplace should be safe for anything with no elaborate opassign
5123 this(int j)@safe nothrow{i = j;}
5134 void foo() @safe nothrow
5140 emplace(ps1, S1.init);
5143 emplace(ps2, S2.init);
5147 T bar(T)() @property
5149 T t/+ = void+/; //CTFE void illegal
5155 static assert(a == 5);
5157 static assert(b.i == 5);
5159 static assert(c.i == 5);
5174 int[2] get(){return [1, 2];}
5190 assert(ss.ii == [1, 2]);
5191 assert(iss.ii == [1, 2]);
5199 @disable void opAssign(S);
5202 emplace(&s, S.init);
5209 //Without constructor
5214 static S1 opCall(int*){assert(0);}
5217 static assert(!__traits(compiles, emplace(&s, 1)));
5224 static S2 opCall(int*){assert(0);}
5225 static S2 opCall(int){assert(0);}
5226 this(int i){this.i = i;}
5232 //With postblit ambiguity
5237 static S3 opCall(ref S3){assert(0);}
5240 emplace(&s, S3.init);
5244 @safe unittest //@@@9559@@@
5246 import std.algorithm.iteration : map;
5247 import std.array : array;
5248 import std.typecons : Nullable;
5249 alias I = Nullable!int;
5250 auto ints = [0, 1, 2].map!(i => i & 1 ? I.init : I(i))();
5251 auto asArray = array(ints);
5254 @system unittest //http://forum.dlang.org/post/nxbdgtdlmwscocbiypjs@forum.dlang.org
5256 import std.array : array;
5257 import std.datetime : SysTime, UTC;
5258 import std.math : isNaN;
5270 assert(a.i.isNaN(), "why is 'j' zero?? and i is not NaN?");
5272 assert(!a.i.isNaN());
5274 SysTime when; // comment this line avoid the breakage
5280 assert(&b1); // verify that default eyes invariants are ok;
5282 auto b2 = B(SysTime(0, UTC()), 1, A(1));
5284 auto b3 = B(SysTime(0, UTC()), 1, A(1));
5287 auto arr = [b2, b3];
5289 assert(arr[0].j == 1);
5290 assert(arr[1].j == 1);
5291 auto a2 = arr.array(); // << bang, invariant is raised, also if b2 and b3 are good
5303 immutable int[2] ii;
5314 static assert(!__traits(compiles, {S ss = S(uu);}));
5315 static assert(!__traits(compiles, emplace(&s, uu)));
5328 emplace(&sii, sii2);
5329 //emplace(&sii, uii2); //Sorry, this implementation doesn't know how to...
5330 //emplace(&uii, sii2); //Sorry, this implementation doesn't know how to...
5331 emplace(&uii, uii2);
5332 emplace(&sii, sii2[]);
5333 //emplace(&sii, uii2[]); //Sorry, this implementation doesn't know how to...
5334 //emplace(&uii, sii2[]); //Sorry, this implementation doesn't know how to...
5335 emplace(&uii, uii2[]);
5340 bool allowDestruction = false;
5345 ~this(){assert(allowDestruction);}
5353 emplace(&ss3, ss2[]);
5354 assert(ss1[1] == s);
5355 assert(ss2[1] == s);
5356 assert(ss3[1] == s);
5357 allowDestruction = true;
5362 //Checks postblit, construction, and context pointer
5392 S[2][2][2] sss = void;
5396 @system unittest //Constness
5401 emplaceRef!(const int)(a, 5);
5404 const(int)* p = void;
5405 emplaceRef!(const int*)(p, &i);
5411 alias IS = immutable(S);
5413 emplaceRef!IS(s, IS());
5415 emplaceRef!(IS[2])(ss, IS());
5417 IS[2] iss = IS.init;
5418 emplaceRef!(IS[2])(ss, iss);
5419 emplaceRef!(IS[2])(ss, iss[]);
5422 pure nothrow @safe @nogc unittest
5428 emplaceRef!int(i, 5);
5431 // Test attribute propagation for UDTs
5432 pure nothrow @safe /* @nogc */ unittest
5436 this(this) pure nothrow @safe @nogc {}
5440 emplaceRef(safe, Safe());
5442 Safe[1] safeArr = [Safe()];
5443 Safe[1] uninitializedSafeArr = void;
5444 emplaceRef(uninitializedSafeArr, safe);
5445 emplaceRef(uninitializedSafeArr, safeArr);
5447 static struct Unsafe
5449 this(this) @system {}
5452 Unsafe unsafe = void;
5453 static assert(!__traits(compiles, emplaceRef(unsafe, Unsafe())));
5455 Unsafe[1] unsafeArr = [Unsafe()];
5456 Unsafe[1] uninitializedUnsafeArr = void;
5457 static assert(!__traits(compiles, emplaceRef(uninitializedUnsafeArr, unsafe)));
5458 static assert(!__traits(compiles, emplaceRef(uninitializedUnsafeArr, unsafeArr)));
5471 import core.stdc.stdlib : malloc;
5472 void[] buf = malloc(Node.sizeof)[0 .. Node.sizeof];
5474 import std.conv : emplace;
5475 const Node* n = emplace!(const Node)(buf, 42, null, 10);
5476 assert(n.payload == 42);
5477 assert(n.next == null);
5478 assert(n.refs == 10);
5484 auto k = emplace!__conv_EmplaceTest(new void[__conv_EmplaceTest.sizeof], 5, var);
5497 assert(x == 5 && y == 42);
5503 static align(A.alignof) byte[__traits(classInstanceSize, A)] sbuf;
5505 auto a = emplace!A(buf, 55);
5506 assert(a.x == 55 && a.y == 55);
5508 // emplace in bigger buffer
5509 buf = new byte[](__traits(classInstanceSize, A) + 10);
5510 a = emplace!A(buf, 55);
5511 assert(a.x == 55 && a.y == 55);
5514 static assert(!is(typeof(emplace!A(buf))));
5516 // Bulk of emplace unittests ends here
5520 import std.algorithm.comparison : equal;
5521 import std.algorithm.iteration : map;
5522 // Check fix for http://d.puremagic.com/issues/show_bug.cgi?id=2971
5523 assert(equal(map!(to!int)(["42", "34", "345"]), [42, 34, 345]));
5526 // Undocumented for the time being
5527 void toTextRange(T, W)(T value, W writer)
5528 if (isIntegral!T && isOutputRange!(W, char))
5530 import core.internal.string : SignedStringBuf, signedToTempString,
5531 UnsignedStringBuf, unsignedToTempString;
5535 SignedStringBuf buf = void;
5536 put(writer, signedToTempString(value, buf, 10));
5540 UnsignedStringBuf buf = void;
5541 put(writer, unsignedToTempString(value, buf, 10));
5547 import std.array : appender;
5548 auto result = appender!(char[])();
5549 toTextRange(-1, result);
5550 assert(result.data == "-1");
5555 Returns the corresponding _unsigned value for $(D x) (e.g. if $(D x) has type
5556 $(D int), it returns $(D cast(uint) x)). The advantage compared to the cast
5557 is that you do not need to rewrite the cast if $(D x) later changes type
5558 (e.g from $(D int) to $(D long)).
5560 Note that the result is always mutable even if the original type was const
5561 or immutable. In order to retain the constness, use $(REF Unsigned, std,traits).
5563 auto unsigned(T)(T x)
5566 return cast(Unqual!(Unsigned!T))x;
5572 import std.traits : Unsigned;
5573 immutable int s = 42;
5574 auto u1 = unsigned(s); //not qualified
5575 static assert(is(typeof(u1) == uint));
5576 Unsigned!(typeof(s)) u2 = unsigned(s); //same qualification
5577 static assert(is(typeof(u2) == immutable uint));
5578 immutable u3 = unsigned(s); //explicitly qualified
5583 foreach (T; AliasSeq!(byte, ubyte))
5585 static assert(is(typeof(unsigned(cast(T) 1)) == ubyte));
5586 static assert(is(typeof(unsigned(cast(const T) 1)) == ubyte));
5587 static assert(is(typeof(unsigned(cast(immutable T) 1)) == ubyte));
5590 foreach (T; AliasSeq!(short, ushort))
5592 static assert(is(typeof(unsigned(cast(T) 1)) == ushort));
5593 static assert(is(typeof(unsigned(cast(const T) 1)) == ushort));
5594 static assert(is(typeof(unsigned(cast(immutable T) 1)) == ushort));
5597 foreach (T; AliasSeq!(int, uint))
5599 static assert(is(typeof(unsigned(cast(T) 1)) == uint));
5600 static assert(is(typeof(unsigned(cast(const T) 1)) == uint));
5601 static assert(is(typeof(unsigned(cast(immutable T) 1)) == uint));
5604 foreach (T; AliasSeq!(long, ulong))
5606 static assert(is(typeof(unsigned(cast(T) 1)) == ulong));
5607 static assert(is(typeof(unsigned(cast(const T) 1)) == ulong));
5608 static assert(is(typeof(unsigned(cast(immutable T) 1)) == ulong));
5612 auto unsigned(T)(T x)
5615 // All characters are unsigned
5616 static assert(T.min == 0);
5617 return cast(Unqual!T) x;
5622 foreach (T; AliasSeq!(char, wchar, dchar))
5624 static assert(is(typeof(unsigned(cast(T)'A')) == T));
5625 static assert(is(typeof(unsigned(cast(const T)'A')) == T));
5626 static assert(is(typeof(unsigned(cast(immutable T)'A')) == T));
5632 Returns the corresponding _signed value for $(D x) (e.g. if $(D x) has type
5633 $(D uint), it returns $(D cast(int) x)). The advantage compared to the cast
5634 is that you do not need to rewrite the cast if $(D x) later changes type
5635 (e.g from $(D uint) to $(D ulong)).
5637 Note that the result is always mutable even if the original type was const
5638 or immutable. In order to retain the constness, use $(REF Signed, std,traits).
5643 return cast(Unqual!(Signed!T))x;
5649 import std.traits : Signed;
5651 immutable uint u = 42;
5652 auto s1 = signed(u); //not qualified
5653 static assert(is(typeof(s1) == int));
5654 Signed!(typeof(u)) s2 = signed(u); //same qualification
5655 static assert(is(typeof(s2) == immutable int));
5656 immutable s3 = signed(u); //explicitly qualified
5661 foreach (T; AliasSeq!(byte, ubyte))
5663 static assert(is(typeof(signed(cast(T) 1)) == byte));
5664 static assert(is(typeof(signed(cast(const T) 1)) == byte));
5665 static assert(is(typeof(signed(cast(immutable T) 1)) == byte));
5668 foreach (T; AliasSeq!(short, ushort))
5670 static assert(is(typeof(signed(cast(T) 1)) == short));
5671 static assert(is(typeof(signed(cast(const T) 1)) == short));
5672 static assert(is(typeof(signed(cast(immutable T) 1)) == short));
5675 foreach (T; AliasSeq!(int, uint))
5677 static assert(is(typeof(signed(cast(T) 1)) == int));
5678 static assert(is(typeof(signed(cast(const T) 1)) == int));
5679 static assert(is(typeof(signed(cast(immutable T) 1)) == int));
5682 foreach (T; AliasSeq!(long, ulong))
5684 static assert(is(typeof(signed(cast(T) 1)) == long));
5685 static assert(is(typeof(signed(cast(const T) 1)) == long));
5686 static assert(is(typeof(signed(cast(immutable T) 1)) == long));
5700 Returns the representation of an enumerated value, i.e. the value converted to
5701 the base type of the enumeration.
5703 OriginalType!E asOriginalType(E)(E value) if (is(E == enum))
5712 static assert(is(typeof(A.a.asOriginalType) == int));
5713 assert(A.a.asOriginalType == 42);
5714 enum B : double { a = 43 }
5715 static assert(is(typeof(B.a.asOriginalType) == double));
5716 assert(B.a.asOriginalType == 43);
5720 A wrapper on top of the built-in cast operator that allows one to restrict
5721 casting of the original type of the value.
5723 A common issue with using a raw cast is that it may silently continue to
5724 compile even if the value's type has changed during refactoring,
5725 which breaks the initial assumption about the cast.
5728 From = The type to cast from. The programmer must ensure it is legal
5731 template castFrom(From)
5735 To = The type _to cast _to.
5736 value = The value _to cast. It must be of type $(D From),
5737 otherwise a compile-time error is emitted.
5740 the value after the cast, returned by reference if possible.
5742 auto ref to(To, T)(auto ref T value) @system
5746 "the value to cast is not of specified type '" ~ From.stringof ~
5747 "', it is of type '" ~ T.stringof ~ "'"
5751 is(typeof(cast(To) value)),
5752 "can't cast from '" ~ From.stringof ~ "' to '" ~ To.stringof ~ "'"
5755 return cast(To) value;
5762 // Regular cast, which has been verified to be legal by the programmer:
5765 auto y = cast(int) x;
5768 // However this will still compile if 'x' is changed to be a pointer:
5771 auto y = cast(int) x;
5774 // castFrom provides a more reliable alternative to casting:
5777 auto y = castFrom!long.to!int(x);
5780 // Changing the type of 'x' will now issue a compiler error,
5781 // allowing bad casts to be caught before it's too late:
5785 !__traits(compiles, castFrom!long.to!int(x))
5788 // if cast is still needed, must be changed to:
5789 auto y = castFrom!(long*).to!int(x);
5793 // https://issues.dlang.org/show_bug.cgi?id=16667
5796 ubyte[] a = ['a', 'b', 'c'];
5797 assert(castFrom!(ubyte[]).to!(string)(a) == "abc");
5801 Check the correctness of a string for $(D hexString).
5802 The result is true if and only if the input string is composed of whitespace
5803 characters (\f\n\r\t\v lineSep paraSep nelSep) and
5804 an even number of hexadecimal digits (regardless of the case).
5807 private bool isHexLiteral(String)(scope const String hexData)
5809 import std.ascii : isHexDigit;
5810 import std.uni : lineSep, paraSep, nelSep;
5812 foreach (const dchar c; hexData)
5840 // test all the hex digits
5841 static assert( ("0123456789abcdefABCDEF").isHexLiteral);
5842 // empty or white strings are not valid
5843 static assert( "\r\n\t".isHexLiteral);
5844 // but are accepted if the count of hex digits is even
5845 static assert( "A\r\n\tB".isHexLiteral);
5852 static assert( "".isHexLiteral);
5853 static assert( " \r".isHexLiteral);
5854 static assert( whitespace.isHexLiteral);
5855 static assert( ""w.isHexLiteral);
5856 static assert( " \r"w.isHexLiteral);
5857 static assert( ""d.isHexLiteral);
5858 static assert( " \r"d.isHexLiteral);
5859 static assert( "\u2028\u2029\u0085"d.isHexLiteral);
5861 static assert( !("5" ~ whitespace).isHexLiteral);
5862 static assert( !"123".isHexLiteral);
5863 static assert( !"1A3".isHexLiteral);
5864 static assert( !"1 23".isHexLiteral);
5865 static assert( !"\r\n\tC".isHexLiteral);
5866 static assert( !"123"w.isHexLiteral);
5867 static assert( !"1A3"w.isHexLiteral);
5868 static assert( !"1 23"w.isHexLiteral);
5869 static assert( !"\r\n\tC"w.isHexLiteral);
5870 static assert( !"123"d.isHexLiteral);
5871 static assert( !"1A3"d.isHexLiteral);
5872 static assert( !"1 23"d.isHexLiteral);
5873 static assert( !"\r\n\tC"d.isHexLiteral);
5874 // even x strings with invalid charset
5875 static assert( !"12gG".isHexLiteral);
5876 static assert( !"2A 3q".isHexLiteral);
5877 static assert( !"12gG"w.isHexLiteral);
5878 static assert( !"2A 3q"w.isHexLiteral);
5879 static assert( !"12gG"d.isHexLiteral);
5880 static assert( !"2A 3q"d.isHexLiteral);
5882 static assert( ("5A" ~ whitespace).isHexLiteral);
5883 static assert( ("5A 01A C FF de 1b").isHexLiteral);
5884 static assert( ("0123456789abcdefABCDEF").isHexLiteral);
5885 static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF").isHexLiteral);
5886 static assert( ("5A 01A C FF de 1b"w).isHexLiteral);
5887 static assert( ("0123456789abcdefABCDEF"w).isHexLiteral);
5888 static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"w).isHexLiteral);
5889 static assert( ("5A 01A C FF de 1b"d).isHexLiteral);
5890 static assert( ("0123456789abcdefABCDEF"d).isHexLiteral);
5891 static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"d).isHexLiteral);
5892 // library version allows what's pointed by issue 10454
5893 static assert( ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").isHexLiteral);
5897 Converts a hex literal to a string at compile time.
5899 Takes a string made of hexadecimal digits and returns
5900 the matching string by converting each pair of digits to a character.
5901 The input string can also include white characters, which can be used
5902 to keep the literal string readable in the source code.
5904 The function is intended to replace the hexadecimal literal strings
5905 starting with $(D 'x'), which could be removed to simplify the core language.
5908 hexData = string to be converted.
5911 a $(D string), a $(D wstring) or a $(D dstring), according to the type of hexData.
5913 template hexString(string hexData)
5914 if (hexData.isHexLiteral)
5916 immutable hexString = hexStrImpl(hexData);
5920 template hexString(wstring hexData)
5921 if (hexData.isHexLiteral)
5923 immutable hexString = hexStrImpl(hexData);
5927 template hexString(dstring hexData)
5928 if (hexData.isHexLiteral)
5930 immutable hexString = hexStrImpl(hexData);
5936 // conversion at compile time
5937 auto string1 = hexString!"304A314B";
5938 assert(string1 == "0J1K");
5939 auto string2 = hexString!"304A314B"w;
5940 assert(string2 == "0J1K"w);
5941 auto string3 = hexString!"304A314B"d;
5942 assert(string3 == "0J1K"d);
5946 Takes a hexadecimal string literal and returns its representation.
5947 hexData is granted to be a valid string by the caller.
5948 C is granted to be a valid char type by the caller.
5951 private auto hexStrImpl(String)(scope String hexData)
5953 import std.ascii : isHexDigit;
5954 alias C = Unqual!(ElementEncodingType!String);
5956 result.length = hexData.length / 2;
5959 foreach (c; hexData)
5964 if (c >= '0' && c <= '9')
5965 x = cast(ubyte)(c - '0');
5966 else if (c >= 'a' && c <= 'f')
5967 x = cast(ubyte)(c - ('a' - 10));
5968 else if (c >= 'A' && c <= 'F')
5969 x = cast(ubyte)(c - ('A' - 10));
5972 v = cast(ubyte)((v << 4) | x);
5973 result[cnt / 2] = v;
5980 result.length = cnt / 2;
5987 assert(hexString!"46 47 48 49 4A 4B" == "FGHIJK");
5988 assert(hexString!"30\r\n\t\f\v31 32 33 32 31 30" == "0123210");
5989 assert(hexString!"ab cd" == hexString!"ABCD");
5994 * Convert integer to a range of characters.
5995 * Intended to be lightweight and fast.
5998 * radix = 2, 8, 10, 16
5999 * Char = character type for output
6000 * letterCase = lower for deadbeef, upper for DEADBEEF
6001 * value = integer to convert. Can be uint or ulong. If radix is 10, can also be
6004 * Random access range with slicing and everything
6007 auto toChars(ubyte radix = 10, Char = char, LetterCase letterCase = LetterCase.lower, T)(T value)
6008 pure nothrow @nogc @safe
6009 if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) &&
6010 (is(Unqual!T == uint) || is(Unqual!T == ulong) ||
6011 radix == 10 && (is(Unqual!T == int) || is(Unqual!T == long))))
6013 alias UT = Unqual!T;
6015 static if (radix == 10)
6017 /* uint.max is 42_9496_7295
6018 * int.max is 21_4748_3647
6019 * ulong.max is 1844_6744_0737_0955_1615
6020 * long.max is 922_3372_0368_5477_5807
6022 static struct Result
6024 void initialize(UT value)
6033 buf[0] = cast(char)(cast(uint) value + '0');
6039 auto i = cast(uint) buf.length - 1;
6040 while (cast(Unsigned!UT) value >= 10)
6042 buf[i] = cast(ubyte)('0' + cast(Unsigned!UT) value % 10);
6043 value = unsigned(value) / 10;
6046 buf[i] = cast(char)(cast(uint) value + '0');
6053 upr = cast(uint) buf.length;
6056 @property size_t length() { return upr - lwr; }
6058 alias opDollar = length;
6060 @property bool empty() { return upr == lwr; }
6062 @property Char front() { return buf[lwr]; }
6064 void popFront() { ++lwr; }
6066 @property Char back() { return buf[upr - 1]; }
6068 void popBack() { --upr; }
6070 @property Result save() { return this; }
6072 Char opIndex(size_t i) { return buf[lwr + i]; }
6074 Result opSlice(size_t lwr, size_t upr)
6076 Result result = void;
6078 result.lwr = cast(uint)(this.lwr + lwr);
6079 result.upr = cast(uint)(this.lwr + upr);
6084 uint lwr = void, upr = void;
6085 char[(UT.sizeof == 4) ? 10 + isSigned!T : 20] buf = void;
6088 Result result = void;
6089 result.initialize(value);
6094 static if (radix == 2)
6096 else static if (radix == 8)
6098 else static if (radix == 16)
6102 static struct Result
6109 while (value >>>= SHIFT)
6114 @property size_t length() { return len; }
6116 @property bool empty() { return len == 0; }
6118 @property Char front() { return opIndex(0); }
6120 void popFront() { --len; }
6122 @property Char back() { return opIndex(len - 1); }
6130 @property Result save() { return this; }
6132 Char opIndex(size_t i)
6134 Char c = (value >>> ((len - i - 1) * SHIFT)) & ((1 << SHIFT) - 1);
6135 return cast(Char)((radix < 10 || c < 10) ? c + '0'
6136 : (letterCase == LetterCase.upper ? c + 'A' - 10
6140 Result opSlice(size_t lwr, size_t upr)
6142 Result result = void;
6143 result.value = value >>> ((len - upr) * SHIFT);
6144 result.len = cast(ubyte)(upr - lwr);
6153 return Result(value);
6164 assert(toChars!2(0u).array == "0");
6165 assert(toChars!2(0Lu).array == "0");
6166 assert(toChars!2(1u).array == "1");
6167 assert(toChars!2(1Lu).array == "1");
6169 auto r = toChars!2(2u);
6170 assert(r.length == 2);
6171 assert(r[0] == '1');
6172 assert(r[1 .. 2].array == "0");
6174 assert(r.array == "10");
6175 assert(s.retro.array == "01");
6178 assert(toChars!8(0u).array == "0");
6179 assert(toChars!8(0Lu).array == "0");
6180 assert(toChars!8(1u).array == "1");
6181 assert(toChars!8(1234567Lu).array == "4553207");
6183 auto r = toChars!8(8u);
6184 assert(r.length == 2);
6185 assert(r[0] == '1');
6186 assert(r[1 .. 2].array == "0");
6188 assert(r.array == "10");
6189 assert(s.retro.array == "01");
6192 assert(toChars!10(0u).array == "0");
6193 assert(toChars!10(0Lu).array == "0");
6194 assert(toChars!10(1u).array == "1");
6195 assert(toChars!10(1234567Lu).array == "1234567");
6196 assert(toChars!10(uint.max).array == "4294967295");
6197 assert(toChars!10(ulong.max).array == "18446744073709551615");
6199 auto r = toChars(10u);
6200 assert(r.length == 2);
6201 assert(r[0] == '1');
6202 assert(r[1 .. 2].array == "0");
6204 assert(r.array == "10");
6205 assert(s.retro.array == "01");
6208 assert(toChars!10(0).array == "0");
6209 assert(toChars!10(0L).array == "0");
6210 assert(toChars!10(1).array == "1");
6211 assert(toChars!10(1234567L).array == "1234567");
6212 assert(toChars!10(int.max).array == "2147483647");
6213 assert(toChars!10(long.max).array == "9223372036854775807");
6214 assert(toChars!10(-int.max).array == "-2147483647");
6215 assert(toChars!10(-long.max).array == "-9223372036854775807");
6216 assert(toChars!10(int.min).array == "-2147483648");
6217 assert(toChars!10(long.min).array == "-9223372036854775808");
6219 auto r = toChars!10(10);
6220 assert(r.length == 2);
6221 assert(r[0] == '1');
6222 assert(r[1 .. 2].array == "0");
6224 assert(r.array == "10");
6225 assert(s.retro.array == "01");
6228 assert(toChars!(16)(0u).array == "0");
6229 assert(toChars!(16)(0Lu).array == "0");
6230 assert(toChars!(16)(10u).array == "a");
6231 assert(toChars!(16, char, LetterCase.upper)(0x12AF34567Lu).array == "12AF34567");
6233 auto r = toChars!(16)(16u);
6234 assert(r.length == 2);
6235 assert(r[0] == '1');
6236 assert(r[1 .. 2].array == "0");
6238 assert(r.array == "10");
6239 assert(s.retro.array == "01");
6243 @safe unittest // opSlice (issue 16192)
6245 import std.meta : AliasSeq;
6247 static struct Test { ubyte radix; uint number; }
6249 alias tests = AliasSeq!(
6250 Test(2, 0b1_0110_0111u),
6251 Test(2, 0b10_1100_1110u),
6252 Test(8, octal!123456701u),
6253 Test(8, octal!1234567012u),
6254 Test(10, 123456789u),
6255 Test(10, 1234567890u),
6256 Test(16, 0x789ABCDu),
6257 Test(16, 0x789ABCDEu),
6260 foreach (test; tests)
6262 enum ubyte radix = test.radix;
6263 auto original = toChars!radix(test.number);
6265 // opSlice vs popFront
6266 auto r = original.save;
6268 for (; !r.empty; r.popFront(), ++i)
6270 assert(original[i .. original.length].tupleof == r.tupleof);
6271 // tupleof is used to work around issue 16216.
6274 // opSlice vs popBack
6277 for (; !r.empty; r.popBack(), ++i)
6279 assert(original[0 .. original.length - i].tupleof == r.tupleof);
6282 // opSlice vs both popFront and popBack
6285 for (; r.length >= 2; r.popFront(), r.popBack(), ++i)
6287 assert(original[i .. original.length - i].tupleof == r.tupleof);