For obj-c stage-final re-use the checksum from the previous stage
[official-gcc.git] / libphobos / src / std / conv.d
blob3560d134f58468eab47dfb093ccd49676003a0f3
1 // Written in the D programming language.
3 /**
4 A one-stop shop for converting values from one type to another.
6 $(SCRIPT inhibitQuickIndex = 1;)
7 $(BOOKTABLE,
8 $(TR $(TH Category) $(TH Functions))
9 $(TR $(TD Generic) $(TD
10 $(LREF asOriginalType)
11 $(LREF castFrom)
12 $(LREF emplace)
13 $(LREF parse)
14 $(LREF to)
15 $(LREF toChars)
17 $(TR $(TD Strings) $(TD
18 $(LREF text)
19 $(LREF wtext)
20 $(LREF dtext)
21 $(LREF hexString)
23 $(TR $(TD Numeric) $(TD
24 $(LREF octal)
25 $(LREF roundTo)
26 $(LREF signed)
27 $(LREF unsigned)
29 $(TR $(TD Exceptions) $(TD
30 $(LREF ConvException)
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),
41 Shin Fujishiro,
42 Adam D. Ruppe,
43 Kenji Hara
45 Source: $(PHOBOSSRC std/_conv.d)
48 module std.conv;
50 public import std.ascii : LetterCase;
52 import std.meta;
53 import std.range.primitives;
54 import std.traits;
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 *************** */
67 /**
68 * Thrown on conversion errors.
70 class ConvException : Exception
72 import std.exception : basicExceptionCtors;
73 ///
74 mixin basicExceptionCtors;
77 private auto convError(S, T)(S source, string fn = __FILE__, size_t ln = __LINE__)
79 string msg;
81 if (source.empty)
82 msg = "Unexpected end of input when converting from type " ~ S.stringof ~ " to type " ~ T.stringof;
83 else
85 ElementType!S el = source.front;
87 if (el == '\n')
88 msg = text("Unexpected '\\n' when converting from type " ~ S.stringof ~ " to type " ~ T.stringof);
89 else
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__)
99 string msg;
101 if (source.empty)
102 msg = text("Unexpected end of input when converting from type " ~ S.stringof ~ " base ", radix,
103 " to type " ~ T.stringof);
104 else
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__)
120 if (source.empty)
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);
124 source.popFront();
127 private
129 T toStr(T, S)(S src)
130 if (isSomeString!T)
132 // workaround for Bugzilla 14198
133 static if (is(S == bool) && is(typeof({ T s = "string"; })))
135 return src ? "true" : "false";
137 else
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);
145 return w.data;
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
171 @safe pure nothrow
172 this(string s, string fn = __FILE__, size_t ln = __LINE__)
174 super(s, fn, ln);
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)
193 $(I UnsignedInteger)
194 $(I Sign):
195 $(B +)
196 $(B -))
198 For conversion _to unsigned types, the grammar recognized is:
199 $(PRE $(I UnsignedInteger):
200 $(I DecimalDigit)
201 $(I DecimalDigit) $(I UnsignedInteger))
203 template to(T)
205 T to(A...)(A args)
206 if (A.length > 0)
208 return toImpl!T(args);
211 // Fix issue 6175
212 T to(S)(ref S arg)
213 if (isStaticArray!S)
215 return toImpl!T(arg);
218 // Fix issue 16108
219 T to(S)(ref S 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.
230 @safe pure unittest
232 int a = 42;
233 int b = to!int(a);
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`.)
246 @safe pure unittest
248 import std.exception : assertThrown;
250 int a = 420;
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.
269 @safe pure unittest
271 auto str = to!string(42, 16);
272 assert(str == "2A");
273 auto i = to!int(str, 16);
274 assert(i == 42);
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).
284 @safe pure unittest
286 // 2^24 - 1, largest proper integer representable as float
287 int a = 16_777_215;
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.
297 @safe pure unittest
299 import std.string : split;
301 int[] a = [1, 2, 3];
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]);
307 int[string] c;
308 c["a"] = 1;
309 c["b"] = 2;
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.
323 @safe unittest
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.
333 @safe pure unittest
335 import std.exception : assertThrown;
336 // Testing object conversions
337 class A {}
338 class B : A {}
339 class C : A {}
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.
348 * $(UL
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
359 * it is defined.)
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
393 auto w = "abcx"w;
394 const(void)[] b = w;
395 assert(b.length == 8);
397 auto c = to!(wchar[])(b);
398 assert(c == "abcx");
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
427 @safe pure unittest
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"));
445 alias ARR = int[];
446 assertThrown!ConvException(to!ARR(" [1]"));
448 alias AA = int[int];
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;
476 enforce(0 <= value,
477 new ConvOverflowException("Conversion negative overflow"));
480 return value;
483 @safe pure nothrow unittest
485 enum E { a } // Issue 9523 - Allow identity enum conversion
486 auto e = to!E(E.a);
487 assert(e == E.a);
490 @safe pure nothrow unittest
492 int a = 42;
493 auto b = to!long(a);
494 assert(a == b);
497 // Tests for issue 6377
498 @safe pure unittest
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))
509 // positive overflow
510 Uint un = Uint.max;
511 assertThrown!ConvOverflowException(to!Sint(un),
512 text(Sint.stringof, ' ', Uint.stringof, ' ', un));
514 // negative overflow
515 Sint sn = -1;
516 assertThrown!ConvOverflowException(to!Uint(sn),
517 text(Sint.stringof, ' ', Uint.stringof, ' ', un));
519 }();
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))
534 Uint un = Uint.max;
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))
543 Uint un = Uint.max;
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))
553 Sint sn = -1;
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))
561 Sint sn = -1;
562 assertThrown!ConvOverflowException(to!Uint(sn));
564 }();
568 Converting static arrays forwards to their dynamic counterparts.
570 private T toImpl(T, S)(ref S s)
571 if (isStaticArray!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();
595 @safe pure unittest
597 static struct Test
599 struct T
601 this(S s) @safe pure { }
603 struct S
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
611 Test.S s;
612 Test.T t = s;
615 @safe pure unittest
617 class B
619 T opCast(T)() { return 43; }
621 auto b = new B;
622 assert(to!int(b) == 43);
624 struct S
626 T opCast(T)() { return 43; }
628 auto s = S();
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))))
641 return T(value);
644 // Bugzilla 3961
645 @safe pure unittest
647 struct Int
649 int x;
651 Int i = to!Int(1);
653 static struct Int2
655 int x;
656 this(int x) @safe pure { this.x = x; }
658 Int2 i2 = to!Int2(1);
660 static struct Int3
662 int x;
663 static Int3 opCall(int x) @safe pure
665 Int3 i;
666 i.x = x;
667 return i;
670 Int3 i3 = to!Int3(1);
673 // Bugzilla 6808
674 @safe pure unittest
676 static struct FakeBigInt
678 this(string s) @safe pure {}
681 string s = "101";
682 auto i3 = to!FakeBigInt(s);
685 /// ditto
686 private T toImpl(T, S)(S value)
687 if (!isImplicitlyConvertible!(S, T) &&
688 is(T == class) && is(typeof(new T(value))))
690 return new T(value);
693 @safe pure unittest
695 static struct S
697 int x;
699 static class C
701 int x;
702 this(int x) @safe pure { this.x = x; }
705 static class B
707 int value;
708 this(S src) @safe pure { value = src.x; }
709 this(C src) @safe pure { value = src.x; }
712 S s = S(1);
713 auto b1 = to!B(s); // == new B(s)
714 assert(b1.value == 1);
716 C c = new C(2);
717 auto b2 = to!B(c); // == new B(c)
718 assert(b2.value == 2);
720 auto c2 = to!C(3); // == new C(3)
721 assert(c2.x == 3);
724 @safe pure unittest
726 struct S
728 class A
730 this(B b) @safe pure {}
732 class B : A
734 this() @safe pure { super(this); }
738 S.B b = new S.B();
739 S.A a = to!(S.A)(b); // == cast(S.A) b
740 // (do not run construction conversion like new S.A(b))
741 assert(b is a);
743 static class C : Object
745 this() @safe pure {}
746 this(Object o) @safe pure {}
749 Object oc = new C();
750 C a2 = to!C(oc); // == new C(a)
751 // Construction conversion overrides down-casting conversion
752 assert(a2 !is a); //
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);
778 else
780 // const <- mutable
781 // const <- immutable
782 enum isModConvertible = !is(S == shared);
785 else
787 static if (is(T == shared))
789 // shared <- shared mutable
790 enum isModConvertible = is(S == shared) && !is(S == const);
792 else
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);
807 return result;
810 // Unittest for 6288
811 @safe pure unittest
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)
821 if (0 <= n && n < 5)
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;
830 interface I {}
831 interface J {}
833 class A {}
834 class B : A {}
835 class C : B, I, J {}
836 class D : I {}
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
866 else
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
874 }();
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
891 return value.idup;
893 else
895 // conversion (immutable|const) -> mutable
896 return value.dup;
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();
905 w.put(value);
906 return w.data;
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 "
923 ~ T.stringof));
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.
931 return () @system {
932 static if (is(S : const(char)*))
933 import core.stdc.string : strlen;
934 else
935 size_t strlen(S s) nothrow
937 S p = s;
938 while (*p++) {}
939 return p-s-1;
941 return toImpl!T(value ? value[0 .. strlen(value)].dup : null);
942 }();
944 else static if (isSomeString!T && is(S == enum))
946 static if (isSwitchable!(OriginalType!S) && EnumMembers!S.length <= 50)
948 switch (value)
950 foreach (member; NoDuplicates!(EnumMembers!S))
952 case member:
953 return to!T(enumRep!(immutable(T), S, member));
955 default:
958 else
960 foreach (member; EnumMembers!S)
962 if (value == member)
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 ~ ")");
974 FormatSpec!char f;
975 formatValue(app, cast(OriginalType!S) value, f);
976 return app.data;
978 else
980 // other non-string values runs formatting
981 return toStr!T(value);
985 // Bugzilla 14042
986 @system unittest
988 immutable(char)* ptr = "hello".ptr;
989 auto result = ptr.to!(char[]);
991 // Bugzilla 8384
992 @system unittest
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))
1016 test1(e, "");
1017 test1(e.ptr, "");
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);
1035 return w.data;
1038 // Bugzilla 16108
1039 @system unittest
1041 static struct A
1043 int val;
1044 bool flag;
1046 string toString() { return text(val, ":", flag); }
1048 @disable this(this);
1051 auto a = A();
1052 assert(to!string(a) == "0:false");
1054 static struct B
1056 int val;
1057 bool flag;
1059 @disable this(this);
1062 auto b = B();
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: }
1074 }));
1078 @safe unittest
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);
1094 @safe pure unittest
1096 import std.exception;
1097 void dg()
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));
1120 foreach (T; Chars)
1122 foreach (U; Chars)
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));
1134 dg();
1135 assertCTFEable!dg;
1138 @safe pure unittest
1140 // Conversion representing bool value with string
1141 bool b;
1142 assert(to!string(b) == "false");
1143 b = true;
1144 assert(to!string(b) == "true");
1147 @safe pure unittest
1149 // Conversion representing character value with string
1150 alias AllChars =
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)
1158 Char1 c = 'a';
1159 assert(to!(Char2[])(c)[0] == c);
1161 uint x = 4;
1162 assert(to!(Char1[])(x) == "4");
1165 string s = "foo";
1166 string s2;
1167 foreach (char c; s)
1169 s2 ~= to!string(c);
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");
1201 assertCTFEable!(
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]");
1215 @system unittest
1217 // Conversion representing class object with string
1218 class A
1220 override string toString() const { return "an A"; }
1222 A a;
1223 assert(to!string(a) == "null");
1224 a = new A;
1225 assert(to!string(a) == "an A");
1227 // Bug 7660
1228 class C { override string toString() const { return "C"; } }
1229 struct S { C c; alias c this; }
1230 S s; s.c = new C();
1231 assert(to!string(s) == "C");
1234 @safe unittest
1236 // Conversion representing struct object with string
1237 struct S1
1239 string toString() { return "wyda"; }
1241 assert(to!string(S1()) == "wyda");
1243 struct S2
1245 int a = 42;
1246 float b = 43.5;
1248 S2 s2;
1249 assert(to!string(s2) == "S2(42, 43.5)");
1251 // Test for issue 8080
1252 struct S8080
1254 short[4] data;
1255 alias data this;
1256 string toString() { return "<S>"; }
1258 S8080 s8080;
1259 assert(to!string(s8080) == "<S>");
1262 @safe unittest
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);
1286 @safe unittest
1288 enum E
1290 foo,
1291 doo = foo, // check duplicate switch statements
1292 bar,
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);
1304 assert(s1 == s2);
1305 // ensure we don't allocate when it's unnecessary
1306 assert(s1 is s2);
1309 foreach (S; AliasSeq!(char[], wchar[], dchar[]))
1311 auto s1 = to!S(E.foo);
1312 auto s2 = to!S(E.foo);
1313 assert(s1 == s2);
1314 // ensure each mutable array is unique
1315 assert(s1 !is s2);
1319 // ditto
1320 @trusted pure private T toImpl(T, S)(S value, uint radix, LetterCase letterCase = LetterCase.upper)
1321 if (isIntegral!S &&
1322 isExactSomeString!T)
1325 assert(radix >= 2 && radix <= 36);
1327 body
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';
1338 char mod = void;
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;
1346 mValue = div;
1347 } while (mValue);
1349 return cast(T) buffer[index .. $].dup;
1352 import std.array : array;
1353 switch (radix)
1355 case 10:
1356 // The (value+0) is so integral promotions happen to the type
1357 return toChars!(10, EEType)(value + 0).array;
1358 case 16:
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;
1362 else
1363 return toChars!(16, EEType, LetterCase.lower)(unsigned(unsigned(value) + 0)).array;
1364 case 2:
1365 return toChars!(2, EEType)(unsigned(unsigned(value) + 0)).array;
1366 case 8:
1367 return toChars!(8, EEType)(unsigned(unsigned(value) + 0)).array;
1369 default:
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;
1414 else
1416 static assert(tSmallest < 0);
1417 immutable good = value >= tSmallest;
1419 if (!good)
1420 throw new ConvOverflowException("Conversion negative overflow");
1422 static if (S.max > T.max)
1424 // possible overflow
1425 if (value > T.max)
1426 throw new ConvOverflowException("Conversion positive overflow");
1428 return (ref value)@trusted{ return cast(T) value; }(value);
1431 @safe pure unittest
1433 import std.exception;
1435 dchar a = ' ';
1436 assert(to!char(a) == ' ');
1437 a = 300;
1438 assert(collectException(to!char(a)));
1440 dchar from0 = 'A';
1441 char to0 = to!char(from0);
1443 wchar from1 = 'A';
1444 char to1 = to!char(from1);
1446 char from2 = 'A';
1447 char to2 = to!char(from2);
1449 char from3 = 'A';
1450 wchar to3 = to!wchar(from3);
1452 char from4 = 'A';
1453 dchar to4 = to!dchar(from4);
1456 @safe unittest
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
1462 // type.
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];
1508 else
1510 import std.array : appender;
1511 auto w = appender!(E[])();
1512 w.reserve(value.length);
1513 foreach (i, ref e; value)
1515 w.put(to!E(e));
1517 return w.data;
1521 @safe pure unittest
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
1539 struct Wrap
1541 string wrap;
1542 alias wrap this;
1544 Wrap[] warr = to!(Wrap[])(["foo", "bar"]); // should work
1546 // Issue 12633
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];
1555 foreach (i; [1, 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!");
1563 @safe unittest
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;
1596 @safe unittest
1598 // hash to hash conversions
1599 int[string] a;
1600 a["0"] = 1;
1601 a["1"] = 2;
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)()
1624 Integral a = 42;
1625 auto b = to!Floating(a);
1626 assert(a == b);
1627 assert(a == to!Integral(b));
1630 private void testFloatingToIntegral(Floating, Integral)()
1632 import std.math : floatTraits, RealFormat;
1634 bool convFails(Source, Target, E)(Source src)
1637 auto t = to!Target(src);
1638 catch (E)
1639 return true;
1640 return false;
1643 // convert some value
1644 Floating a = 4.2e1;
1645 auto b = to!Integral(a);
1646 assert(is(typeof(b) == Integral) && b == 42);
1647 // convert some negative value (if applicable)
1648 a = -4.2e1;
1649 static if (Integral.min < 0)
1651 b = to!Integral(a);
1652 assert(is(typeof(b) == Integral) && b == -42);
1654 else
1656 // no go for unsigned types
1657 assert(convFails!(Floating, Integral, ConvOverflowException)(a));
1659 // convert to the smallest integral value
1660 a = 0.0 + Integral.min;
1661 static if (Integral.min < 0)
1663 a = -a; // -Integral.min not representable as an Integral
1664 assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1665 || Floating.sizeof <= Integral.sizeof
1666 || floatTraits!Floating.realFormat == RealFormat.ieeeExtended53);
1668 a = 0.0 + Integral.min;
1669 assert(to!Integral(a) == Integral.min);
1670 --a; // no more representable as an Integral
1671 assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1672 || Floating.sizeof <= Integral.sizeof
1673 || floatTraits!Floating.realFormat == RealFormat.ieeeExtended53);
1674 a = 0.0 + Integral.max;
1675 assert(to!Integral(a) == Integral.max
1676 || Floating.sizeof <= Integral.sizeof
1677 || floatTraits!Floating.realFormat == RealFormat.ieeeExtended53);
1678 ++a; // no more representable as an Integral
1679 assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1680 || Floating.sizeof <= Integral.sizeof
1681 || floatTraits!Floating.realFormat == RealFormat.ieeeExtended53);
1682 // convert a value with a fractional part
1683 a = 3.14;
1684 assert(to!Integral(a) == 3);
1685 a = 3.99;
1686 assert(to!Integral(a) == 3);
1687 static if (Integral.min < 0)
1689 a = -3.14;
1690 assert(to!Integral(a) == -3);
1691 a = -3.99;
1692 assert(to!Integral(a) == -3);
1696 @safe pure unittest
1698 alias AllInts = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong);
1699 alias AllFloats = AliasSeq!(float, double, real);
1700 alias AllNumerics = AliasSeq!(AllInts, AllFloats);
1701 // test with same type
1703 foreach (T; AllNumerics)
1705 T a = 42;
1706 auto b = to!T(a);
1707 assert(is(typeof(a) == typeof(b)) && a == b);
1710 // test that floating-point numbers convert properly to largest ints
1711 // see http://oregonstate.edu/~peterseb/mth351/docs/351s2001_fp80x87.html
1712 // look for "largest fp integer with a predecessor"
1714 // float
1715 int a = 16_777_215; // 2^24 - 1
1716 assert(to!int(to!float(a)) == a);
1717 assert(to!int(to!float(-a)) == -a);
1718 // double
1719 long b = 9_007_199_254_740_991; // 2^53 - 1
1720 assert(to!long(to!double(b)) == b);
1721 assert(to!long(to!double(-b)) == -b);
1722 // real
1723 static if (real.mant_dig >= 64)
1725 ulong c = 18_446_744_073_709_551_615UL; // 2^64 - 1
1726 assert(to!ulong(to!real(c)) == c);
1729 // test conversions floating => integral
1731 // AllInts[0 .. $ - 1] should be AllInts
1732 // @@@ BUG IN COMPILER @@@
1733 foreach (Integral; AllInts[0 .. $ - 1])
1735 foreach (Floating; AllFloats)
1737 testFloatingToIntegral!(Floating, Integral)();
1741 // test conversion integral => floating
1743 foreach (Integral; AllInts[0 .. $ - 1])
1745 foreach (Floating; AllFloats)
1747 testIntegralToFloating!(Integral, Floating)();
1751 // test parsing
1753 foreach (T; AllNumerics)
1755 // from type immutable(char)[2]
1756 auto a = to!T("42");
1757 assert(a == 42);
1758 // from type char[]
1759 char[] s1 = "42".dup;
1760 a = to!T(s1);
1761 assert(a == 42);
1762 // from type char[2]
1763 char[2] s2;
1764 s2[] = "42";
1765 a = to!T(s2);
1766 assert(a == 42);
1767 // from type immutable(wchar)[2]
1768 a = to!T("42"w);
1769 assert(a == 42);
1774 @safe unittest
1776 alias AllInts = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong);
1777 alias AllFloats = AliasSeq!(float, double, real);
1778 alias AllNumerics = AliasSeq!(AllInts, AllFloats);
1779 // test conversions to string
1781 foreach (T; AllNumerics)
1783 T a = 42;
1784 assert(to!string(a) == "42");
1785 assert(to!wstring(a) == "42"w);
1786 assert(to!dstring(a) == "42"d);
1787 // array test
1788 T[] b = new T[2];
1789 b[0] = 42;
1790 b[1] = 33;
1791 assert(to!string(b) == "[42, 33]");
1794 // test array to string conversion
1795 foreach (T ; AllNumerics)
1797 auto a = [to!T(1), 2, 3];
1798 assert(to!string(a) == "[1, 2, 3]");
1800 // test enum to int conversion
1801 enum Testing { Test1, Test2 }
1802 Testing t;
1803 auto a = to!string(t);
1804 assert(a == "Test1");
1809 String, or string-like input range, to non-string conversion runs parsing.
1810 $(UL
1811 $(LI When the source is a wide string, it is first converted to a narrow
1812 string and then parsed.)
1813 $(LI When the source is a narrow string, normal text parsing occurs.))
1815 private T toImpl(T, S)(S value)
1816 if (isInputRange!S && isSomeChar!(ElementEncodingType!S) &&
1817 !isExactSomeString!T && is(typeof(parse!T(value))))
1819 scope(success)
1821 if (!value.empty)
1823 throw convError!(S, T)(value);
1826 return parse!T(value);
1829 /// ditto
1830 private T toImpl(T, S)(S value, uint radix)
1831 if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S) &&
1832 isIntegral!T && is(typeof(parse!T(value, radix))))
1834 scope(success)
1836 if (!value.empty)
1838 throw convError!(S, T)(value);
1841 return parse!T(value, radix);
1844 @safe pure unittest
1846 // Issue 6668 - ensure no collaterals thrown
1847 try { to!uint("-1"); }
1848 catch (ConvException e) { assert(e.next is null); }
1851 @safe pure unittest
1853 foreach (Str; AliasSeq!(string, wstring, dstring))
1855 Str a = "123";
1856 assert(to!int(a) == 123);
1857 assert(to!double(a) == 123);
1860 // 6255
1861 auto n = to!int("FF", 16);
1862 assert(n == 255);
1865 // bugzilla 15800
1866 @safe unittest
1868 import std.utf : byCodeUnit, byChar, byWchar, byDchar;
1870 assert(to!int(byCodeUnit("10")) == 10);
1871 assert(to!int(byCodeUnit("10"), 10) == 10);
1872 assert(to!int(byCodeUnit("10"w)) == 10);
1873 assert(to!int(byCodeUnit("10"w), 10) == 10);
1875 assert(to!int(byChar("10")) == 10);
1876 assert(to!int(byChar("10"), 10) == 10);
1877 assert(to!int(byWchar("10")) == 10);
1878 assert(to!int(byWchar("10"), 10) == 10);
1879 assert(to!int(byDchar("10")) == 10);
1880 assert(to!int(byDchar("10"), 10) == 10);
1884 Convert a value that is implicitly convertible to the enum base type
1885 into an Enum value. If the value does not match any enum member values
1886 a ConvException is thrown.
1887 Enums with floating-point or string base types are not supported.
1889 private T toImpl(T, S)(S value)
1890 if (is(T == enum) && !is(S == enum)
1891 && is(typeof(value == OriginalType!T.init))
1892 && !isFloatingPoint!(OriginalType!T) && !isSomeString!(OriginalType!T))
1894 foreach (Member; EnumMembers!T)
1896 if (Member == value)
1897 return Member;
1899 throw new ConvException(convFormat("Value (%s) does not match any member value of enum '%s'", value, T.stringof));
1902 @safe pure unittest
1904 import std.exception;
1905 enum En8143 : int { A = 10, B = 20, C = 30, D = 20 }
1906 enum En8143[][] m3 = to!(En8143[][])([[10, 30], [30, 10]]);
1907 static assert(m3 == [[En8143.A, En8143.C], [En8143.C, En8143.A]]);
1909 En8143 en1 = to!En8143(10);
1910 assert(en1 == En8143.A);
1911 assertThrown!ConvException(to!En8143(5)); // matches none
1912 En8143[][] m1 = to!(En8143[][])([[10, 30], [30, 10]]);
1913 assert(m1 == [[En8143.A, En8143.C], [En8143.C, En8143.A]]);
1916 /***************************************************************
1917 Rounded conversion from floating point to integral.
1919 Rounded conversions do not work with non-integral target types.
1922 template roundTo(Target)
1924 Target roundTo(Source)(Source value)
1926 import std.math : trunc;
1928 static assert(isFloatingPoint!Source);
1929 static assert(isIntegral!Target);
1930 return to!Target(trunc(value + (value < 0 ? -0.5L : 0.5L)));
1935 @safe unittest
1937 assert(roundTo!int(3.14) == 3);
1938 assert(roundTo!int(3.49) == 3);
1939 assert(roundTo!int(3.5) == 4);
1940 assert(roundTo!int(3.999) == 4);
1941 assert(roundTo!int(-3.14) == -3);
1942 assert(roundTo!int(-3.49) == -3);
1943 assert(roundTo!int(-3.5) == -4);
1944 assert(roundTo!int(-3.999) == -4);
1945 assert(roundTo!(const int)(to!(const double)(-3.999)) == -4);
1948 @safe unittest
1950 import std.exception;
1951 // boundary values
1952 foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint))
1954 assert(roundTo!Int(Int.min - 0.4L) == Int.min);
1955 assert(roundTo!Int(Int.max + 0.4L) == Int.max);
1956 assertThrown!ConvOverflowException(roundTo!Int(Int.min - 0.5L));
1957 assertThrown!ConvOverflowException(roundTo!Int(Int.max + 0.5L));
1962 The $(D parse) family of functions works quite like the $(D to)
1963 family, except that:
1964 $(OL
1965 $(LI It only works with character ranges as input.)
1966 $(LI It takes the input by reference. (This means that rvalues - such
1967 as string literals - are not accepted: use $(D to) instead.))
1968 $(LI It advances the input to the position following the conversion.)
1969 $(LI It does not throw if it could not convert the entire input.))
1971 This overload converts an character input range to a `bool`.
1973 Params:
1974 Target = the type to convert to
1975 source = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
1977 Returns:
1978 A `bool`
1980 Throws:
1981 A $(LREF ConvException) if the range does not represent a `bool`.
1983 Note:
1984 All character input range conversions using $(LREF to) are forwarded
1985 to `parse` and do not require lvalues.
1987 Target parse(Target, Source)(ref Source source)
1988 if (isInputRange!Source &&
1989 isSomeChar!(ElementType!Source) &&
1990 is(Unqual!Target == bool))
1992 import std.ascii : toLower;
1994 static if (isNarrowString!Source)
1996 import std.string : representation;
1997 auto s = source.representation;
1999 else
2001 alias s = source;
2004 if (!s.empty)
2006 auto c1 = toLower(s.front);
2007 bool result = c1 == 't';
2008 if (result || c1 == 'f')
2010 s.popFront();
2011 foreach (c; result ? "rue" : "alse")
2013 if (s.empty || toLower(s.front) != c)
2014 goto Lerr;
2015 s.popFront();
2018 static if (isNarrowString!Source)
2019 source = cast(Source) s;
2021 return result;
2024 Lerr:
2025 throw parseError("bool should be case-insensitive 'true' or 'false'");
2029 @safe unittest
2031 auto s = "true";
2032 bool b = parse!bool(s);
2033 assert(b);
2036 @safe unittest
2038 import std.algorithm.comparison : equal;
2039 import std.exception;
2040 struct InputString
2042 string _s;
2043 @property auto front() { return _s.front; }
2044 @property bool empty() { return _s.empty; }
2045 void popFront() { _s.popFront(); }
2048 auto s = InputString("trueFALSETrueFalsetRUEfALSE");
2049 assert(parse!bool(s) == true);
2050 assert(s.equal("FALSETrueFalsetRUEfALSE"));
2051 assert(parse!bool(s) == false);
2052 assert(s.equal("TrueFalsetRUEfALSE"));
2053 assert(parse!bool(s) == true);
2054 assert(s.equal("FalsetRUEfALSE"));
2055 assert(parse!bool(s) == false);
2056 assert(s.equal("tRUEfALSE"));
2057 assert(parse!bool(s) == true);
2058 assert(s.equal("fALSE"));
2059 assert(parse!bool(s) == false);
2060 assert(s.empty);
2062 foreach (ss; ["tfalse", "ftrue", "t", "f", "tru", "fals", ""])
2064 s = InputString(ss);
2065 assertThrown!ConvException(parse!bool(s));
2070 Parses a character $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
2071 to an integral value.
2073 Params:
2074 Target = the integral type to convert to
2075 s = the lvalue of an input range
2077 Returns:
2078 A number of type `Target`
2080 Throws:
2081 A $(LREF ConvException) If an overflow occurred during conversion or
2082 if no character of the input was meaningfully converted.
2084 Target parse(Target, Source)(ref Source s)
2085 if (isSomeChar!(ElementType!Source) &&
2086 isIntegral!Target && !is(Target == enum))
2088 static if (Target.sizeof < int.sizeof)
2090 // smaller types are handled like integers
2091 auto v = .parse!(Select!(Target.min < 0, int, uint))(s);
2092 auto result = ()@trusted{ return cast(Target) v; }();
2093 if (result == v)
2094 return result;
2095 throw new ConvOverflowException("Overflow in integral conversion");
2097 else
2099 // int or larger types
2101 static if (Target.min < 0)
2102 bool sign = false;
2103 else
2104 enum bool sign = false;
2106 enum char maxLastDigit = Target.min < 0 ? 7 : 5;
2107 uint c;
2109 static if (isNarrowString!Source)
2111 import std.string : representation;
2112 auto source = s.representation;
2114 else
2116 alias source = s;
2119 if (source.empty)
2120 goto Lerr;
2122 c = source.front;
2124 static if (Target.min < 0)
2126 switch (c)
2128 case '-':
2129 sign = true;
2130 goto case '+';
2131 case '+':
2132 source.popFront();
2134 if (source.empty)
2135 goto Lerr;
2137 c = source.front;
2139 break;
2141 default:
2142 break;
2145 c -= '0';
2146 if (c <= 9)
2148 Target v = cast(Target) c;
2150 source.popFront();
2152 while (!source.empty)
2154 c = cast(typeof(c)) (source.front - '0');
2156 if (c > 9)
2157 break;
2159 if (v >= 0 && (v < Target.max/10 ||
2160 (v == Target.max/10 && c <= maxLastDigit + sign)))
2162 // Note: `v` can become negative here in case of parsing
2163 // the most negative value:
2164 v = cast(Target) (v * 10 + c);
2166 source.popFront();
2168 else
2169 throw new ConvOverflowException("Overflow in integral conversion");
2172 if (sign)
2173 v = -v;
2175 static if (isNarrowString!Source)
2176 s = cast(Source) source;
2178 return v;
2180 Lerr:
2181 static if (isNarrowString!Source)
2182 throw convError!(Source, Target)(cast(Source) source);
2183 else
2184 throw convError!(Source, Target)(source);
2189 @safe pure unittest
2191 string s = "123";
2192 auto a = parse!int(s);
2193 assert(a == 123);
2195 // parse only accepts lvalues
2196 static assert(!__traits(compiles, parse!int("123")));
2200 @safe pure unittest
2202 import std.string : tr;
2203 string test = "123 \t 76.14";
2204 auto a = parse!uint(test);
2205 assert(a == 123);
2206 assert(test == " \t 76.14"); // parse bumps string
2207 test = tr(test, " \t\n\r", "", "d"); // skip ws
2208 assert(test == "76.14");
2209 auto b = parse!double(test);
2210 assert(b == 76.14);
2211 assert(test == "");
2214 @safe pure unittest
2216 foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2219 assert(to!Int("0") == 0);
2221 static if (isSigned!Int)
2223 assert(to!Int("+0") == 0);
2224 assert(to!Int("-0") == 0);
2228 static if (Int.sizeof >= byte.sizeof)
2230 assert(to!Int("6") == 6);
2231 assert(to!Int("23") == 23);
2232 assert(to!Int("68") == 68);
2233 assert(to!Int("127") == 0x7F);
2235 static if (isUnsigned!Int)
2237 assert(to!Int("255") == 0xFF);
2239 static if (isSigned!Int)
2241 assert(to!Int("+6") == 6);
2242 assert(to!Int("+23") == 23);
2243 assert(to!Int("+68") == 68);
2244 assert(to!Int("+127") == 0x7F);
2246 assert(to!Int("-6") == -6);
2247 assert(to!Int("-23") == -23);
2248 assert(to!Int("-68") == -68);
2249 assert(to!Int("-128") == -128);
2253 static if (Int.sizeof >= short.sizeof)
2255 assert(to!Int("468") == 468);
2256 assert(to!Int("32767") == 0x7FFF);
2258 static if (isUnsigned!Int)
2260 assert(to!Int("65535") == 0xFFFF);
2262 static if (isSigned!Int)
2264 assert(to!Int("+468") == 468);
2265 assert(to!Int("+32767") == 0x7FFF);
2267 assert(to!Int("-468") == -468);
2268 assert(to!Int("-32768") == -32768);
2272 static if (Int.sizeof >= int.sizeof)
2274 assert(to!Int("2147483647") == 0x7FFFFFFF);
2276 static if (isUnsigned!Int)
2278 assert(to!Int("4294967295") == 0xFFFFFFFF);
2281 static if (isSigned!Int)
2283 assert(to!Int("+2147483647") == 0x7FFFFFFF);
2285 assert(to!Int("-2147483648") == -2147483648);
2289 static if (Int.sizeof >= long.sizeof)
2291 assert(to!Int("9223372036854775807") == 0x7FFFFFFFFFFFFFFF);
2293 static if (isUnsigned!Int)
2295 assert(to!Int("18446744073709551615") == 0xFFFFFFFFFFFFFFFF);
2298 static if (isSigned!Int)
2300 assert(to!Int("+9223372036854775807") == 0x7FFFFFFFFFFFFFFF);
2302 assert(to!Int("-9223372036854775808") == 0x8000000000000000);
2308 @safe pure unittest
2310 import std.exception;
2311 // parsing error check
2312 foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2315 immutable string[] errors1 =
2318 "-",
2319 "+",
2320 "-+",
2321 " ",
2322 " 0",
2323 "0 ",
2324 "- 0",
2325 "1-",
2326 "xx",
2327 "123h",
2328 "-+1",
2329 "--1",
2330 "+-1",
2331 "++1",
2333 foreach (j, s; errors1)
2334 assertThrown!ConvException(to!Int(s));
2337 // parse!SomeUnsigned cannot parse head sign.
2338 static if (isUnsigned!Int)
2340 immutable string[] errors2 =
2342 "+5",
2343 "-78",
2345 foreach (j, s; errors2)
2346 assertThrown!ConvException(to!Int(s));
2350 // positive overflow check
2351 foreach (i, Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2353 immutable string[] errors =
2355 "128", // > byte.max
2356 "256", // > ubyte.max
2357 "32768", // > short.max
2358 "65536", // > ushort.max
2359 "2147483648", // > int.max
2360 "4294967296", // > uint.max
2361 "9223372036854775808", // > long.max
2362 "18446744073709551616", // > ulong.max
2364 foreach (j, s; errors[i..$])
2365 assertThrown!ConvOverflowException(to!Int(s));
2368 // negative overflow check
2369 foreach (i, Int; AliasSeq!(byte, short, int, long))
2371 immutable string[] errors =
2373 "-129", // < byte.min
2374 "-32769", // < short.min
2375 "-2147483649", // < int.min
2376 "-9223372036854775809", // < long.min
2378 foreach (j, s; errors[i..$])
2379 assertThrown!ConvOverflowException(to!Int(s));
2383 @safe pure unittest
2385 void checkErrMsg(string input, dchar charInMsg, dchar charNotInMsg)
2389 int x = input.to!int();
2390 assert(false, "Invalid conversion did not throw");
2392 catch (ConvException e)
2394 // Ensure error message contains failing character, not the character
2395 // beyond.
2396 import std.algorithm.searching : canFind;
2397 assert( e.msg.canFind(charInMsg) &&
2398 !e.msg.canFind(charNotInMsg));
2400 catch (Exception e)
2402 assert(false, "Did not throw ConvException");
2405 checkErrMsg("@$", '@', '$');
2406 checkErrMsg("@$123", '@', '$');
2407 checkErrMsg("1@$23", '@', '$');
2408 checkErrMsg("1@$", '@', '$');
2409 checkErrMsg("1@$2", '@', '$');
2410 checkErrMsg("12@$", '@', '$');
2413 @safe pure unittest
2415 import std.exception;
2416 assertCTFEable!({ string s = "1234abc"; assert(parse! int(s) == 1234 && s == "abc"); });
2417 assertCTFEable!({ string s = "-1234abc"; assert(parse! int(s) == -1234 && s == "abc"); });
2418 assertCTFEable!({ string s = "1234abc"; assert(parse!uint(s) == 1234 && s == "abc"); });
2421 // Issue 13931
2422 @safe pure unittest
2424 import std.exception;
2426 assertThrown!ConvOverflowException("-21474836480".to!int());
2427 assertThrown!ConvOverflowException("-92233720368547758080".to!long());
2430 // Issue 14396
2431 @safe pure unittest
2433 struct StrInputRange
2435 this (string s) { str = s; }
2436 char front() const @property { return str[front_index]; }
2437 char popFront() { return str[front_index++]; }
2438 bool empty() const @property { return str.length <= front_index; }
2439 string str;
2440 size_t front_index = 0;
2442 auto input = StrInputRange("777");
2443 assert(parse!int(input) == 777);
2446 /// ditto
2447 Target parse(Target, Source)(ref Source source, uint radix)
2448 if (isSomeChar!(ElementType!Source) &&
2449 isIntegral!Target && !is(Target == enum))
2452 assert(radix >= 2 && radix <= 36);
2454 body
2456 import core.checkedint : mulu, addu;
2457 import std.exception : enforce;
2459 if (radix == 10)
2460 return parse!Target(source);
2462 enforce!ConvException(!source.empty, "s must not be empty in integral parse");
2464 immutable uint beyond = (radix < 10 ? '0' : 'a'-10) + radix;
2465 Target v = 0;
2467 static if (isNarrowString!Source)
2469 import std.string : representation;
2470 auto s = source.representation;
2472 else
2474 alias s = source;
2479 uint c = s.front;
2480 if (c < '0')
2481 break;
2482 if (radix < 10)
2484 if (c >= beyond)
2485 break;
2487 else
2489 if (c > '9')
2491 c |= 0x20;//poorman's tolower
2492 if (c < 'a' || c >= beyond)
2493 break;
2494 c -= 'a'-10-'0';
2498 bool overflow = false;
2499 auto nextv = v.mulu(radix, overflow).addu(c - '0', overflow);
2500 enforce!ConvOverflowException(!overflow && nextv <= Target.max, "Overflow in integral conversion");
2501 v = cast(Target) nextv;
2502 s.popFront();
2503 } while (!s.empty);
2505 static if (isNarrowString!Source)
2506 source = cast(Source) s;
2508 return v;
2511 @safe pure unittest
2513 string s; // parse doesn't accept rvalues
2514 foreach (i; 2 .. 37)
2516 assert(parse!int(s = "0", i) == 0);
2517 assert(parse!int(s = "1", i) == 1);
2518 assert(parse!byte(s = "10", i) == i);
2521 assert(parse!int(s = "0011001101101", 2) == 0b0011001101101);
2522 assert(parse!int(s = "765", 8) == octal!765);
2523 assert(parse!int(s = "fCDe", 16) == 0xfcde);
2525 // 6609
2526 assert(parse!int(s = "-42", 10) == -42);
2528 assert(parse!ubyte(s = "ff", 16) == 0xFF);
2531 @safe pure unittest // bugzilla 7302
2533 import std.range : cycle;
2534 auto r = cycle("2A!");
2535 auto u = parse!uint(r, 16);
2536 assert(u == 42);
2537 assert(r.front == '!');
2540 @safe pure unittest // bugzilla 13163
2542 import std.exception;
2543 foreach (s; ["fff", "123"])
2544 assertThrown!ConvOverflowException(s.parse!ubyte(16));
2547 @safe pure unittest // bugzilla 17282
2549 auto str = "0=\x00\x02\x55\x40&\xff\xf0\n\x00\x04\x55\x40\xff\xf0~4+10\n";
2550 assert(parse!uint(str) == 0);
2554 * Takes a string representing an `enum` type and returns that type.
2556 * Params:
2557 * Target = the `enum` type to convert to
2558 * s = the lvalue of the range to _parse
2560 * Returns:
2561 * An `enum` of type `Target`
2563 * Throws:
2564 * A $(LREF ConvException) if type `Target` does not have a member
2565 * represented by `s`.
2567 Target parse(Target, Source)(ref Source s)
2568 if (isSomeString!Source && !is(Source == enum) &&
2569 is(Target == enum))
2571 import std.algorithm.searching : startsWith;
2572 Target result;
2573 size_t longest_match = 0;
2575 foreach (i, e; EnumMembers!Target)
2577 auto ident = __traits(allMembers, Target)[i];
2578 if (longest_match < ident.length && s.startsWith(ident))
2580 result = e;
2581 longest_match = ident.length ;
2585 if (longest_match > 0)
2587 s = s[longest_match .. $];
2588 return result ;
2591 throw new ConvException(
2592 Target.stringof ~ " does not have a member named '"
2593 ~ to!string(s) ~ "'");
2597 @safe unittest
2599 enum EnumType : bool { a = true, b = false, c = a }
2601 auto str = "a";
2602 assert(parse!EnumType(str) == EnumType.a);
2605 @safe unittest
2607 import std.exception;
2609 enum EB : bool { a = true, b = false, c = a }
2610 enum EU { a, b, c }
2611 enum EI { a = -1, b = 0, c = 1 }
2612 enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
2613 enum EC : char { a = 'a', b = 'b', c = 'c' }
2614 enum ES : string { a = "aaa", b = "bbb", c = "ccc" }
2616 foreach (E; AliasSeq!(EB, EU, EI, EF, EC, ES))
2618 assert(to!E("a"c) == E.a);
2619 assert(to!E("b"w) == E.b);
2620 assert(to!E("c"d) == E.c);
2622 assertThrown!ConvException(to!E("d"));
2626 @safe pure unittest // bugzilla 4744
2628 enum A { member1, member11, member111 }
2629 assert(to!A("member1" ) == A.member1 );
2630 assert(to!A("member11" ) == A.member11 );
2631 assert(to!A("member111") == A.member111);
2632 auto s = "member1111";
2633 assert(parse!A(s) == A.member111 && s == "1");
2637 * Parses a character range to a floating point number.
2639 * Params:
2640 * Target = a floating point type
2641 * source = the lvalue of the range to _parse
2643 * Returns:
2644 * A floating point number of type `Target`
2646 * Throws:
2647 * A $(LREF ConvException) if `p` is empty, if no number could be
2648 * parsed, or if an overflow occurred.
2650 Target parse(Target, Source)(ref Source source)
2651 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
2652 isFloatingPoint!Target && !is(Target == enum))
2654 import std.ascii : isDigit, isAlpha, toLower, toUpper, isHexDigit;
2655 import std.exception : enforce;
2657 static if (isNarrowString!Source)
2659 import std.string : representation;
2660 auto p = source.representation;
2662 else
2664 alias p = source;
2667 static immutable real[14] negtab =
2668 [ 1e-4096L,1e-2048L,1e-1024L,1e-512L,1e-256L,1e-128L,1e-64L,1e-32L,
2669 1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L ];
2670 static immutable real[13] postab =
2671 [ 1e+4096L,1e+2048L,1e+1024L,1e+512L,1e+256L,1e+128L,1e+64L,1e+32L,
2672 1e+16L,1e+8L,1e+4L,1e+2L,1e+1L ];
2674 ConvException bailOut()(string msg = null, string fn = __FILE__, size_t ln = __LINE__)
2676 if (msg == null)
2677 msg = "Floating point conversion error";
2678 return new ConvException(text(msg, " for input \"", source, "\"."), fn, ln);
2682 enforce(!p.empty, bailOut());
2684 bool sign = false;
2685 switch (p.front)
2687 case '-':
2688 sign = true;
2689 p.popFront();
2690 enforce(!p.empty, bailOut());
2691 if (toLower(p.front) == 'i')
2692 goto case 'i';
2693 break;
2694 case '+':
2695 p.popFront();
2696 enforce(!p.empty, bailOut());
2697 break;
2698 case 'i': case 'I':
2699 // inf
2700 p.popFront();
2701 enforce(!p.empty && toUpper(p.front) == 'N',
2702 bailOut("error converting input to floating point"));
2703 p.popFront();
2704 enforce(!p.empty && toUpper(p.front) == 'F',
2705 bailOut("error converting input to floating point"));
2706 // skip past the last 'f'
2707 p.popFront();
2708 static if (isNarrowString!Source)
2709 source = cast(Source) p;
2710 return sign ? -Target.infinity : Target.infinity;
2711 default: {}
2714 bool isHex = false;
2715 bool startsWithZero = p.front == '0';
2716 if (startsWithZero)
2718 p.popFront();
2719 if (p.empty)
2721 static if (isNarrowString!Source)
2722 source = cast(Source) p;
2723 return sign ? -0.0 : 0.0;
2726 isHex = p.front == 'x' || p.front == 'X';
2727 if (isHex) p.popFront();
2729 else if (toLower(p.front) == 'n')
2731 // nan
2732 p.popFront();
2733 enforce(!p.empty && toUpper(p.front) == 'A',
2734 bailOut("error converting input to floating point"));
2735 p.popFront();
2736 enforce(!p.empty && toUpper(p.front) == 'N',
2737 bailOut("error converting input to floating point"));
2738 // skip past the last 'n'
2739 p.popFront();
2740 static if (isNarrowString!Source)
2741 source = cast(Source) p;
2742 return typeof(return).nan;
2746 * The following algorithm consists of 2 steps:
2747 * 1) parseDigits processes the textual input into msdec and possibly
2748 * lsdec/msscale variables, followed by the exponent parser which sets
2749 * exp below.
2750 * Hex: input is 0xaaaaa...p+000... where aaaa is the mantissa in hex
2751 * and 000 is the exponent in decimal format with base 2.
2752 * Decimal: input is 0.00333...p+000... where 0.0033 is the mantissa
2753 * in decimal and 000 is the exponent in decimal format with base 10.
2754 * 2) Convert msdec/lsdec and exp into native real format
2757 real ldval = 0.0;
2758 char dot = 0; /* if decimal point has been seen */
2759 int exp = 0;
2760 ulong msdec = 0, lsdec = 0;
2761 ulong msscale = 1;
2762 bool sawDigits;
2764 enum { hex, decimal }
2766 // sets msdec, lsdec/msscale, and sawDigits by parsing the mantissa digits
2767 void parseDigits(alias FloatFormat)()
2769 static if (FloatFormat == hex)
2771 enum uint base = 16;
2772 enum ulong msscaleMax = 0x1000_0000_0000_0000UL; // largest power of 16 a ulong holds
2773 enum ubyte expIter = 4; // iterate the base-2 exponent by 4 for every hex digit
2774 alias checkDigit = isHexDigit;
2776 * convert letter to binary representation: First clear bit
2777 * to convert lower space chars to upperspace, then -('A'-10)
2778 * converts letter A to 10, letter B to 11, ...
2780 alias convertDigit = (int x) => isAlpha(x) ? ((x & ~0x20) - ('A' - 10)) : x - '0';
2781 sawDigits = false;
2783 else static if (FloatFormat == decimal)
2785 enum uint base = 10;
2786 enum ulong msscaleMax = 10_000_000_000_000_000_000UL; // largest power of 10 a ulong holds
2787 enum ubyte expIter = 1; // iterate the base-10 exponent once for every decimal digit
2788 alias checkDigit = isDigit;
2789 alias convertDigit = (int x) => x - '0';
2790 // Used to enforce that any mantissa digits are present
2791 sawDigits = startsWithZero;
2793 else
2794 static assert(false, "Unrecognized floating-point format used.");
2796 while (!p.empty)
2798 int i = p.front;
2799 while (checkDigit(i))
2801 sawDigits = true; /* must have at least 1 digit */
2803 i = convertDigit(i);
2805 if (msdec < (ulong.max - base)/base)
2807 // For base 16: Y = ... + y3*16^3 + y2*16^2 + y1*16^1 + y0*16^0
2808 msdec = msdec * base + i;
2810 else if (msscale < msscaleMax)
2812 lsdec = lsdec * base + i;
2813 msscale *= base;
2815 else
2817 exp += expIter;
2819 exp -= dot;
2820 p.popFront();
2821 if (p.empty)
2822 break;
2823 i = p.front;
2824 if (i == '_')
2826 p.popFront();
2827 if (p.empty)
2828 break;
2829 i = p.front;
2832 if (i == '.' && !dot)
2834 p.popFront();
2835 dot += expIter;
2837 else
2838 break;
2841 // Have we seen any mantissa digits so far?
2842 enforce(sawDigits, bailOut("no digits seen"));
2843 static if (FloatFormat == hex)
2844 enforce(!p.empty && (p.front == 'p' || p.front == 'P'),
2845 bailOut("Floating point parsing: exponent is required"));
2848 if (isHex)
2849 parseDigits!hex;
2850 else
2851 parseDigits!decimal;
2853 if (isHex || (!p.empty && (p.front == 'e' || p.front == 'E')))
2855 char sexp = 0;
2856 int e = 0;
2858 p.popFront();
2859 enforce(!p.empty, new ConvException("Unexpected end of input"));
2860 switch (p.front)
2862 case '-': sexp++;
2863 goto case;
2864 case '+': p.popFront();
2865 break;
2866 default: {}
2868 sawDigits = false;
2869 while (!p.empty && isDigit(p.front))
2871 if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow
2873 e = e * 10 + p.front - '0';
2875 p.popFront();
2876 sawDigits = true;
2878 exp += (sexp) ? -e : e;
2879 enforce(sawDigits, new ConvException("No digits seen."));
2882 ldval = msdec;
2883 if (msscale != 1) /* if stuff was accumulated in lsdec */
2884 ldval = ldval * msscale + lsdec;
2885 if (isHex)
2887 import std.math : ldexp;
2889 // Exponent is power of 2, not power of 10
2890 ldval = ldexp(ldval,exp);
2892 else if (ldval)
2894 uint u = 0;
2895 int pow = 4096;
2897 while (exp > 0)
2899 while (exp >= pow)
2901 ldval *= postab[u];
2902 exp -= pow;
2904 pow >>= 1;
2905 u++;
2907 while (exp < 0)
2909 while (exp <= -pow)
2911 ldval *= negtab[u];
2912 enforce(ldval != 0, new ConvException("Range error"));
2913 exp += pow;
2915 pow >>= 1;
2916 u++;
2920 // if overflow occurred
2921 enforce(ldval != real.infinity, new ConvException("Range error"));
2923 static if (isNarrowString!Source)
2924 source = cast(Source) p;
2925 return sign ? -ldval : ldval;
2929 @safe unittest
2931 import std.math : approxEqual;
2932 auto str = "123.456";
2934 assert(parse!double(str).approxEqual(123.456));
2937 @safe unittest
2939 import std.exception;
2940 import std.math : isNaN, fabs;
2942 // Compare reals with given precision
2943 bool feq(in real rx, in real ry, in real precision = 0.000001L)
2945 if (rx == ry)
2946 return 1;
2948 if (isNaN(rx))
2949 return cast(bool) isNaN(ry);
2951 if (isNaN(ry))
2952 return 0;
2954 return cast(bool)(fabs(rx - ry) <= precision);
2957 // Make given typed literal
2958 F Literal(F)(F f)
2960 return f;
2963 foreach (Float; AliasSeq!(float, double, real))
2965 assert(to!Float("123") == Literal!Float(123));
2966 assert(to!Float("+123") == Literal!Float(+123));
2967 assert(to!Float("-123") == Literal!Float(-123));
2968 assert(to!Float("123e2") == Literal!Float(123e2));
2969 assert(to!Float("123e+2") == Literal!Float(123e+2));
2970 assert(to!Float("123e-2") == Literal!Float(123e-2));
2971 assert(to!Float("123.") == Literal!Float(123.0));
2972 assert(to!Float(".375") == Literal!Float(.375));
2974 assert(to!Float("1.23375E+2") == Literal!Float(1.23375E+2));
2976 assert(to!Float("0") is 0.0);
2977 assert(to!Float("-0") is -0.0);
2979 assert(isNaN(to!Float("nan")));
2981 assertThrown!ConvException(to!Float("\x00"));
2984 // min and max
2985 float f = to!float("1.17549e-38");
2986 assert(feq(cast(real) f, cast(real) 1.17549e-38));
2987 assert(feq(cast(real) f, cast(real) float.min_normal));
2988 f = to!float("3.40282e+38");
2989 assert(to!string(f) == to!string(3.40282e+38));
2991 // min and max
2992 double d = to!double("2.22508e-308");
2993 assert(feq(cast(real) d, cast(real) 2.22508e-308));
2994 assert(feq(cast(real) d, cast(real) double.min_normal));
2995 d = to!double("1.79769e+308");
2996 assert(to!string(d) == to!string(1.79769e+308));
2997 assert(to!string(d) == to!string(double.max));
2999 assert(to!string(to!real(to!string(real.max / 2L))) == to!string(real.max / 2L));
3001 // min and max
3002 real r = to!real(to!string(real.min_normal));
3003 version (NetBSD)
3005 // NetBSD notice
3006 // to!string returns 3.3621e-4932L. It is less than real.min_normal and it is subnormal value
3007 // Simple C code
3008 // long double rd = 3.3621e-4932L;
3009 // printf("%Le\n", rd);
3010 // has unexpected result: 1.681050e-4932
3012 // Bug report: http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=50937
3014 else
3016 assert(to!string(r) == to!string(real.min_normal));
3018 r = to!real(to!string(real.max));
3019 assert(to!string(r) == to!string(real.max));
3022 // Tests for the double implementation
3023 @system unittest
3025 // @system because strtod is not @safe.
3026 import std.math : floatTraits, RealFormat;
3028 static if (floatTraits!real.realFormat == RealFormat.ieeeDouble)
3030 import core.stdc.stdlib, std.exception, std.math;
3032 //Should be parsed exactly: 53 bit mantissa
3033 string s = "0x1A_BCDE_F012_3456p10";
3034 auto x = parse!real(s);
3035 assert(x == 0x1A_BCDE_F012_3456p10L);
3036 //1 bit is implicit
3037 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0xA_BCDE_F012_3456);
3038 assert(strtod("0x1ABCDEF0123456p10", null) == x);
3040 //Should be parsed exactly: 10 bit mantissa
3041 s = "0x3FFp10";
3042 x = parse!real(s);
3043 assert(x == 0x03FFp10);
3044 //1 bit is implicit
3045 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_F800_0000_0000);
3046 assert(strtod("0x3FFp10", null) == x);
3048 //60 bit mantissa, round up
3049 s = "0xFFF_FFFF_FFFF_FFFFp10";
3050 x = parse!real(s);
3051 assert(approxEqual(x, 0xFFF_FFFF_FFFF_FFFFp10));
3052 //1 bit is implicit
3053 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x0000_0000_0000_0000);
3054 assert(strtod("0xFFFFFFFFFFFFFFFp10", null) == x);
3056 //60 bit mantissa, round down
3057 s = "0xFFF_FFFF_FFFF_FF90p10";
3058 x = parse!real(s);
3059 assert(approxEqual(x, 0xFFF_FFFF_FFFF_FF90p10));
3060 //1 bit is implicit
3061 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_FFFF_FFFF_FFFF);
3062 assert(strtod("0xFFFFFFFFFFFFF90p10", null) == x);
3064 //61 bit mantissa, round up 2
3065 s = "0x1F0F_FFFF_FFFF_FFFFp10";
3066 x = parse!real(s);
3067 assert(approxEqual(x, 0x1F0F_FFFF_FFFF_FFFFp10));
3068 //1 bit is implicit
3069 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_1000_0000_0000);
3070 assert(strtod("0x1F0FFFFFFFFFFFFFp10", null) == x);
3072 //61 bit mantissa, round down 2
3073 s = "0x1F0F_FFFF_FFFF_FF10p10";
3074 x = parse!real(s);
3075 assert(approxEqual(x, 0x1F0F_FFFF_FFFF_FF10p10));
3076 //1 bit is implicit
3077 assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_0FFF_FFFF_FFFF);
3078 assert(strtod("0x1F0FFFFFFFFFFF10p10", null) == x);
3080 //Huge exponent
3081 s = "0x1F_FFFF_FFFF_FFFFp900";
3082 x = parse!real(s);
3083 assert(strtod("0x1FFFFFFFFFFFFFp900", null) == x);
3085 //exponent too big -> converror
3086 s = "";
3087 assertThrown!ConvException(x = parse!real(s));
3088 assert(strtod("0x1FFFFFFFFFFFFFp1024", null) == real.infinity);
3090 //-exponent too big -> 0
3091 s = "0x1FFFFFFFFFFFFFp-2000";
3092 x = parse!real(s);
3093 assert(x == 0);
3094 assert(strtod("0x1FFFFFFFFFFFFFp-2000", null) == x);
3098 @system unittest
3100 import core.stdc.errno;
3101 import core.stdc.stdlib;
3102 import std.math : floatTraits, RealFormat;
3104 errno = 0; // In case it was set by another unittest in a different module.
3105 struct longdouble
3107 static if (floatTraits!real.realFormat == RealFormat.ieeeQuadruple)
3109 ushort[8] value;
3111 else static if (floatTraits!real.realFormat == RealFormat.ieeeExtended ||
3112 floatTraits!real.realFormat == RealFormat.ieeeExtended53)
3114 ushort[5] value;
3116 else static if (floatTraits!real.realFormat == RealFormat.ieeeDouble)
3118 ushort[4] value;
3120 else
3121 static assert(false, "Not implemented");
3124 real ld;
3125 longdouble x;
3126 real ld1;
3127 longdouble x1;
3128 int i;
3130 static if (floatTraits!real.realFormat == RealFormat.ieeeQuadruple)
3131 // Our parser is currently limited to ieeeExtended precision
3132 enum s = "0x1.FFFFFFFFFFFFFFFEp-16382";
3133 else static if (floatTraits!real.realFormat == RealFormat.ieeeExtended)
3134 enum s = "0x1.FFFFFFFFFFFFFFFEp-16382";
3135 else static if (floatTraits!real.realFormat == RealFormat.ieeeExtended53)
3136 enum s = "0x1.FFFFFFFFFFFFFFFEp-16382";
3137 else static if (floatTraits!real.realFormat == RealFormat.ieeeDouble)
3138 enum s = "0x1.FFFFFFFFFFFFFFFEp-1000";
3139 else
3140 static assert(false, "Floating point format for real not supported");
3142 auto s2 = s.idup;
3143 ld = parse!real(s2);
3144 assert(s2.empty);
3145 x = *cast(longdouble *)&ld;
3147 static if (floatTraits!real.realFormat == RealFormat.ieeeExtended)
3149 version (CRuntime_Microsoft)
3150 ld1 = 0x1.FFFFFFFFFFFFFFFEp-16382L; // strtold currently mapped to strtod
3151 else
3152 ld1 = strtold(s.ptr, null);
3154 else static if (floatTraits!real.realFormat == RealFormat.ieeeExtended53)
3155 ld1 = 0x1.FFFFFFFFFFFFFFFEp-16382L; // strtold rounds to 53 bits.
3156 else
3157 ld1 = strtold(s.ptr, null);
3159 x1 = *cast(longdouble *)&ld1;
3160 assert(x1 == x && ld1 == ld);
3162 assert(!errno);
3164 s2 = "1.0e5";
3165 ld = parse!real(s2);
3166 assert(s2.empty);
3167 x = *cast(longdouble *)&ld;
3168 ld1 = strtold("1.0e5", null);
3169 x1 = *cast(longdouble *)&ld1;
3172 @safe pure unittest
3174 import std.exception;
3176 // Bugzilla 4959
3178 auto s = "0 ";
3179 auto x = parse!double(s);
3180 assert(s == " ");
3181 assert(x == 0.0);
3184 // Bugzilla 3369
3185 assert(to!float("inf") == float.infinity);
3186 assert(to!float("-inf") == -float.infinity);
3188 // Bugzilla 6160
3189 assert(6_5.536e3L == to!real("6_5.536e3")); // 2^16
3190 assert(0x1000_000_000_p10 == to!real("0x1000_000_000_p10")); // 7.03687e+13
3192 // Bugzilla 6258
3193 assertThrown!ConvException(to!real("-"));
3194 assertThrown!ConvException(to!real("in"));
3196 // Bugzilla 7055
3197 assertThrown!ConvException(to!float("INF2"));
3199 //extra stress testing
3200 auto ssOK = ["1.", "1.1.1", "1.e5", "2e1e", "2a", "2e1_1",
3201 "inf", "-inf", "infa", "-infa", "inf2e2", "-inf2e2"];
3202 auto ssKO = ["", " ", "2e", "2e+", "2e-", "2ee", "2e++1", "2e--1", "2e_1", "+inf"];
3203 foreach (s; ssOK)
3204 parse!double(s);
3205 foreach (s; ssKO)
3206 assertThrown!ConvException(parse!double(s));
3210 Parsing one character off a range returns the first element and calls `popFront`.
3212 Params:
3213 Target = the type to convert to
3214 s = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3216 Returns:
3217 A character of type `Target`
3219 Throws:
3220 A $(LREF ConvException) if the range is empty.
3222 Target parse(Target, Source)(ref Source s)
3223 if (isSomeString!Source && !is(Source == enum) &&
3224 staticIndexOf!(Unqual!Target, dchar, Unqual!(ElementEncodingType!Source)) >= 0)
3226 if (s.empty)
3227 throw convError!(Source, Target)(s);
3228 static if (is(Unqual!Target == dchar))
3230 Target result = s.front;
3231 s.popFront();
3232 return result;
3234 else
3236 // Special case: okay so parse a Char off a Char[]
3237 Target result = s[0];
3238 s = s[1 .. $];
3239 return result;
3243 @safe pure unittest
3245 foreach (Str; AliasSeq!(string, wstring, dstring))
3247 foreach (Char; AliasSeq!(char, wchar, dchar))
3249 static if (is(Unqual!Char == dchar) ||
3250 Char.sizeof == ElementEncodingType!Str.sizeof)
3252 Str s = "aaa";
3253 assert(parse!Char(s) == 'a');
3254 assert(s == "aa");
3260 /// ditto
3261 Target parse(Target, Source)(ref Source s)
3262 if (!isSomeString!Source && isInputRange!Source && isSomeChar!(ElementType!Source) &&
3263 isSomeChar!Target && Target.sizeof >= ElementType!Source.sizeof && !is(Target == enum))
3265 if (s.empty)
3266 throw convError!(Source, Target)(s);
3267 Target result = s.front;
3268 s.popFront();
3269 return result;
3273 @safe pure unittest
3275 auto s = "Hello, World!";
3276 char first = parse!char(s);
3277 assert(first == 'H');
3278 assert(s == "ello, World!");
3283 Tests for to!bool and parse!bool
3285 @safe pure unittest
3287 import std.exception;
3289 assert(to!bool("TruE") == true);
3290 assert(to!bool("faLse"d) == false);
3291 assertThrown!ConvException(to!bool("maybe"));
3293 auto t = "TrueType";
3294 assert(parse!bool(t) == true);
3295 assert(t == "Type");
3297 auto f = "False killer whale"d;
3298 assert(parse!bool(f) == false);
3299 assert(f == " killer whale"d);
3301 auto m = "maybe";
3302 assertThrown!ConvException(parse!bool(m));
3303 assert(m == "maybe"); // m shouldn't change on failure
3305 auto s = "true";
3306 auto b = parse!(const(bool))(s);
3307 assert(b == true);
3311 Parsing a character range to `typeof(null)` returns `null` if the range
3312 spells `"null"`. This function is case insensitive.
3314 Params:
3315 Target = the type to convert to
3316 s = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3318 Returns:
3319 `null`
3321 Throws:
3322 A $(LREF ConvException) if the range doesn't represent `null`.
3324 Target parse(Target, Source)(ref Source s)
3325 if (isInputRange!Source &&
3326 isSomeChar!(ElementType!Source) &&
3327 is(Unqual!Target == typeof(null)))
3329 import std.ascii : toLower;
3330 foreach (c; "null")
3332 if (s.empty || toLower(s.front) != c)
3333 throw parseError("null should be case-insensitive 'null'");
3334 s.popFront();
3336 return null;
3340 @safe pure unittest
3342 import std.exception : assertThrown;
3344 alias NullType = typeof(null);
3345 auto s1 = "null";
3346 assert(parse!NullType(s1) is null);
3347 assert(s1 == "");
3349 auto s2 = "NUll"d;
3350 assert(parse!NullType(s2) is null);
3351 assert(s2 == "");
3353 auto m = "maybe";
3354 assertThrown!ConvException(parse!NullType(m));
3355 assert(m == "maybe"); // m shouldn't change on failure
3357 auto s = "NULL";
3358 assert(parse!(const NullType)(s) is null);
3361 //Used internally by parse Array/AA, to remove ascii whites
3362 package void skipWS(R)(ref R r)
3364 import std.ascii : isWhite;
3365 static if (isSomeString!R)
3367 //Implementation inspired from stripLeft.
3368 foreach (i, c; r)
3370 if (!isWhite(c))
3372 r = r[i .. $];
3373 return;
3376 r = r[0 .. 0]; //Empty string with correct type.
3377 return;
3379 else
3381 for (; !r.empty && isWhite(r.front); r.popFront())
3387 * Parses an array from a string given the left bracket (default $(D
3388 * '[')), right bracket (default $(D ']')), and element separator (by
3389 * default $(D ',')). A trailing separator is allowed.
3391 * Params:
3392 * s = The string to parse
3393 * lbracket = the character that starts the array
3394 * rbracket = the character that ends the array
3395 * comma = the character that separates the elements of the array
3397 * Returns:
3398 * An array of type `Target`
3400 Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
3401 if (isSomeString!Source && !is(Source == enum) &&
3402 isDynamicArray!Target && !is(Target == enum))
3404 import std.array : appender;
3406 auto result = appender!Target();
3408 parseCheck!s(lbracket);
3409 skipWS(s);
3410 if (s.empty)
3411 throw convError!(Source, Target)(s);
3412 if (s.front == rbracket)
3414 s.popFront();
3415 return result.data;
3417 for (;; s.popFront(), skipWS(s))
3419 if (!s.empty && s.front == rbracket)
3420 break;
3421 result ~= parseElement!(ElementType!Target)(s);
3422 skipWS(s);
3423 if (s.empty)
3424 throw convError!(Source, Target)(s);
3425 if (s.front != comma)
3426 break;
3428 parseCheck!s(rbracket);
3430 return result.data;
3434 @safe pure unittest
3436 auto s1 = `[['h', 'e', 'l', 'l', 'o'], "world"]`;
3437 auto a1 = parse!(string[])(s1);
3438 assert(a1 == ["hello", "world"]);
3440 auto s2 = `["aaa", "bbb", "ccc"]`;
3441 auto a2 = parse!(string[])(s2);
3442 assert(a2 == ["aaa", "bbb", "ccc"]);
3445 @safe unittest // Bugzilla 9615
3447 string s0 = "[1,2, ]";
3448 string s1 = "[1,2, \t\v\r\n]";
3449 string s2 = "[1,2]";
3450 assert(s0.parse!(int[]) == [1,2]);
3451 assert(s1.parse!(int[]) == [1,2]);
3452 assert(s2.parse!(int[]) == [1,2]);
3454 string s3 = `["a","b",]`;
3455 string s4 = `["a","b"]`;
3456 assert(s3.parse!(string[]) == ["a","b"]);
3457 assert(s4.parse!(string[]) == ["a","b"]);
3459 import std.exception : assertThrown;
3460 string s5 = "[,]";
3461 string s6 = "[, \t,]";
3462 assertThrown!ConvException(parse!(string[])(s5));
3463 assertThrown!ConvException(parse!(int[])(s6));
3466 @safe unittest
3468 int[] a = [1, 2, 3, 4, 5];
3469 auto s = to!string(a);
3470 assert(to!(int[])(s) == a);
3473 @safe unittest
3475 int[][] a = [ [1, 2] , [3], [4, 5] ];
3476 auto s = to!string(a);
3477 assert(to!(int[][])(s) == a);
3480 @safe unittest
3482 int[][][] ia = [ [[1,2],[3,4],[5]] , [[6],[],[7,8,9]] , [[]] ];
3484 char[] s = to!(char[])(ia);
3485 int[][][] ia2;
3487 ia2 = to!(typeof(ia2))(s);
3488 assert( ia == ia2);
3491 @safe pure unittest
3493 import std.exception;
3495 //Check proper failure
3496 auto s = "[ 1 , 2 , 3 ]";
3497 foreach (i ; 0 .. s.length-1)
3499 auto ss = s[0 .. i];
3500 assertThrown!ConvException(parse!(int[])(ss));
3502 int[] arr = parse!(int[])(s);
3505 @safe pure unittest
3507 //Checks parsing of strings with escaped characters
3508 string s1 = `[
3509 "Contains a\0null!",
3510 "tab\there",
3511 "line\nbreak",
3512 "backslash \\ slash / question \?",
3513 "number \x35 five",
3514 "unicode \u65E5 sun",
3515 "very long \U000065E5 sun"
3518 //Note: escaped characters purposefully replaced and isolated to guarantee
3519 //there are no typos in the escape syntax
3520 string[] s2 = [
3521 "Contains a" ~ '\0' ~ "null!",
3522 "tab" ~ '\t' ~ "here",
3523 "line" ~ '\n' ~ "break",
3524 "backslash " ~ '\\' ~ " slash / question ?",
3525 "number 5 five",
3526 "unicode 日 sun",
3527 "very long 日 sun"
3529 assert(s2 == parse!(string[])(s1));
3530 assert(s1.empty);
3533 /// ditto
3534 Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
3535 if (isExactSomeString!Source &&
3536 isStaticArray!Target && !is(Target == enum))
3538 static if (hasIndirections!Target)
3539 Target result = Target.init[0].init;
3540 else
3541 Target result = void;
3543 parseCheck!s(lbracket);
3544 skipWS(s);
3545 if (s.empty)
3546 throw convError!(Source, Target)(s);
3547 if (s.front == rbracket)
3549 static if (result.length != 0)
3550 goto Lmanyerr;
3551 else
3553 s.popFront();
3554 return result;
3557 for (size_t i = 0; ; s.popFront(), skipWS(s))
3559 if (i == result.length)
3560 goto Lmanyerr;
3561 result[i++] = parseElement!(ElementType!Target)(s);
3562 skipWS(s);
3563 if (s.empty)
3564 throw convError!(Source, Target)(s);
3565 if (s.front != comma)
3567 if (i != result.length)
3568 goto Lfewerr;
3569 break;
3572 parseCheck!s(rbracket);
3574 return result;
3576 Lmanyerr:
3577 throw parseError(text("Too many elements in input, ", result.length, " elements expected."));
3579 Lfewerr:
3580 throw parseError(text("Too few elements in input, ", result.length, " elements expected."));
3583 @safe pure unittest
3585 import std.exception;
3587 auto s1 = "[1,2,3,4]";
3588 auto sa1 = parse!(int[4])(s1);
3589 assert(sa1 == [1,2,3,4]);
3591 auto s2 = "[[1],[2,3],[4]]";
3592 auto sa2 = parse!(int[][3])(s2);
3593 assert(sa2 == [[1],[2,3],[4]]);
3595 auto s3 = "[1,2,3]";
3596 assertThrown!ConvException(parse!(int[4])(s3));
3598 auto s4 = "[1,2,3,4,5]";
3599 assertThrown!ConvException(parse!(int[4])(s4));
3603 * Parses an associative array from a string given the left bracket (default $(D
3604 * '[')), right bracket (default $(D ']')), key-value separator (default $(D
3605 * ':')), and element seprator (by default $(D ',')).
3607 * Params:
3608 * s = the string to parse
3609 * lbracket = the character that starts the associative array
3610 * rbracket = the character that ends the associative array
3611 * keyval = the character that associates the key with the value
3612 * comma = the character that separates the elements of the associative array
3614 * Returns:
3615 * An associative array of type `Target`
3617 Target parse(Target, Source)(ref Source s, dchar lbracket = '[',
3618 dchar rbracket = ']', dchar keyval = ':', dchar comma = ',')
3619 if (isSomeString!Source && !is(Source == enum) &&
3620 isAssociativeArray!Target && !is(Target == enum))
3622 alias KeyType = typeof(Target.init.keys[0]);
3623 alias ValType = typeof(Target.init.values[0]);
3625 Target result;
3627 parseCheck!s(lbracket);
3628 skipWS(s);
3629 if (s.empty)
3630 throw convError!(Source, Target)(s);
3631 if (s.front == rbracket)
3633 s.popFront();
3634 return result;
3636 for (;; s.popFront(), skipWS(s))
3638 auto key = parseElement!KeyType(s);
3639 skipWS(s);
3640 parseCheck!s(keyval);
3641 skipWS(s);
3642 auto val = parseElement!ValType(s);
3643 skipWS(s);
3644 result[key] = val;
3645 if (s.empty)
3646 throw convError!(Source, Target)(s);
3647 if (s.front != comma)
3648 break;
3650 parseCheck!s(rbracket);
3652 return result;
3656 @safe pure unittest
3658 auto s1 = "[1:10, 2:20, 3:30]";
3659 auto aa1 = parse!(int[int])(s1);
3660 assert(aa1 == [1:10, 2:20, 3:30]);
3662 auto s2 = `["aaa":10, "bbb":20, "ccc":30]`;
3663 auto aa2 = parse!(int[string])(s2);
3664 assert(aa2 == ["aaa":10, "bbb":20, "ccc":30]);
3666 auto s3 = `["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]`;
3667 auto aa3 = parse!(int[][string])(s3);
3668 assert(aa3 == ["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]);
3671 @safe pure unittest
3673 import std.exception;
3675 //Check proper failure
3676 auto s = "[1:10, 2:20, 3:30]";
3677 foreach (i ; 0 .. s.length-1)
3679 auto ss = s[0 .. i];
3680 assertThrown!ConvException(parse!(int[int])(ss));
3682 int[int] aa = parse!(int[int])(s);
3685 private dchar parseEscape(Source)(ref Source s)
3686 if (isInputRange!Source && isSomeChar!(ElementType!Source))
3688 parseCheck!s('\\');
3689 if (s.empty)
3690 throw parseError("Unterminated escape sequence");
3692 dchar getHexDigit()(ref Source s_ = s) // workaround
3694 import std.ascii : isAlpha, isHexDigit;
3695 if (s_.empty)
3696 throw parseError("Unterminated escape sequence");
3697 s_.popFront();
3698 if (s_.empty)
3699 throw parseError("Unterminated escape sequence");
3700 dchar c = s_.front;
3701 if (!isHexDigit(c))
3702 throw parseError("Hex digit is missing");
3703 return isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0';
3706 dchar result;
3708 switch (s.front)
3710 case '"': result = '\"'; break;
3711 case '\'': result = '\''; break;
3712 case '0': result = '\0'; break;
3713 case '?': result = '\?'; break;
3714 case '\\': result = '\\'; break;
3715 case 'a': result = '\a'; break;
3716 case 'b': result = '\b'; break;
3717 case 'f': result = '\f'; break;
3718 case 'n': result = '\n'; break;
3719 case 'r': result = '\r'; break;
3720 case 't': result = '\t'; break;
3721 case 'v': result = '\v'; break;
3722 case 'x':
3723 result = getHexDigit() << 4;
3724 result |= getHexDigit();
3725 break;
3726 case 'u':
3727 result = getHexDigit() << 12;
3728 result |= getHexDigit() << 8;
3729 result |= getHexDigit() << 4;
3730 result |= getHexDigit();
3731 break;
3732 case 'U':
3733 result = getHexDigit() << 28;
3734 result |= getHexDigit() << 24;
3735 result |= getHexDigit() << 20;
3736 result |= getHexDigit() << 16;
3737 result |= getHexDigit() << 12;
3738 result |= getHexDigit() << 8;
3739 result |= getHexDigit() << 4;
3740 result |= getHexDigit();
3741 break;
3742 default:
3743 throw parseError("Unknown escape character " ~ to!string(s.front));
3745 if (s.empty)
3746 throw parseError("Unterminated escape sequence");
3748 s.popFront();
3750 return result;
3753 @safe pure unittest
3755 string[] s1 = [
3756 `\"`, `\'`, `\?`, `\\`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v`, //Normal escapes
3757 //`\141`, //@@@9621@@@ Octal escapes.
3758 `\x61`,
3759 `\u65E5`, `\U00012456`
3760 //`\&amp;`, `\&quot;`, //@@@9621@@@ Named Character Entities.
3763 const(dchar)[] s2 = [
3764 '\"', '\'', '\?', '\\', '\a', '\b', '\f', '\n', '\r', '\t', '\v', //Normal escapes
3765 //'\141', //@@@9621@@@ Octal escapes.
3766 '\x61',
3767 '\u65E5', '\U00012456'
3768 //'\&amp;', '\&quot;', //@@@9621@@@ Named Character Entities.
3771 foreach (i ; 0 .. s1.length)
3773 assert(s2[i] == parseEscape(s1[i]));
3774 assert(s1[i].empty);
3778 @safe pure unittest
3780 import std.exception;
3782 string[] ss = [
3783 `hello!`, //Not an escape
3784 `\`, //Premature termination
3785 `\/`, //Not an escape
3786 `\gggg`, //Not an escape
3787 `\xzz`, //Not an hex
3788 `\x0`, //Premature hex end
3789 `\XB9`, //Not legal hex syntax
3790 `\u!!`, //Not a unicode hex
3791 `\777`, //Octal is larger than a byte //Note: Throws, but simply because octals are unsupported
3792 `\u123`, //Premature hex end
3793 `\U123123` //Premature hex end
3795 foreach (s ; ss)
3796 assertThrown!ConvException(parseEscape(s));
3799 // Undocumented
3800 Target parseElement(Target, Source)(ref Source s)
3801 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
3802 isExactSomeString!Target)
3804 import std.array : appender;
3805 auto result = appender!Target();
3807 // parse array of chars
3808 if (s.empty)
3809 throw convError!(Source, Target)(s);
3810 if (s.front == '[')
3811 return parse!Target(s);
3813 parseCheck!s('\"');
3814 if (s.empty)
3815 throw convError!(Source, Target)(s);
3816 if (s.front == '\"')
3818 s.popFront();
3819 return result.data;
3821 while (true)
3823 if (s.empty)
3824 throw parseError("Unterminated quoted string");
3825 switch (s.front)
3827 case '\"':
3828 s.popFront();
3829 return result.data;
3830 case '\\':
3831 result.put(parseEscape(s));
3832 break;
3833 default:
3834 result.put(s.front);
3835 s.popFront();
3836 break;
3839 assert(0);
3842 // ditto
3843 Target parseElement(Target, Source)(ref Source s)
3844 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
3845 isSomeChar!Target && !is(Target == enum))
3847 Target c;
3849 parseCheck!s('\'');
3850 if (s.empty)
3851 throw convError!(Source, Target)(s);
3852 if (s.front != '\\')
3854 c = s.front;
3855 s.popFront();
3857 else
3858 c = parseEscape(s);
3859 parseCheck!s('\'');
3861 return c;
3864 // ditto
3865 Target parseElement(Target, Source)(ref Source s)
3866 if (isInputRange!Source && isSomeChar!(ElementType!Source) &&
3867 !isSomeString!Target && !isSomeChar!Target)
3869 return parse!Target(s);
3873 /***************************************************************
3874 * Convenience functions for converting one or more arguments
3875 * of any type into _text (the three character widths).
3877 string text(T...)(T args)
3878 if (T.length > 0) { return textImpl!string(args); }
3880 ///ditto
3881 wstring wtext(T...)(T args)
3882 if (T.length > 0) { return textImpl!wstring(args); }
3884 ///ditto
3885 dstring dtext(T...)(T args)
3886 if (T.length > 0) { return textImpl!dstring(args); }
3889 @safe unittest
3891 assert( text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"c);
3892 assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w);
3893 assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d);
3896 @safe unittest
3898 char c = 'h';
3899 wchar w = '你';
3900 dchar d = 'እ';
3902 assert( text(c, "ello", ' ', w, "好 ", d, "ው ሰላም ነው") == "hello 你好 እው ሰላም ነው"c);
3903 assert(wtext(c, "ello", ' ', w, "好 ", d, "ው ሰላም ነው") == "hello 你好 እው ሰላም ነው"w);
3904 assert(dtext(c, "ello", ' ', w, "好 ", d, "ው ሰላም ነው") == "hello 你好 እው ሰላም ነው"d);
3906 string cs = "今日は";
3907 wstring ws = "여보세요";
3908 dstring ds = "Здравствуйте";
3910 assert( text(cs, ' ', ws, " ", ds) == "今日は 여보세요 Здравствуйте"c);
3911 assert(wtext(cs, ' ', ws, " ", ds) == "今日は 여보세요 Здравствуйте"w);
3912 assert(dtext(cs, ' ', ws, " ", ds) == "今日は 여보세요 Здравствуйте"d);
3915 private S textImpl(S, U...)(U args)
3917 static if (U.length == 0)
3919 return null;
3921 else static if (U.length == 1)
3923 return to!S(args[0]);
3925 else
3927 import std.array : appender;
3929 auto app = appender!S();
3931 foreach (arg; args)
3932 app.put(to!S(arg));
3933 return app.data;
3938 /***************************************************************
3939 The $(D octal) facility provides a means to declare a number in base 8.
3940 Using $(D octal!177) or $(D octal!"177") for 127 represented in octal
3941 (same as 0177 in C).
3943 The rules for strings are the usual for literals: If it can fit in an
3944 $(D int), it is an $(D int). Otherwise, it is a $(D long). But, if the
3945 user specifically asks for a $(D long) with the $(D L) suffix, always
3946 give the $(D long). Give an unsigned iff it is asked for with the $(D
3947 U) or $(D u) suffix. _Octals created from integers preserve the type
3948 of the passed-in integral.
3950 See_Also:
3951 $(LREF parse) for parsing octal strings at runtime.
3953 template octal(string num)
3954 if (isOctalLiteral(num))
3956 static if ((octalFitsInInt!num && !literalIsLong!num) && !literalIsUnsigned!num)
3957 enum octal = octal!int(num);
3958 else static if ((!octalFitsInInt!num || literalIsLong!num) && !literalIsUnsigned!num)
3959 enum octal = octal!long(num);
3960 else static if ((octalFitsInInt!num && !literalIsLong!num) && literalIsUnsigned!num)
3961 enum octal = octal!uint(num);
3962 else static if ((!octalFitsInInt!(num) || literalIsLong!(num)) && literalIsUnsigned!(num))
3963 enum octal = octal!ulong(num);
3964 else
3965 static assert(false);
3968 /// Ditto
3969 template octal(alias decimalInteger)
3970 if (is(typeof(decimalInteger)) && isIntegral!(typeof(decimalInteger)))
3972 enum octal = octal!(typeof(decimalInteger))(to!string(decimalInteger));
3976 @safe unittest
3978 // same as 0177
3979 auto x = octal!177;
3980 // octal is a compile-time device
3981 enum y = octal!160;
3982 // Create an unsigned octal
3983 auto z = octal!"1_000_000u";
3987 Takes a string, num, which is an octal literal, and returns its
3988 value, in the type T specified.
3990 private T octal(T)(const string num)
3992 assert(isOctalLiteral(num));
3994 T value = 0;
3996 foreach (const char s; num)
3998 if (s < '0' || s > '7') // we only care about digits; skip the rest
3999 // safe to skip - this is checked out in the assert so these
4000 // are just suffixes
4001 continue;
4003 value *= 8;
4004 value += s - '0';
4007 return value;
4010 @safe unittest
4012 int a = octal!int("10");
4013 assert(a == 8);
4017 Take a look at int.max and int.max+1 in octal and the logic for this
4018 function follows directly.
4020 private template octalFitsInInt(string octalNum)
4022 // note it is important to strip the literal of all
4023 // non-numbers. kill the suffix and underscores lest they mess up
4024 // the number of digits here that we depend on.
4025 enum bool octalFitsInInt = strippedOctalLiteral(octalNum).length < 11 ||
4026 strippedOctalLiteral(octalNum).length == 11 &&
4027 strippedOctalLiteral(octalNum)[0] == '1';
4030 private string strippedOctalLiteral(string original)
4032 string stripped = "";
4033 foreach (c; original)
4034 if (c >= '0' && c <= '7')
4035 stripped ~= c;
4036 return stripped;
4039 private template literalIsLong(string num)
4041 static if (num.length > 1)
4042 // can be xxL or xxLu according to spec
4043 enum literalIsLong = (num[$-1] == 'L' || num[$-2] == 'L');
4044 else
4045 enum literalIsLong = false;
4048 private template literalIsUnsigned(string num)
4050 static if (num.length > 1)
4051 // can be xxU or xxUL according to spec
4052 enum literalIsUnsigned = (num[$-1] == 'u' || num[$-2] == 'u')
4053 // both cases are allowed too
4054 || (num[$-1] == 'U' || num[$-2] == 'U');
4055 else
4056 enum literalIsUnsigned = false;
4060 Returns if the given string is a correctly formatted octal literal.
4062 The format is specified in spec/lex.html. The leading zero is allowed, but
4063 not required.
4065 @safe pure nothrow @nogc
4066 private bool isOctalLiteral(const string num)
4068 if (num.length == 0)
4069 return false;
4071 // Must start with a number. To avoid confusion, literals that
4072 // start with a '0' are not allowed
4073 if (num[0] == '0' && num.length > 1)
4074 return false;
4075 if (num[0] < '0' || num[0] > '7')
4076 return false;
4078 foreach (i, c; num)
4080 if ((c < '0' || c > '7') && c != '_') // not a legal character
4082 if (i < num.length - 2)
4083 return false;
4084 else // gotta check for those suffixes
4086 if (c != 'U' && c != 'u' && c != 'L')
4087 return false;
4088 if (i != num.length - 1)
4090 // if we're not the last one, the next one must
4091 // also be a suffix to be valid
4092 char c2 = num[$-1];
4093 if (c2 != 'U' && c2 != 'u' && c2 != 'L')
4094 return false; // spam at the end of the string
4095 if (c2 == c)
4096 return false; // repeats are disallowed
4102 return true;
4105 @safe unittest
4107 // ensure that you get the right types, even with embedded underscores
4108 auto w = octal!"100_000_000_000";
4109 static assert(!is(typeof(w) == int));
4110 auto w2 = octal!"1_000_000_000";
4111 static assert(is(typeof(w2) == int));
4113 static assert(octal!"45" == 37);
4114 static assert(octal!"0" == 0);
4115 static assert(octal!"7" == 7);
4116 static assert(octal!"10" == 8);
4117 static assert(octal!"666" == 438);
4119 static assert(octal!45 == 37);
4120 static assert(octal!0 == 0);
4121 static assert(octal!7 == 7);
4122 static assert(octal!10 == 8);
4123 static assert(octal!666 == 438);
4125 static assert(octal!"66_6" == 438);
4127 static assert(octal!2520046213 == 356535435);
4128 static assert(octal!"2520046213" == 356535435);
4130 static assert(octal!17777777777 == int.max);
4132 static assert(!__traits(compiles, octal!823));
4134 static assert(!__traits(compiles, octal!"823"));
4136 static assert(!__traits(compiles, octal!"_823"));
4137 static assert(!__traits(compiles, octal!"spam"));
4138 static assert(!__traits(compiles, octal!"77%"));
4140 static assert(is(typeof(octal!"17777777777") == int));
4141 static assert(octal!"17777777777" == int.max);
4143 static assert(is(typeof(octal!"20000000000U") == ulong)); // Shouldn't this be uint?
4144 static assert(octal!"20000000000" == uint(int.max) + 1);
4146 static assert(is(typeof(octal!"777777777777777777777") == long));
4147 static assert(octal!"777777777777777777777" == long.max);
4149 static assert(is(typeof(octal!"1000000000000000000000U") == ulong));
4150 static assert(octal!"1000000000000000000000" == ulong(long.max) + 1);
4152 int a;
4153 long b;
4155 // biggest value that should fit in an it
4156 a = octal!"17777777777";
4157 assert(a == int.max);
4158 // should not fit in the int
4159 static assert(!__traits(compiles, a = octal!"20000000000"));
4160 // ... but should fit in a long
4161 b = octal!"20000000000";
4162 assert(b == 1L + int.max);
4164 b = octal!"1L";
4165 assert(b == 1);
4166 b = octal!1L;
4167 assert(b == 1);
4171 emplaceRef is a package function for phobos internal use. It works like
4172 emplace, but takes its argument by ref (as opposed to "by pointer").
4174 This makes it easier to use, easier to be safe, and faster in a non-inline
4175 build.
4177 Furthermore, emplaceRef optionally takes a type paremeter, which specifies
4178 the type we want to build. This helps to build qualified objects on mutable
4179 buffer, without breaking the type system with unsafe casts.
4181 package void emplaceRef(T, UT, Args...)(ref UT chunk, auto ref Args args)
4183 static if (args.length == 0)
4185 static assert(is(typeof({static T i;})),
4186 convFormat("Cannot emplace a %1$s because %1$s.this() is annotated with @disable.", T.stringof));
4187 static if (is(T == class)) static assert(!isAbstractClass!T,
4188 T.stringof ~ " is abstract and it can't be emplaced");
4189 emplaceInitializer(chunk);
4191 else static if (
4192 !is(T == struct) && Args.length == 1 /* primitives, enums, arrays */
4194 Args.length == 1 && is(typeof({T t = args[0];})) /* conversions */
4196 is(typeof(T(args))) /* general constructors */)
4198 static struct S
4200 T payload;
4201 this(ref Args x)
4203 static if (Args.length == 1)
4204 static if (is(typeof(payload = x[0])))
4205 payload = x[0];
4206 else
4207 payload = T(x[0]);
4208 else
4209 payload = T(x);
4212 if (__ctfe)
4214 static if (is(typeof(chunk = T(args))))
4215 chunk = T(args);
4216 else static if (args.length == 1 && is(typeof(chunk = args[0])))
4217 chunk = args[0];
4218 else assert(0, "CTFE emplace doesn't support "
4219 ~ T.stringof ~ " from " ~ Args.stringof);
4221 else
4223 S* p = () @trusted { return cast(S*) &chunk; }();
4224 emplaceInitializer(*p);
4225 p.__ctor(args);
4228 else static if (is(typeof(chunk.__ctor(args))))
4230 // This catches the rare case of local types that keep a frame pointer
4231 emplaceInitializer(chunk);
4232 chunk.__ctor(args);
4234 else
4236 //We can't emplace. Try to diagnose a disabled postblit.
4237 static assert(!(Args.length == 1 && is(Args[0] : T)),
4238 convFormat("Cannot emplace a %1$s because %1$s.this(this) is annotated with @disable.", T.stringof));
4240 //We can't emplace.
4241 static assert(false,
4242 convFormat("%s cannot be emplaced from %s.", T.stringof, Args[].stringof));
4245 // ditto
4246 package void emplaceRef(UT, Args...)(ref UT chunk, auto ref Args args)
4247 if (is(UT == Unqual!UT))
4249 emplaceRef!(UT, UT)(chunk, args);
4252 //emplace helper functions
4253 private void emplaceInitializer(T)(ref T chunk) @trusted pure nothrow
4255 static if (!hasElaborateAssign!T && isAssignable!T)
4256 chunk = T.init;
4257 else
4259 import core.stdc.string : memcpy;
4260 static immutable T init = T.init;
4261 memcpy(&chunk, &init, T.sizeof);
4265 // emplace
4267 Given a pointer $(D chunk) to uninitialized memory (but already typed
4268 as $(D T)), constructs an object of non-$(D class) type $(D T) at that
4269 address. If `T` is a class, initializes the class reference to null.
4271 Returns: A pointer to the newly constructed object (which is the same
4272 as $(D chunk)).
4274 T* emplace(T)(T* chunk) @safe pure nothrow
4276 emplaceRef!T(*chunk);
4277 return chunk;
4281 @system unittest
4283 static struct S
4285 int i = 42;
4287 S[2] s2 = void;
4288 emplace(&s2);
4289 assert(s2[0].i == 42 && s2[1].i == 42);
4293 @system unittest
4295 interface I {}
4296 class K : I {}
4298 K k = void;
4299 emplace(&k);
4300 assert(k is null);
4302 I i = void;
4303 emplace(&i);
4304 assert(i is null);
4308 Given a pointer $(D chunk) to uninitialized memory (but already typed
4309 as a non-class type $(D T)), constructs an object of type $(D T) at
4310 that address from arguments $(D args). If `T` is a class, initializes
4311 the class reference to `args[0]`.
4313 This function can be $(D @trusted) if the corresponding constructor of
4314 $(D T) is $(D @safe).
4316 Returns: A pointer to the newly constructed object (which is the same
4317 as $(D chunk)).
4319 T* emplace(T, Args...)(T* chunk, auto ref Args args)
4320 if (is(T == struct) || Args.length == 1)
4322 emplaceRef!T(*chunk, args);
4323 return chunk;
4327 @system unittest
4329 int a;
4330 int b = 42;
4331 assert(*emplace!int(&a, b) == 42);
4334 @system unittest
4336 shared int i;
4337 emplace(&i, 42);
4338 assert(i == 42);
4341 private void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment, string typeName) @nogc pure nothrow
4343 assert(chunk.length >= typeSize, "emplace: Chunk size too small.");
4344 assert((cast(size_t) chunk.ptr) % typeAlignment == 0, "emplace: Chunk is not aligned.");
4348 Given a raw memory area $(D chunk), constructs an object of $(D class)
4349 type $(D T) at that address. The constructor is passed the arguments
4350 $(D Args).
4352 If `T` is an inner class whose `outer` field can be used to access an instance
4353 of the enclosing class, then `Args` must not be empty, and the first member of it
4354 must be a valid initializer for that `outer` field. Correct initialization of
4355 this field is essential to access members of the outer class inside `T` methods.
4357 Preconditions:
4358 $(D chunk) must be at least as large as $(D T) needs
4359 and should have an alignment multiple of $(D T)'s alignment. (The size
4360 of a $(D class) instance is obtained by using $(D
4361 __traits(classInstanceSize, T))).
4363 Note:
4364 This function can be $(D @trusted) if the corresponding constructor of
4365 $(D T) is $(D @safe).
4367 Returns: The newly constructed object.
4369 T emplace(T, Args...)(void[] chunk, auto ref Args args)
4370 if (is(T == class))
4372 static assert(!isAbstractClass!T, T.stringof ~
4373 " is abstract and it can't be emplaced");
4375 enum classSize = __traits(classInstanceSize, T);
4376 testEmplaceChunk(chunk, classSize, classInstanceAlignment!T, T.stringof);
4377 auto result = cast(T) chunk.ptr;
4379 // Initialize the object in its pre-ctor state
4380 chunk[0 .. classSize] = typeid(T).initializer[];
4382 static if (isInnerClass!T)
4384 static assert(Args.length > 0,
4385 "Initializing an inner class requires a pointer to the outer class");
4386 static assert(is(Args[0] : typeof(T.outer)),
4387 "The first argument must be a pointer to the outer class");
4389 result.outer = args[0];
4390 alias args1 = args[1..$];
4392 else alias args1 = args;
4394 // Call the ctor if any
4395 static if (is(typeof(result.__ctor(args1))))
4397 // T defines a genuine constructor accepting args
4398 // Go the classic route: write .init first, then call ctor
4399 result.__ctor(args1);
4401 else
4403 static assert(args1.length == 0 && !is(typeof(&T.__ctor)),
4404 "Don't know how to initialize an object of type "
4405 ~ T.stringof ~ " with arguments " ~ typeof(args1).stringof);
4407 return result;
4411 @system unittest
4413 static class C
4415 int i;
4416 this(int i){this.i = i;}
4418 auto buf = new void[__traits(classInstanceSize, C)];
4419 auto c = emplace!C(buf, 5);
4420 assert(c.i == 5);
4423 @system unittest
4425 class Outer
4427 int i = 3;
4428 class Inner
4430 auto getI() { return i; }
4433 auto outerBuf = new void[__traits(classInstanceSize, Outer)];
4434 auto innerBuf = new void[__traits(classInstanceSize, Outer.Inner)];
4435 auto inner = innerBuf.emplace!(Outer.Inner)(outerBuf.emplace!Outer);
4436 assert(inner.getI == 3);
4439 @nogc pure nothrow @system unittest
4441 int var = 6;
4442 align(__conv_EmplaceTestClass.alignof) ubyte[__traits(classInstanceSize, __conv_EmplaceTestClass)] buf;
4443 auto k = emplace!__conv_EmplaceTestClass(buf, 5, var);
4444 assert(k.i == 5);
4445 assert(var == 7);
4449 Given a raw memory area $(D chunk), constructs an object of non-$(D
4450 class) type $(D T) at that address. The constructor is passed the
4451 arguments $(D args), if any.
4453 Preconditions:
4454 $(D chunk) must be at least as large
4455 as $(D T) needs and should have an alignment multiple of $(D T)'s
4456 alignment.
4458 Note:
4459 This function can be $(D @trusted) if the corresponding constructor of
4460 $(D T) is $(D @safe).
4462 Returns: A pointer to the newly constructed object.
4464 T* emplace(T, Args...)(void[] chunk, auto ref Args args)
4465 if (!is(T == class))
4467 testEmplaceChunk(chunk, T.sizeof, T.alignof, T.stringof);
4468 emplaceRef!(T, Unqual!T)(*cast(Unqual!T*) chunk.ptr, args);
4469 return cast(T*) chunk.ptr;
4473 @system unittest
4475 struct S
4477 int a, b;
4479 auto buf = new void[S.sizeof];
4480 S s;
4481 s.a = 42;
4482 s.b = 43;
4483 auto s1 = emplace!S(buf, s);
4484 assert(s1.a == 42 && s1.b == 43);
4487 // Bulk of emplace unittests starts here
4489 @system unittest /* unions */
4491 static union U
4493 string a;
4494 int b;
4495 struct
4497 long c;
4498 int[] d;
4501 U u1 = void;
4502 U u2 = { "hello" };
4503 emplace(&u1, u2);
4504 assert(u1.a == "hello");
4507 version (unittest) private struct __conv_EmplaceTest
4509 int i = 3;
4510 this(int i)
4512 assert(this.i == 3 && i == 5);
4513 this.i = i;
4515 this(int i, ref int j)
4517 assert(i == 5 && j == 6);
4518 this.i = i;
4519 ++j;
4522 @disable:
4523 this();
4524 this(this);
4525 void opAssign();
4528 version (unittest) private class __conv_EmplaceTestClass
4530 int i = 3;
4531 this(int i) @nogc @safe pure nothrow
4533 assert(this.i == 3 && i == 5);
4534 this.i = i;
4536 this(int i, ref int j) @nogc @safe pure nothrow
4538 assert(i == 5 && j == 6);
4539 this.i = i;
4540 ++j;
4544 @system unittest // bugzilla 15772
4546 abstract class Foo {}
4547 class Bar: Foo {}
4548 void[] memory;
4549 // test in emplaceInitializer
4550 static assert(!is(typeof(emplace!Foo(cast(Foo*) memory.ptr))));
4551 static assert( is(typeof(emplace!Bar(cast(Bar*) memory.ptr))));
4552 // test in the emplace overload that takes void[]
4553 static assert(!is(typeof(emplace!Foo(memory))));
4554 static assert( is(typeof(emplace!Bar(memory))));
4557 @system unittest
4559 struct S { @disable this(); }
4560 S s = void;
4561 static assert(!__traits(compiles, emplace(&s)));
4562 emplace(&s, S.init);
4565 @system unittest
4567 struct S1
4570 struct S2
4572 void opAssign(S2);
4575 S1 s1 = void;
4576 S2 s2 = void;
4577 S1[2] as1 = void;
4578 S2[2] as2 = void;
4579 emplace(&s1);
4580 emplace(&s2);
4581 emplace(&as1);
4582 emplace(&as2);
4585 @system unittest
4587 static struct S1
4589 this(this) @disable;
4591 static struct S2
4593 this() @disable;
4595 S1[2] ss1 = void;
4596 S2[2] ss2 = void;
4597 emplace(&ss1);
4598 static assert(!__traits(compiles, emplace(&ss2)));
4599 S1 s1 = S1.init;
4600 S2 s2 = S2.init;
4601 static assert(!__traits(compiles, emplace(&ss1, s1)));
4602 emplace(&ss2, s2);
4605 @system unittest
4607 struct S
4609 immutable int i;
4611 S s = void;
4612 S[2] ss1 = void;
4613 S[2] ss2 = void;
4614 emplace(&s, 5);
4615 assert(s.i == 5);
4616 emplace(&ss1, s);
4617 assert(ss1[0].i == 5 && ss1[1].i == 5);
4618 emplace(&ss2, ss1);
4619 assert(ss2 == ss1);
4622 //Start testing emplace-args here
4624 @system unittest
4626 interface I {}
4627 class K : I {}
4629 K k = null, k2 = new K;
4630 assert(k !is k2);
4631 emplace!K(&k, k2);
4632 assert(k is k2);
4634 I i = null;
4635 assert(i !is k);
4636 emplace!I(&i, k);
4637 assert(i is k);
4640 @system unittest
4642 static struct S
4644 int i = 5;
4645 void opAssign(S){assert(0);}
4647 S[2] sa = void;
4648 S[2] sb;
4649 emplace(&sa, sb);
4650 assert(sa[0].i == 5 && sa[1].i == 5);
4653 //Start testing emplace-struct here
4655 // Test constructor branch
4656 @system unittest
4658 struct S
4660 double x = 5, y = 6;
4661 this(int a, int b)
4663 assert(x == 5 && y == 6);
4664 x = a;
4665 y = b;
4669 auto s1 = new void[S.sizeof];
4670 auto s2 = S(42, 43);
4671 assert(*emplace!S(cast(S*) s1.ptr, s2) == s2);
4672 assert(*emplace!S(cast(S*) s1, 44, 45) == S(44, 45));
4675 @system unittest
4677 __conv_EmplaceTest k = void;
4678 emplace(&k, 5);
4679 assert(k.i == 5);
4682 @system unittest
4684 int var = 6;
4685 __conv_EmplaceTest k = void;
4686 emplace(&k, 5, var);
4687 assert(k.i == 5);
4688 assert(var == 7);
4691 // Test matching fields branch
4692 @system unittest
4694 struct S { uint n; }
4695 S s;
4696 emplace!S(&s, 2U);
4697 assert(s.n == 2);
4700 @safe unittest
4702 struct S { int a, b; this(int){} }
4703 S s;
4704 static assert(!__traits(compiles, emplace!S(&s, 2, 3)));
4707 @system unittest
4709 struct S { int a, b = 7; }
4710 S s1 = void, s2 = void;
4712 emplace!S(&s1, 2);
4713 assert(s1.a == 2 && s1.b == 7);
4715 emplace!S(&s2, 2, 3);
4716 assert(s2.a == 2 && s2.b == 3);
4719 //opAssign
4720 @system unittest
4722 static struct S
4724 int i = 5;
4725 void opAssign(int){assert(0);}
4726 void opAssign(S){assert(0);}
4728 S sa1 = void;
4729 S sa2 = void;
4730 S sb1 = S(1);
4731 emplace(&sa1, sb1);
4732 emplace(&sa2, 2);
4733 assert(sa1.i == 1);
4734 assert(sa2.i == 2);
4737 //postblit precedence
4738 @system unittest
4740 //Works, but breaks in "-w -O" because of @@@9332@@@.
4741 //Uncomment test when 9332 is fixed.
4742 static struct S
4744 int i;
4746 this(S other){assert(false);}
4747 this(int i){this.i = i;}
4748 this(this){}
4750 S a = void;
4751 assert(is(typeof({S b = a;}))); //Postblit
4752 assert(is(typeof({S b = S(a);}))); //Constructor
4753 auto b = S(5);
4754 emplace(&a, b);
4755 assert(a.i == 5);
4757 static struct S2
4759 int* p;
4760 this(const S2){}
4762 static assert(!is(immutable S2 : S2));
4763 S2 s2 = void;
4764 immutable is2 = (immutable S2).init;
4765 emplace(&s2, is2);
4768 //nested structs and postblit
4769 @system unittest
4771 static struct S
4773 int* p;
4774 this(int i){p = [i].ptr;}
4775 this(this)
4777 if (p)
4778 p = [*p].ptr;
4781 static struct SS
4783 S s;
4784 void opAssign(const SS)
4786 assert(0);
4789 SS ssa = void;
4790 SS ssb = SS(S(5));
4791 emplace(&ssa, ssb);
4792 assert(*ssa.s.p == 5);
4793 assert(ssa.s.p != ssb.s.p);
4796 //disabled postblit
4797 @system unittest
4799 static struct S1
4801 int i;
4802 @disable this(this);
4804 S1 s1 = void;
4805 emplace(&s1, 1);
4806 assert(s1.i == 1);
4807 static assert(!__traits(compiles, emplace(&s1, S1.init)));
4809 static struct S2
4811 int i;
4812 @disable this(this);
4813 this(ref S2){}
4815 S2 s2 = void;
4816 static assert(!__traits(compiles, emplace(&s2, 1)));
4817 emplace(&s2, S2.init);
4819 static struct SS1
4821 S1 s;
4823 SS1 ss1 = void;
4824 emplace(&ss1);
4825 static assert(!__traits(compiles, emplace(&ss1, SS1.init)));
4827 static struct SS2
4829 S2 s;
4831 SS2 ss2 = void;
4832 emplace(&ss2);
4833 static assert(!__traits(compiles, emplace(&ss2, SS2.init)));
4836 // SS1 sss1 = s1; //This doesn't compile
4837 // SS1 sss1 = SS1(s1); //This doesn't compile
4838 // So emplace shouldn't compile either
4839 static assert(!__traits(compiles, emplace(&sss1, s1)));
4840 static assert(!__traits(compiles, emplace(&sss2, s2)));
4843 //Imutability
4844 @system unittest
4846 //Castable immutability
4848 static struct S1
4850 int i;
4852 static assert(is( immutable(S1) : S1));
4853 S1 sa = void;
4854 auto sb = immutable(S1)(5);
4855 emplace(&sa, sb);
4856 assert(sa.i == 5);
4858 //Un-castable immutability
4860 static struct S2
4862 int* p;
4864 static assert(!is(immutable(S2) : S2));
4865 S2 sa = void;
4866 auto sb = immutable(S2)(null);
4867 assert(!__traits(compiles, emplace(&sa, sb)));
4871 @system unittest
4873 static struct S
4875 immutable int i;
4876 immutable(int)* j;
4878 S s = void;
4879 emplace(&s, 1, null);
4880 emplace(&s, 2, &s.i);
4881 assert(s is S(2, &s.i));
4884 //Context pointer
4885 @system unittest
4887 int i = 0;
4889 struct S1
4891 void foo(){++i;}
4893 S1 sa = void;
4894 S1 sb;
4895 emplace(&sa, sb);
4896 sa.foo();
4897 assert(i == 1);
4900 struct S2
4902 void foo(){++i;}
4903 this(this){}
4905 S2 sa = void;
4906 S2 sb;
4907 emplace(&sa, sb);
4908 sa.foo();
4909 assert(i == 2);
4913 //Alias this
4914 @system unittest
4916 static struct S
4918 int i;
4920 //By Ref
4922 static struct SS1
4924 int j;
4925 S s;
4926 alias s this;
4928 S s = void;
4929 SS1 ss = SS1(1, S(2));
4930 emplace(&s, ss);
4931 assert(s.i == 2);
4933 //By Value
4935 static struct SS2
4937 int j;
4938 S s;
4939 S foo() @property{return s;}
4940 alias foo this;
4942 S s = void;
4943 SS2 ss = SS2(1, S(2));
4944 emplace(&s, ss);
4945 assert(s.i == 2);
4948 version (unittest)
4950 //Ambiguity
4951 struct __std_conv_S
4953 int i;
4954 this(__std_conv_SS ss) {assert(0);}
4955 static opCall(__std_conv_SS ss)
4957 __std_conv_S s; s.i = ss.j;
4958 return s;
4961 struct __std_conv_SS
4963 int j;
4964 __std_conv_S s;
4965 ref __std_conv_S foo() return @property {s.i = j; return s;}
4966 alias foo this;
4968 static assert(is(__std_conv_SS : __std_conv_S));
4969 @system unittest
4971 __std_conv_S s = void;
4972 __std_conv_SS ss = __std_conv_SS(1);
4974 __std_conv_S sTest1 = ss; //this calls "SS alias this" (and not "S.this(SS)")
4975 emplace(&s, ss); //"alias this" should take precedence in emplace over "opCall"
4976 assert(s.i == 1);
4980 //Nested classes
4981 @system unittest
4983 class A{}
4984 static struct S
4986 A a;
4988 S s1 = void;
4989 S s2 = S(new A);
4990 emplace(&s1, s2);
4991 assert(s1.a is s2.a);
4994 //safety & nothrow & CTFE
4995 @system unittest
4997 //emplace should be safe for anything with no elaborate opassign
4998 static struct S1
5000 int i;
5002 static struct S2
5004 int i;
5005 this(int j)@safe nothrow{i = j;}
5008 int i;
5009 S1 s1 = void;
5010 S2 s2 = void;
5012 auto pi = &i;
5013 auto ps1 = &s1;
5014 auto ps2 = &s2;
5016 void foo() @safe nothrow
5018 emplace(pi);
5019 emplace(pi, 5);
5020 emplace(ps1);
5021 emplace(ps1, 5);
5022 emplace(ps1, S1.init);
5023 emplace(ps2);
5024 emplace(ps2, 5);
5025 emplace(ps2, S2.init);
5027 foo();
5029 T bar(T)() @property
5031 T t/+ = void+/; //CTFE void illegal
5032 emplace(&t, 5);
5033 return t;
5035 // CTFE
5036 enum a = bar!int;
5037 static assert(a == 5);
5038 enum b = bar!S1;
5039 static assert(b.i == 5);
5040 enum c = bar!S2;
5041 static assert(c.i == 5);
5042 // runtime
5043 auto aa = bar!int;
5044 assert(aa == 5);
5045 auto bb = bar!S1;
5046 assert(bb.i == 5);
5047 auto cc = bar!S2;
5048 assert(cc.i == 5);
5052 @system unittest
5054 struct S
5056 int[2] get(){return [1, 2];}
5057 alias get this;
5059 struct SS
5061 int[2] ii;
5063 struct ISS
5065 int[2] ii;
5067 S s;
5068 SS ss = void;
5069 ISS iss = void;
5070 emplace(&ss, s);
5071 emplace(&iss, s);
5072 assert(ss.ii == [1, 2]);
5073 assert(iss.ii == [1, 2]);
5076 //disable opAssign
5077 @system unittest
5079 static struct S
5081 @disable void opAssign(S);
5083 S s;
5084 emplace(&s, S.init);
5087 //opCall
5088 @system unittest
5090 int i;
5091 //Without constructor
5093 static struct S1
5095 int i;
5096 static S1 opCall(int*){assert(0);}
5098 S1 s = void;
5099 static assert(!__traits(compiles, emplace(&s, 1)));
5101 //With constructor
5103 static struct S2
5105 int i = 0;
5106 static S2 opCall(int*){assert(0);}
5107 static S2 opCall(int){assert(0);}
5108 this(int i){this.i = i;}
5110 S2 s = void;
5111 emplace(&s, 1);
5112 assert(s.i == 1);
5114 //With postblit ambiguity
5116 static struct S3
5118 int i = 0;
5119 static S3 opCall(ref S3){assert(0);}
5121 S3 s = void;
5122 emplace(&s, S3.init);
5126 @safe unittest //@@@9559@@@
5128 import std.algorithm.iteration : map;
5129 import std.array : array;
5130 import std.typecons : Nullable;
5131 alias I = Nullable!int;
5132 auto ints = [0, 1, 2].map!(i => i & 1 ? I.init : I(i))();
5133 auto asArray = array(ints);
5136 @system unittest //http://forum.dlang.org/post/nxbdgtdlmwscocbiypjs@forum.dlang.org
5138 import std.array : array;
5139 import std.datetime : SysTime, UTC;
5140 import std.math : isNaN;
5142 static struct A
5144 double i;
5147 static struct B
5149 invariant()
5151 if (j == 0)
5152 assert(a.i.isNaN(), "why is 'j' zero?? and i is not NaN?");
5153 else
5154 assert(!a.i.isNaN());
5156 SysTime when; // comment this line avoid the breakage
5157 int j;
5158 A a;
5161 B b1 = B.init;
5162 assert(&b1); // verify that default eyes invariants are ok;
5164 auto b2 = B(SysTime(0, UTC()), 1, A(1));
5165 assert(&b2);
5166 auto b3 = B(SysTime(0, UTC()), 1, A(1));
5167 assert(&b3);
5169 auto arr = [b2, b3];
5171 assert(arr[0].j == 1);
5172 assert(arr[1].j == 1);
5173 auto a2 = arr.array(); // << bang, invariant is raised, also if b2 and b3 are good
5176 //static arrays
5177 @system unittest
5179 static struct S
5181 int[2] ii;
5183 static struct IS
5185 immutable int[2] ii;
5187 int[2] ii;
5188 S s = void;
5189 IS ims = void;
5190 ubyte ub = 2;
5191 emplace(&s, ub);
5192 emplace(&s, ii);
5193 emplace(&ims, ub);
5194 emplace(&ims, ii);
5195 uint[2] uu;
5196 static assert(!__traits(compiles, {S ss = S(uu);}));
5197 static assert(!__traits(compiles, emplace(&s, uu)));
5200 @system unittest
5202 int[2] sii;
5203 int[2] sii2;
5204 uint[2] uii;
5205 uint[2] uii2;
5206 emplace(&sii, 1);
5207 emplace(&sii, 1U);
5208 emplace(&uii, 1);
5209 emplace(&uii, 1U);
5210 emplace(&sii, sii2);
5211 //emplace(&sii, uii2); //Sorry, this implementation doesn't know how to...
5212 //emplace(&uii, sii2); //Sorry, this implementation doesn't know how to...
5213 emplace(&uii, uii2);
5214 emplace(&sii, sii2[]);
5215 //emplace(&sii, uii2[]); //Sorry, this implementation doesn't know how to...
5216 //emplace(&uii, sii2[]); //Sorry, this implementation doesn't know how to...
5217 emplace(&uii, uii2[]);
5220 @system unittest
5222 bool allowDestruction = false;
5223 struct S
5225 int i;
5226 this(this){}
5227 ~this(){assert(allowDestruction);}
5229 S s = S(1);
5230 S[2] ss1 = void;
5231 S[2] ss2 = void;
5232 S[2] ss3 = void;
5233 emplace(&ss1, s);
5234 emplace(&ss2, ss1);
5235 emplace(&ss3, ss2[]);
5236 assert(ss1[1] == s);
5237 assert(ss2[1] == s);
5238 assert(ss3[1] == s);
5239 allowDestruction = true;
5242 @system unittest
5244 //Checks postblit, construction, and context pointer
5245 int count = 0;
5246 struct S
5248 this(this)
5250 ++count;
5252 ~this()
5254 --count;
5258 S s;
5260 S[4] ss = void;
5261 emplace(&ss, s);
5262 assert(count == 4);
5264 assert(count == 0);
5267 @system unittest
5269 struct S
5271 int i;
5273 S s;
5274 S[2][2][2] sss = void;
5275 emplace(&sss, s);
5278 @system unittest //Constness
5280 import std.stdio;
5282 int a = void;
5283 emplaceRef!(const int)(a, 5);
5285 immutable i = 5;
5286 const(int)* p = void;
5287 emplaceRef!(const int*)(p, &i);
5289 struct S
5291 int* p;
5293 alias IS = immutable(S);
5294 S s = void;
5295 emplaceRef!IS(s, IS());
5296 S[2] ss = void;
5297 emplaceRef!(IS[2])(ss, IS());
5299 IS[2] iss = IS.init;
5300 emplaceRef!(IS[2])(ss, iss);
5301 emplaceRef!(IS[2])(ss, iss[]);
5304 pure nothrow @safe @nogc unittest
5306 int i;
5307 emplaceRef(i);
5308 emplaceRef!int(i);
5309 emplaceRef(i, 5);
5310 emplaceRef!int(i, 5);
5313 // Test attribute propagation for UDTs
5314 pure nothrow @safe /* @nogc */ unittest
5316 static struct Safe
5318 this(this) pure nothrow @safe @nogc {}
5321 Safe safe = void;
5322 emplaceRef(safe, Safe());
5324 Safe[1] safeArr = [Safe()];
5325 Safe[1] uninitializedSafeArr = void;
5326 emplaceRef(uninitializedSafeArr, safe);
5327 emplaceRef(uninitializedSafeArr, safeArr);
5329 static struct Unsafe
5331 this(this) @system {}
5334 Unsafe unsafe = void;
5335 static assert(!__traits(compiles, emplaceRef(unsafe, Unsafe())));
5337 Unsafe[1] unsafeArr = [Unsafe()];
5338 Unsafe[1] uninitializedUnsafeArr = void;
5339 static assert(!__traits(compiles, emplaceRef(uninitializedUnsafeArr, unsafe)));
5340 static assert(!__traits(compiles, emplaceRef(uninitializedUnsafeArr, unsafeArr)));
5343 @system unittest
5345 // Issue 15313
5346 static struct Node
5348 int payload;
5349 Node* next;
5350 uint refs;
5353 import core.stdc.stdlib : malloc;
5354 void[] buf = malloc(Node.sizeof)[0 .. Node.sizeof];
5356 import std.conv : emplace;
5357 const Node* n = emplace!(const Node)(buf, 42, null, 10);
5358 assert(n.payload == 42);
5359 assert(n.next == null);
5360 assert(n.refs == 10);
5363 @system unittest
5365 int var = 6;
5366 auto k = emplace!__conv_EmplaceTest(new void[__conv_EmplaceTest.sizeof], 5, var);
5367 assert(k.i == 5);
5368 assert(var == 7);
5371 @system unittest
5373 class A
5375 int x = 5;
5376 int y = 42;
5377 this(int z)
5379 assert(x == 5 && y == 42);
5380 x = y = z;
5383 void[] buf;
5385 static align(A.alignof) byte[__traits(classInstanceSize, A)] sbuf;
5386 buf = sbuf[];
5387 auto a = emplace!A(buf, 55);
5388 assert(a.x == 55 && a.y == 55);
5390 // emplace in bigger buffer
5391 buf = new byte[](__traits(classInstanceSize, A) + 10);
5392 a = emplace!A(buf, 55);
5393 assert(a.x == 55 && a.y == 55);
5395 // need ctor args
5396 static assert(!is(typeof(emplace!A(buf))));
5398 // Bulk of emplace unittests ends here
5400 @safe unittest
5402 import std.algorithm.comparison : equal;
5403 import std.algorithm.iteration : map;
5404 // Check fix for http://d.puremagic.com/issues/show_bug.cgi?id=2971
5405 assert(equal(map!(to!int)(["42", "34", "345"]), [42, 34, 345]));
5408 // Undocumented for the time being
5409 void toTextRange(T, W)(T value, W writer)
5410 if (isIntegral!T && isOutputRange!(W, char))
5412 import core.internal.string : SignedStringBuf, signedToTempString,
5413 UnsignedStringBuf, unsignedToTempString;
5415 if (value < 0)
5417 SignedStringBuf buf = void;
5418 put(writer, signedToTempString(value, buf, 10));
5420 else
5422 UnsignedStringBuf buf = void;
5423 put(writer, unsignedToTempString(value, buf, 10));
5427 @safe unittest
5429 import std.array : appender;
5430 auto result = appender!(char[])();
5431 toTextRange(-1, result);
5432 assert(result.data == "-1");
5437 Returns the corresponding _unsigned value for $(D x) (e.g. if $(D x) has type
5438 $(D int), it returns $(D cast(uint) x)). The advantage compared to the cast
5439 is that you do not need to rewrite the cast if $(D x) later changes type
5440 (e.g from $(D int) to $(D long)).
5442 Note that the result is always mutable even if the original type was const
5443 or immutable. In order to retain the constness, use $(REF Unsigned, std,traits).
5445 auto unsigned(T)(T x)
5446 if (isIntegral!T)
5448 return cast(Unqual!(Unsigned!T))x;
5452 @safe unittest
5454 import std.traits : Unsigned;
5455 immutable int s = 42;
5456 auto u1 = unsigned(s); //not qualified
5457 static assert(is(typeof(u1) == uint));
5458 Unsigned!(typeof(s)) u2 = unsigned(s); //same qualification
5459 static assert(is(typeof(u2) == immutable uint));
5460 immutable u3 = unsigned(s); //explicitly qualified
5463 @safe unittest
5465 foreach (T; AliasSeq!(byte, ubyte))
5467 static assert(is(typeof(unsigned(cast(T) 1)) == ubyte));
5468 static assert(is(typeof(unsigned(cast(const T) 1)) == ubyte));
5469 static assert(is(typeof(unsigned(cast(immutable T) 1)) == ubyte));
5472 foreach (T; AliasSeq!(short, ushort))
5474 static assert(is(typeof(unsigned(cast(T) 1)) == ushort));
5475 static assert(is(typeof(unsigned(cast(const T) 1)) == ushort));
5476 static assert(is(typeof(unsigned(cast(immutable T) 1)) == ushort));
5479 foreach (T; AliasSeq!(int, uint))
5481 static assert(is(typeof(unsigned(cast(T) 1)) == uint));
5482 static assert(is(typeof(unsigned(cast(const T) 1)) == uint));
5483 static assert(is(typeof(unsigned(cast(immutable T) 1)) == uint));
5486 foreach (T; AliasSeq!(long, ulong))
5488 static assert(is(typeof(unsigned(cast(T) 1)) == ulong));
5489 static assert(is(typeof(unsigned(cast(const T) 1)) == ulong));
5490 static assert(is(typeof(unsigned(cast(immutable T) 1)) == ulong));
5494 auto unsigned(T)(T x)
5495 if (isSomeChar!T)
5497 // All characters are unsigned
5498 static assert(T.min == 0);
5499 return cast(Unqual!T) x;
5502 @safe unittest
5504 foreach (T; AliasSeq!(char, wchar, dchar))
5506 static assert(is(typeof(unsigned(cast(T)'A')) == T));
5507 static assert(is(typeof(unsigned(cast(const T)'A')) == T));
5508 static assert(is(typeof(unsigned(cast(immutable T)'A')) == T));
5514 Returns the corresponding _signed value for $(D x) (e.g. if $(D x) has type
5515 $(D uint), it returns $(D cast(int) x)). The advantage compared to the cast
5516 is that you do not need to rewrite the cast if $(D x) later changes type
5517 (e.g from $(D uint) to $(D ulong)).
5519 Note that the result is always mutable even if the original type was const
5520 or immutable. In order to retain the constness, use $(REF Signed, std,traits).
5522 auto signed(T)(T x)
5523 if (isIntegral!T)
5525 return cast(Unqual!(Signed!T))x;
5529 @safe unittest
5531 import std.traits : Signed;
5533 immutable uint u = 42;
5534 auto s1 = signed(u); //not qualified
5535 static assert(is(typeof(s1) == int));
5536 Signed!(typeof(u)) s2 = signed(u); //same qualification
5537 static assert(is(typeof(s2) == immutable int));
5538 immutable s3 = signed(u); //explicitly qualified
5541 @system unittest
5543 foreach (T; AliasSeq!(byte, ubyte))
5545 static assert(is(typeof(signed(cast(T) 1)) == byte));
5546 static assert(is(typeof(signed(cast(const T) 1)) == byte));
5547 static assert(is(typeof(signed(cast(immutable T) 1)) == byte));
5550 foreach (T; AliasSeq!(short, ushort))
5552 static assert(is(typeof(signed(cast(T) 1)) == short));
5553 static assert(is(typeof(signed(cast(const T) 1)) == short));
5554 static assert(is(typeof(signed(cast(immutable T) 1)) == short));
5557 foreach (T; AliasSeq!(int, uint))
5559 static assert(is(typeof(signed(cast(T) 1)) == int));
5560 static assert(is(typeof(signed(cast(const T) 1)) == int));
5561 static assert(is(typeof(signed(cast(immutable T) 1)) == int));
5564 foreach (T; AliasSeq!(long, ulong))
5566 static assert(is(typeof(signed(cast(T) 1)) == long));
5567 static assert(is(typeof(signed(cast(const T) 1)) == long));
5568 static assert(is(typeof(signed(cast(immutable T) 1)) == long));
5572 @safe unittest
5574 // issue 10874
5575 enum Test { a = 0 }
5576 ulong l = 0;
5577 auto t = l.to!Test;
5580 // asOriginalType
5582 Returns the representation of an enumerated value, i.e. the value converted to
5583 the base type of the enumeration.
5585 OriginalType!E asOriginalType(E)(E value) if (is(E == enum))
5587 return value;
5591 @safe unittest
5593 enum A { a = 42 }
5594 static assert(is(typeof(A.a.asOriginalType) == int));
5595 assert(A.a.asOriginalType == 42);
5596 enum B : double { a = 43 }
5597 static assert(is(typeof(B.a.asOriginalType) == double));
5598 assert(B.a.asOriginalType == 43);
5602 A wrapper on top of the built-in cast operator that allows one to restrict
5603 casting of the original type of the value.
5605 A common issue with using a raw cast is that it may silently continue to
5606 compile even if the value's type has changed during refactoring,
5607 which breaks the initial assumption about the cast.
5609 Params:
5610 From = The type to cast from. The programmer must ensure it is legal
5611 to make this cast.
5613 template castFrom(From)
5616 Params:
5617 To = The type _to cast _to.
5618 value = The value _to cast. It must be of type $(D From),
5619 otherwise a compile-time error is emitted.
5621 Returns:
5622 the value after the cast, returned by reference if possible.
5624 auto ref to(To, T)(auto ref T value) @system
5626 static assert(
5627 is(From == T),
5628 "the value to cast is not of specified type '" ~ From.stringof ~
5629 "', it is of type '" ~ T.stringof ~ "'"
5632 static assert(
5633 is(typeof(cast(To) value)),
5634 "can't cast from '" ~ From.stringof ~ "' to '" ~ To.stringof ~ "'"
5637 return cast(To) value;
5642 @system unittest
5644 // Regular cast, which has been verified to be legal by the programmer:
5646 long x;
5647 auto y = cast(int) x;
5650 // However this will still compile if 'x' is changed to be a pointer:
5652 long* x;
5653 auto y = cast(int) x;
5656 // castFrom provides a more reliable alternative to casting:
5658 long x;
5659 auto y = castFrom!long.to!int(x);
5662 // Changing the type of 'x' will now issue a compiler error,
5663 // allowing bad casts to be caught before it's too late:
5665 long* x;
5666 static assert(
5667 !__traits(compiles, castFrom!long.to!int(x))
5670 // if cast is still needed, must be changed to:
5671 auto y = castFrom!(long*).to!int(x);
5675 // https://issues.dlang.org/show_bug.cgi?id=16667
5676 @system unittest
5678 ubyte[] a = ['a', 'b', 'c'];
5679 assert(castFrom!(ubyte[]).to!(string)(a) == "abc");
5683 Check the correctness of a string for $(D hexString).
5684 The result is true if and only if the input string is composed of whitespace
5685 characters (\f\n\r\t\v lineSep paraSep nelSep) and
5686 an even number of hexadecimal digits (regardless of the case).
5688 @safe pure @nogc
5689 private bool isHexLiteral(String)(scope const String hexData)
5691 import std.ascii : isHexDigit;
5692 import std.uni : lineSep, paraSep, nelSep;
5693 size_t i;
5694 foreach (const dchar c; hexData)
5696 switch (c)
5698 case ' ':
5699 case '\t':
5700 case '\v':
5701 case '\f':
5702 case '\r':
5703 case '\n':
5704 case lineSep:
5705 case paraSep:
5706 case nelSep:
5707 continue;
5709 default:
5710 break;
5712 if (c.isHexDigit)
5713 ++i;
5714 else
5715 return false;
5717 return !(i & 1);
5720 @safe unittest
5722 // test all the hex digits
5723 static assert( ("0123456789abcdefABCDEF").isHexLiteral);
5724 // empty or white strings are not valid
5725 static assert( "\r\n\t".isHexLiteral);
5726 // but are accepted if the count of hex digits is even
5727 static assert( "A\r\n\tB".isHexLiteral);
5730 @safe unittest
5732 import std.ascii;
5733 // empty/whites
5734 static assert( "".isHexLiteral);
5735 static assert( " \r".isHexLiteral);
5736 static assert( whitespace.isHexLiteral);
5737 static assert( ""w.isHexLiteral);
5738 static assert( " \r"w.isHexLiteral);
5739 static assert( ""d.isHexLiteral);
5740 static assert( " \r"d.isHexLiteral);
5741 static assert( "\u2028\u2029\u0085"d.isHexLiteral);
5742 // odd x strings
5743 static assert( !("5" ~ whitespace).isHexLiteral);
5744 static assert( !"123".isHexLiteral);
5745 static assert( !"1A3".isHexLiteral);
5746 static assert( !"1 23".isHexLiteral);
5747 static assert( !"\r\n\tC".isHexLiteral);
5748 static assert( !"123"w.isHexLiteral);
5749 static assert( !"1A3"w.isHexLiteral);
5750 static assert( !"1 23"w.isHexLiteral);
5751 static assert( !"\r\n\tC"w.isHexLiteral);
5752 static assert( !"123"d.isHexLiteral);
5753 static assert( !"1A3"d.isHexLiteral);
5754 static assert( !"1 23"d.isHexLiteral);
5755 static assert( !"\r\n\tC"d.isHexLiteral);
5756 // even x strings with invalid charset
5757 static assert( !"12gG".isHexLiteral);
5758 static assert( !"2A 3q".isHexLiteral);
5759 static assert( !"12gG"w.isHexLiteral);
5760 static assert( !"2A 3q"w.isHexLiteral);
5761 static assert( !"12gG"d.isHexLiteral);
5762 static assert( !"2A 3q"d.isHexLiteral);
5763 // valid x strings
5764 static assert( ("5A" ~ whitespace).isHexLiteral);
5765 static assert( ("5A 01A C FF de 1b").isHexLiteral);
5766 static assert( ("0123456789abcdefABCDEF").isHexLiteral);
5767 static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF").isHexLiteral);
5768 static assert( ("5A 01A C FF de 1b"w).isHexLiteral);
5769 static assert( ("0123456789abcdefABCDEF"w).isHexLiteral);
5770 static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"w).isHexLiteral);
5771 static assert( ("5A 01A C FF de 1b"d).isHexLiteral);
5772 static assert( ("0123456789abcdefABCDEF"d).isHexLiteral);
5773 static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"d).isHexLiteral);
5774 // library version allows what's pointed by issue 10454
5775 static assert( ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").isHexLiteral);
5779 Converts a hex literal to a string at compile time.
5781 Takes a string made of hexadecimal digits and returns
5782 the matching string by converting each pair of digits to a character.
5783 The input string can also include white characters, which can be used
5784 to keep the literal string readable in the source code.
5786 The function is intended to replace the hexadecimal literal strings
5787 starting with $(D 'x'), which could be removed to simplify the core language.
5789 Params:
5790 hexData = string to be converted.
5792 Returns:
5793 a $(D string), a $(D wstring) or a $(D dstring), according to the type of hexData.
5795 template hexString(string hexData)
5796 if (hexData.isHexLiteral)
5798 immutable hexString = hexStrImpl(hexData);
5801 /// ditto
5802 template hexString(wstring hexData)
5803 if (hexData.isHexLiteral)
5805 immutable hexString = hexStrImpl(hexData);
5808 /// ditto
5809 template hexString(dstring hexData)
5810 if (hexData.isHexLiteral)
5812 immutable hexString = hexStrImpl(hexData);
5816 @safe unittest
5818 // conversion at compile time
5819 auto string1 = hexString!"304A314B";
5820 assert(string1 == "0J1K");
5821 auto string2 = hexString!"304A314B"w;
5822 assert(string2 == "0J1K"w);
5823 auto string3 = hexString!"304A314B"d;
5824 assert(string3 == "0J1K"d);
5828 Takes a hexadecimal string literal and returns its representation.
5829 hexData is granted to be a valid string by the caller.
5830 C is granted to be a valid char type by the caller.
5832 @safe nothrow pure
5833 private auto hexStrImpl(String)(scope String hexData)
5835 import std.ascii : isHexDigit;
5836 alias C = Unqual!(ElementEncodingType!String);
5837 C[] result;
5838 result.length = hexData.length / 2;
5839 size_t cnt;
5840 ubyte v;
5841 foreach (c; hexData)
5843 if (c.isHexDigit)
5845 ubyte x;
5846 if (c >= '0' && c <= '9')
5847 x = cast(ubyte)(c - '0');
5848 else if (c >= 'a' && c <= 'f')
5849 x = cast(ubyte)(c - ('a' - 10));
5850 else if (c >= 'A' && c <= 'F')
5851 x = cast(ubyte)(c - ('A' - 10));
5852 if (cnt & 1)
5854 v = cast(ubyte)((v << 4) | x);
5855 result[cnt / 2] = v;
5857 else
5858 v = x;
5859 ++cnt;
5862 result.length = cnt / 2;
5863 return result;
5866 @safe unittest
5868 // compile time
5869 assert(hexString!"46 47 48 49 4A 4B" == "FGHIJK");
5870 assert(hexString!"30\r\n\t\f\v31 32 33 32 31 30" == "0123210");
5871 assert(hexString!"ab cd" == hexString!"ABCD");
5876 * Convert integer to a range of characters.
5877 * Intended to be lightweight and fast.
5879 * Params:
5880 * radix = 2, 8, 10, 16
5881 * Char = character type for output
5882 * letterCase = lower for deadbeef, upper for DEADBEEF
5883 * value = integer to convert. Can be uint or ulong. If radix is 10, can also be
5884 * int or long.
5885 * Returns:
5886 * Random access range with slicing and everything
5889 auto toChars(ubyte radix = 10, Char = char, LetterCase letterCase = LetterCase.lower, T)(T value)
5890 pure nothrow @nogc @safe
5891 if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) &&
5892 (is(Unqual!T == uint) || is(Unqual!T == ulong) ||
5893 radix == 10 && (is(Unqual!T == int) || is(Unqual!T == long))))
5895 alias UT = Unqual!T;
5897 static if (radix == 10)
5899 /* uint.max is 42_9496_7295
5900 * int.max is 21_4748_3647
5901 * ulong.max is 1844_6744_0737_0955_1615
5902 * long.max is 922_3372_0368_5477_5807
5904 static struct Result
5906 void initialize(UT value)
5908 bool neg = false;
5909 if (value < 10)
5911 if (value >= 0)
5913 lwr = 0;
5914 upr = 1;
5915 buf[0] = cast(char)(cast(uint) value + '0');
5916 return;
5918 value = -value;
5919 neg = true;
5921 auto i = cast(uint) buf.length - 1;
5922 while (cast(Unsigned!UT) value >= 10)
5924 buf[i] = cast(ubyte)('0' + cast(Unsigned!UT) value % 10);
5925 value = unsigned(value) / 10;
5926 --i;
5928 buf[i] = cast(char)(cast(uint) value + '0');
5929 if (neg)
5931 buf[i - 1] = '-';
5932 --i;
5934 lwr = i;
5935 upr = cast(uint) buf.length;
5938 @property size_t length() { return upr - lwr; }
5940 alias opDollar = length;
5942 @property bool empty() { return upr == lwr; }
5944 @property Char front() { return buf[lwr]; }
5946 void popFront() { ++lwr; }
5948 @property Char back() { return buf[upr - 1]; }
5950 void popBack() { --upr; }
5952 @property Result save() { return this; }
5954 Char opIndex(size_t i) { return buf[lwr + i]; }
5956 Result opSlice(size_t lwr, size_t upr)
5958 Result result = void;
5959 result.buf = buf;
5960 result.lwr = cast(uint)(this.lwr + lwr);
5961 result.upr = cast(uint)(this.lwr + upr);
5962 return result;
5965 private:
5966 uint lwr = void, upr = void;
5967 char[(UT.sizeof == 4) ? 10 + isSigned!T : 20] buf = void;
5970 Result result = void;
5971 result.initialize(value);
5972 return result;
5974 else
5976 static if (radix == 2)
5977 enum SHIFT = 1;
5978 else static if (radix == 8)
5979 enum SHIFT = 3;
5980 else static if (radix == 16)
5981 enum SHIFT = 4;
5982 else
5983 static assert(0);
5984 static struct Result
5986 this(UT value)
5988 this.value = value;
5990 ubyte len = 1;
5991 while (value >>>= SHIFT)
5992 ++len;
5993 this.len = len;
5996 @property size_t length() { return len; }
5998 @property bool empty() { return len == 0; }
6000 @property Char front() { return opIndex(0); }
6002 void popFront() { --len; }
6004 @property Char back() { return opIndex(len - 1); }
6006 void popBack()
6008 value >>>= SHIFT;
6009 --len;
6012 @property Result save() { return this; }
6014 Char opIndex(size_t i)
6016 Char c = (value >>> ((len - i - 1) * SHIFT)) & ((1 << SHIFT) - 1);
6017 return cast(Char)((radix < 10 || c < 10) ? c + '0'
6018 : (letterCase == LetterCase.upper ? c + 'A' - 10
6019 : c + 'a' - 10));
6022 Result opSlice(size_t lwr, size_t upr)
6024 Result result = void;
6025 result.value = value >>> ((len - upr) * SHIFT);
6026 result.len = cast(ubyte)(upr - lwr);
6027 return result;
6030 private:
6031 UT value;
6032 ubyte len;
6035 return Result(value);
6040 @safe unittest
6042 import std.array;
6043 import std.range;
6046 assert(toChars!2(0u).array == "0");
6047 assert(toChars!2(0Lu).array == "0");
6048 assert(toChars!2(1u).array == "1");
6049 assert(toChars!2(1Lu).array == "1");
6051 auto r = toChars!2(2u);
6052 assert(r.length == 2);
6053 assert(r[0] == '1');
6054 assert(r[1 .. 2].array == "0");
6055 auto s = r.save;
6056 assert(r.array == "10");
6057 assert(s.retro.array == "01");
6060 assert(toChars!8(0u).array == "0");
6061 assert(toChars!8(0Lu).array == "0");
6062 assert(toChars!8(1u).array == "1");
6063 assert(toChars!8(1234567Lu).array == "4553207");
6065 auto r = toChars!8(8u);
6066 assert(r.length == 2);
6067 assert(r[0] == '1');
6068 assert(r[1 .. 2].array == "0");
6069 auto s = r.save;
6070 assert(r.array == "10");
6071 assert(s.retro.array == "01");
6074 assert(toChars!10(0u).array == "0");
6075 assert(toChars!10(0Lu).array == "0");
6076 assert(toChars!10(1u).array == "1");
6077 assert(toChars!10(1234567Lu).array == "1234567");
6078 assert(toChars!10(uint.max).array == "4294967295");
6079 assert(toChars!10(ulong.max).array == "18446744073709551615");
6081 auto r = toChars(10u);
6082 assert(r.length == 2);
6083 assert(r[0] == '1');
6084 assert(r[1 .. 2].array == "0");
6085 auto s = r.save;
6086 assert(r.array == "10");
6087 assert(s.retro.array == "01");
6090 assert(toChars!10(0).array == "0");
6091 assert(toChars!10(0L).array == "0");
6092 assert(toChars!10(1).array == "1");
6093 assert(toChars!10(1234567L).array == "1234567");
6094 assert(toChars!10(int.max).array == "2147483647");
6095 assert(toChars!10(long.max).array == "9223372036854775807");
6096 assert(toChars!10(-int.max).array == "-2147483647");
6097 assert(toChars!10(-long.max).array == "-9223372036854775807");
6098 assert(toChars!10(int.min).array == "-2147483648");
6099 assert(toChars!10(long.min).array == "-9223372036854775808");
6101 auto r = toChars!10(10);
6102 assert(r.length == 2);
6103 assert(r[0] == '1');
6104 assert(r[1 .. 2].array == "0");
6105 auto s = r.save;
6106 assert(r.array == "10");
6107 assert(s.retro.array == "01");
6110 assert(toChars!(16)(0u).array == "0");
6111 assert(toChars!(16)(0Lu).array == "0");
6112 assert(toChars!(16)(10u).array == "a");
6113 assert(toChars!(16, char, LetterCase.upper)(0x12AF34567Lu).array == "12AF34567");
6115 auto r = toChars!(16)(16u);
6116 assert(r.length == 2);
6117 assert(r[0] == '1');
6118 assert(r[1 .. 2].array == "0");
6119 auto s = r.save;
6120 assert(r.array == "10");
6121 assert(s.retro.array == "01");
6125 @safe unittest // opSlice (issue 16192)
6127 import std.meta : AliasSeq;
6129 static struct Test { ubyte radix; uint number; }
6131 alias tests = AliasSeq!(
6132 Test(2, 0b1_0110_0111u),
6133 Test(2, 0b10_1100_1110u),
6134 Test(8, octal!123456701u),
6135 Test(8, octal!1234567012u),
6136 Test(10, 123456789u),
6137 Test(10, 1234567890u),
6138 Test(16, 0x789ABCDu),
6139 Test(16, 0x789ABCDEu),
6142 foreach (test; tests)
6144 enum ubyte radix = test.radix;
6145 auto original = toChars!radix(test.number);
6147 // opSlice vs popFront
6148 auto r = original.save;
6149 size_t i = 0;
6150 for (; !r.empty; r.popFront(), ++i)
6152 assert(original[i .. original.length].tupleof == r.tupleof);
6153 // tupleof is used to work around issue 16216.
6156 // opSlice vs popBack
6157 r = original.save;
6158 i = 0;
6159 for (; !r.empty; r.popBack(), ++i)
6161 assert(original[0 .. original.length - i].tupleof == r.tupleof);
6164 // opSlice vs both popFront and popBack
6165 r = original.save;
6166 i = 0;
6167 for (; r.length >= 2; r.popFront(), r.popBack(), ++i)
6169 assert(original[i .. original.length - i].tupleof == r.tupleof);