PageRenderTime 85ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/std/conv.d

http://github.com/jcd/phobos
D | 4888 lines | 3813 code | 448 blank | 627 comment | 824 complexity | 9f8975efc579f42aff691130644fc5ba MD5 | raw file
  1. // Written in the D programming language.
  2. /**
  3. A one-stop shop for converting values from one type to another.
  4. Copyright: Copyright Digital Mars 2007-.
  5. License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
  6. Authors: $(WEB digitalmars.com, Walter Bright),
  7. $(WEB erdani.org, Andrei Alexandrescu),
  8. Shin Fujishiro,
  9. Adam D. Ruppe,
  10. Kenji Hara
  11. Source: $(PHOBOSSRC std/_conv.d)
  12. Macros:
  13. WIKI = Phobos/StdConv
  14. */
  15. module std.conv;
  16. import core.stdc.string;
  17. import std.algorithm, std.array, std.ascii, std.exception, std.range,
  18. std.string, std.traits, std.typecons, std.typetuple, std.uni,
  19. std.utf;
  20. import std.format;
  21. //debug=conv; // uncomment to turn on debugging printf's
  22. /* ************* Exceptions *************** */
  23. /**
  24. * Thrown on conversion errors.
  25. */
  26. class ConvException : Exception
  27. {
  28. @safe pure nothrow
  29. this(string s, string fn = __FILE__, size_t ln = __LINE__)
  30. {
  31. super(s, fn, ln);
  32. }
  33. }
  34. private string convError_unexpected(S)(S source)
  35. {
  36. return source.empty ? "end of input" : text("'", source.front, "'");
  37. }
  38. private auto convError(S, T)(S source, string fn = __FILE__, size_t ln = __LINE__)
  39. {
  40. return new ConvException(
  41. text("Unexpected ", convError_unexpected(source),
  42. " when converting from type "~S.stringof~" to type "~T.stringof),
  43. fn, ln);
  44. }
  45. private auto convError(S, T)(S source, int radix, string fn = __FILE__, size_t ln = __LINE__)
  46. {
  47. return new ConvException(
  48. text("Unexpected ", convError_unexpected(source),
  49. " when converting from type "~S.stringof~" base ", radix,
  50. " to type "~T.stringof),
  51. fn, ln);
  52. }
  53. @safe pure/* nothrow*/ // lazy parameter bug
  54. private auto parseError(lazy string msg, string fn = __FILE__, size_t ln = __LINE__)
  55. {
  56. return new ConvException(text("Can't parse string: ", msg), fn, ln);
  57. }
  58. private void parseCheck(alias source)(dchar c, string fn = __FILE__, size_t ln = __LINE__)
  59. {
  60. if (source.empty)
  61. throw parseError(text("unexpected end of input when expecting", "\"", c, "\""));
  62. if (source.front != c)
  63. throw parseError(text("\"", c, "\" is missing"), fn, ln);
  64. source.popFront();
  65. }
  66. private
  67. {
  68. template isImaginary(T)
  69. {
  70. enum bool isImaginary = staticIndexOf!(Unqual!T,
  71. ifloat, idouble, ireal) >= 0;
  72. }
  73. template isComplex(T)
  74. {
  75. enum bool isComplex = staticIndexOf!(Unqual!T,
  76. cfloat, cdouble, creal) >= 0;
  77. }
  78. template isNarrowInteger(T)
  79. {
  80. enum bool isNarrowInteger = staticIndexOf!(Unqual!T,
  81. byte, ubyte, short, ushort) >= 0;
  82. }
  83. T toStr(T, S)(S src)
  84. if (isSomeString!T)
  85. {
  86. import std.format : FormatSpec, formatValue;
  87. auto w = appender!T();
  88. FormatSpec!(ElementEncodingType!T) f;
  89. formatValue(w, src, f);
  90. return w.data;
  91. }
  92. template isExactSomeString(T)
  93. {
  94. enum isExactSomeString = isSomeString!T && !is(T == enum);
  95. }
  96. template isEnumStrToStr(S, T)
  97. {
  98. enum isEnumStrToStr = isImplicitlyConvertible!(S, T) &&
  99. is(S == enum) && isExactSomeString!T;
  100. }
  101. template isNullToStr(S, T)
  102. {
  103. enum isNullToStr = isImplicitlyConvertible!(S, T) &&
  104. (is(Unqual!S == typeof(null))) && isExactSomeString!T;
  105. }
  106. template isRawStaticArray(T, A...)
  107. {
  108. enum isRawStaticArray =
  109. A.length == 0 &&
  110. isStaticArray!T &&
  111. !is(T == class) &&
  112. !is(T == interface) &&
  113. !is(T == struct) &&
  114. !is(T == union);
  115. }
  116. }
  117. /**
  118. * Thrown on conversion overflow errors.
  119. */
  120. class ConvOverflowException : ConvException
  121. {
  122. @safe pure nothrow
  123. this(string s, string fn = __FILE__, size_t ln = __LINE__)
  124. {
  125. super(s, fn, ln);
  126. }
  127. }
  128. /**
  129. The $(D_PARAM to) family of functions converts a value from type
  130. $(D_PARAM Source) to type $(D_PARAM Target). The source type is
  131. deduced and the target type must be specified, for example the
  132. expression $(D_PARAM to!int(42.0)) converts the number 42 from
  133. $(D_PARAM double) to $(D_PARAM int). The conversion is "safe", i.e.,
  134. it checks for overflow; $(D_PARAM to!int(4.2e10)) would throw the
  135. $(D_PARAM ConvOverflowException) exception. Overflow checks are only
  136. inserted when necessary, e.g., $(D_PARAM to!double(42)) does not do
  137. any checking because any int fits in a double.
  138. Converting a value to its own type (useful mostly for generic code)
  139. simply returns its argument.
  140. Example:
  141. -------------------------
  142. int a = 42;
  143. auto b = to!int(a); // b is int with value 42
  144. auto c = to!double(3.14); // c is double with value 3.14
  145. -------------------------
  146. Converting among numeric types is a safe way to cast them around.
  147. Conversions from floating-point types to integral types allow loss of
  148. precision (the fractional part of a floating-point number). The
  149. conversion is truncating towards zero, the same way a cast would
  150. truncate. (To round a floating point value when casting to an
  151. integral, use $(D_PARAM roundTo).)
  152. Examples:
  153. -------------------------
  154. int a = 420;
  155. auto b = to!long(a); // same as long b = a;
  156. auto c = to!byte(a / 10); // fine, c = 42
  157. auto d = to!byte(a); // throw ConvOverflowException
  158. double e = 4.2e6;
  159. auto f = to!int(e); // f == 4200000
  160. e = -3.14;
  161. auto g = to!uint(e); // fails: floating-to-integral negative overflow
  162. e = 3.14;
  163. auto h = to!uint(e); // h = 3
  164. e = 3.99;
  165. h = to!uint(a); // h = 3
  166. e = -3.99;
  167. f = to!int(a); // f = -3
  168. -------------------------
  169. Conversions from integral types to floating-point types always
  170. succeed, but might lose accuracy. The largest integers with a
  171. predecessor representable in floating-point format are 2^24-1 for
  172. float, 2^53-1 for double, and 2^64-1 for $(D_PARAM real) (when
  173. $(D_PARAM real) is 80-bit, e.g. on Intel machines).
  174. Example:
  175. -------------------------
  176. int a = 16_777_215; // 2^24 - 1, largest proper integer representable as float
  177. assert(to!int(to!float(a)) == a);
  178. assert(to!int(to!float(-a)) == -a);
  179. a += 2;
  180. assert(to!int(to!float(a)) == a); // fails!
  181. -------------------------
  182. Conversions from string to numeric types differ from the C equivalents
  183. $(D_PARAM atoi()) and $(D_PARAM atol()) by checking for overflow and
  184. not allowing whitespace.
  185. For conversion of strings to signed types, the grammar recognized is:
  186. <pre>
  187. $(I Integer): $(I Sign UnsignedInteger)
  188. $(I UnsignedInteger)
  189. $(I Sign):
  190. $(B +)
  191. $(B -)
  192. </pre>
  193. For conversion to unsigned types, the grammar recognized is:
  194. <pre>
  195. $(I UnsignedInteger):
  196. $(I DecimalDigit)
  197. $(I DecimalDigit) $(I UnsignedInteger)
  198. </pre>
  199. Converting an array to another array type works by converting each
  200. element in turn. Associative arrays can be converted to associative
  201. arrays as long as keys and values can in turn be converted.
  202. Example:
  203. -------------------------
  204. int[] a = ([1, 2, 3]).dup;
  205. auto b = to!(float[])(a);
  206. assert(b == [1.0f, 2, 3]);
  207. string str = "1 2 3 4 5 6";
  208. auto numbers = to!(double[])(split(str));
  209. assert(numbers == [1.0, 2, 3, 4, 5, 6]);
  210. int[string] c;
  211. c["a"] = 1;
  212. c["b"] = 2;
  213. auto d = to!(double[wstring])(c);
  214. assert(d["a"w] == 1 && d["b"w] == 2);
  215. -------------------------
  216. Conversions operate transitively, meaning that they work on arrays and
  217. associative arrays of any complexity:
  218. -------------------------
  219. int[string][double[int[]]] a;
  220. ...
  221. auto b = to!(short[wstring][string[double[]]])(a);
  222. -------------------------
  223. This conversion works because $(D_PARAM to!short) applies to an
  224. $(D_PARAM int), $(D_PARAM to!wstring) applies to a $(D_PARAM
  225. string), $(D_PARAM to!string) applies to a $(D_PARAM double), and
  226. $(D_PARAM to!(double[])) applies to an $(D_PARAM int[]). The
  227. conversion might throw an exception because $(D_PARAM to!short)
  228. might fail the range check.
  229. */
  230. /**
  231. Entry point that dispatches to the appropriate conversion
  232. primitive. Client code normally calls $(D _to!TargetType(value))
  233. (and not some variant of $(D toImpl)).
  234. */
  235. template to(T)
  236. {
  237. T to(A...)(A args)
  238. if (!isRawStaticArray!A)
  239. {
  240. return toImpl!T(args);
  241. }
  242. // Fix issue 6175
  243. T to(S)(ref S arg)
  244. if (isRawStaticArray!S)
  245. {
  246. return toImpl!T(arg);
  247. }
  248. }
  249. // Tests for issue 6175
  250. @safe pure unittest
  251. {
  252. char[9] sarr = "blablabla";
  253. auto darr = to!(char[])(sarr);
  254. assert(sarr.ptr == darr.ptr);
  255. assert(sarr.length == darr.length);
  256. }
  257. // Tests for issue 7348
  258. @safe pure unittest
  259. {
  260. assert(to!string(null) == "null");
  261. assert(text(null) == "null");
  262. }
  263. // Tests for issue 11390
  264. @safe pure unittest
  265. {
  266. const(typeof(null)) ctn;
  267. immutable(typeof(null)) itn;
  268. assert(to!string(ctn) == "null");
  269. assert(to!string(itn) == "null");
  270. }
  271. // Tests for issue 8729: do NOT skip leading WS
  272. @safe pure unittest
  273. {
  274. foreach (T; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong))
  275. {
  276. assertThrown!ConvException(to!T(" 0"));
  277. assertThrown!ConvException(to!T(" 0", 8));
  278. }
  279. foreach (T; TypeTuple!(float, double, real))
  280. {
  281. assertThrown!ConvException(to!T(" 0"));
  282. }
  283. assertThrown!ConvException(to!bool(" true"));
  284. alias NullType = typeof(null);
  285. assertThrown!ConvException(to!NullType(" null"));
  286. alias ARR = int[];
  287. assertThrown!ConvException(to!ARR(" [1]"));
  288. alias AA = int[int];
  289. assertThrown!ConvException(to!AA(" [1:1]"));
  290. }
  291. /**
  292. If the source type is implicitly convertible to the target type, $(D
  293. to) simply performs the implicit conversion.
  294. */
  295. T toImpl(T, S)(S value)
  296. if (isImplicitlyConvertible!(S, T) &&
  297. !isEnumStrToStr!(S, T) && !isNullToStr!(S, T))
  298. {
  299. template isSignedInt(T)
  300. {
  301. enum isSignedInt = isIntegral!T && isSigned!T;
  302. }
  303. alias isUnsignedInt = isUnsigned;
  304. // Conversion from integer to integer, and changing its sign
  305. static if (isUnsignedInt!S && isSignedInt!T && S.sizeof == T.sizeof)
  306. { // unsigned to signed & same size
  307. enforce(value <= cast(S)T.max,
  308. new ConvOverflowException("Conversion positive overflow"));
  309. }
  310. else static if (isSignedInt!S && isUnsignedInt!T)
  311. { // signed to unsigned
  312. enforce(0 <= value,
  313. new ConvOverflowException("Conversion negative overflow"));
  314. }
  315. return value;
  316. }
  317. @safe pure unittest
  318. {
  319. enum E { a } // Issue 9523 - Allow identity enum conversion
  320. auto e = to!E(E.a);
  321. assert(e == E.a);
  322. }
  323. @safe pure unittest
  324. {
  325. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  326. int a = 42;
  327. auto b = to!long(a);
  328. assert(a == b);
  329. }
  330. // Tests for issue 6377
  331. @safe pure unittest
  332. {
  333. // Conversion between same size
  334. foreach (S; TypeTuple!(byte, short, int, long))
  335. {
  336. alias Unsigned!S U;
  337. foreach (Sint; TypeTuple!(S, const S, immutable S))
  338. foreach (Uint; TypeTuple!(U, const U, immutable U))
  339. {
  340. // positive overflow
  341. Uint un = Uint.max;
  342. assertThrown!ConvOverflowException(to!Sint(un),
  343. text(Sint.stringof, ' ', Uint.stringof, ' ', un));
  344. // negative overflow
  345. Sint sn = -1;
  346. assertThrown!ConvOverflowException(to!Uint(sn),
  347. text(Sint.stringof, ' ', Uint.stringof, ' ', un));
  348. }
  349. }
  350. // Conversion between different size
  351. foreach (i, S1; TypeTuple!(byte, short, int, long))
  352. foreach ( S2; TypeTuple!(byte, short, int, long)[i+1..$])
  353. {
  354. alias Unsigned!S1 U1;
  355. alias Unsigned!S2 U2;
  356. static assert(U1.sizeof < S2.sizeof);
  357. // small unsigned to big signed
  358. foreach (Uint; TypeTuple!(U1, const U1, immutable U1))
  359. foreach (Sint; TypeTuple!(S2, const S2, immutable S2))
  360. {
  361. Uint un = Uint.max;
  362. assertNotThrown(to!Sint(un));
  363. assert(to!Sint(un) == un);
  364. }
  365. // big unsigned to small signed
  366. foreach (Uint; TypeTuple!(U2, const U2, immutable U2))
  367. foreach (Sint; TypeTuple!(S1, const S1, immutable S1))
  368. {
  369. Uint un = Uint.max;
  370. assertThrown(to!Sint(un));
  371. }
  372. static assert(S1.sizeof < U2.sizeof);
  373. // small signed to big unsigned
  374. foreach (Sint; TypeTuple!(S1, const S1, immutable S1))
  375. foreach (Uint; TypeTuple!(U2, const U2, immutable U2))
  376. {
  377. Sint sn = -1;
  378. assertThrown!ConvOverflowException(to!Uint(sn));
  379. }
  380. // big signed to small unsigned
  381. foreach (Sint; TypeTuple!(S2, const S2, immutable S2))
  382. foreach (Uint; TypeTuple!(U1, const U1, immutable U1))
  383. {
  384. Sint sn = -1;
  385. assertThrown!ConvOverflowException(to!Uint(sn));
  386. }
  387. }
  388. }
  389. /*
  390. Converting static arrays forwards to their dynamic counterparts.
  391. */
  392. T toImpl(T, S)(ref S s)
  393. if (isRawStaticArray!S)
  394. {
  395. return toImpl!(T, typeof(s[0])[])(s);
  396. }
  397. @safe pure unittest
  398. {
  399. char[4] test = ['a', 'b', 'c', 'd'];
  400. static assert(!isInputRange!(Unqual!(char[4])));
  401. assert(to!string(test) == test);
  402. }
  403. /**
  404. When source type supports member template function opCast, is is used.
  405. */
  406. T toImpl(T, S)(S value)
  407. if (!isImplicitlyConvertible!(S, T) &&
  408. is(typeof(S.init.opCast!T()) : T) &&
  409. !isExactSomeString!T)
  410. {
  411. return value.opCast!T();
  412. }
  413. @safe pure unittest
  414. {
  415. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  416. class B
  417. {
  418. T opCast(T)() { return 43; }
  419. }
  420. auto b = new B;
  421. assert(to!int(b) == 43);
  422. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  423. struct S
  424. {
  425. T opCast(T)() { return 43; }
  426. }
  427. auto s = S();
  428. assert(to!int(s) == 43);
  429. }
  430. /**
  431. When target type supports 'converting construction', it is used.
  432. $(UL $(LI If target type is struct, $(D T(value)) is used.)
  433. $(LI If target type is class, $(D new T(value)) is used.))
  434. */
  435. T toImpl(T, S)(S value)
  436. if (!isImplicitlyConvertible!(S, T) &&
  437. is(T == struct) && is(typeof(T(value))))
  438. {
  439. return T(value);
  440. }
  441. // Bugzilla 3961
  442. @safe pure unittest
  443. {
  444. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  445. struct Int
  446. {
  447. int x;
  448. }
  449. Int i = to!Int(1);
  450. static struct Int2
  451. {
  452. int x;
  453. this(int x) @safe pure { this.x = x; }
  454. }
  455. Int2 i2 = to!Int2(1);
  456. static struct Int3
  457. {
  458. int x;
  459. static Int3 opCall(int x) @safe pure
  460. {
  461. Int3 i;
  462. i.x = x;
  463. return i;
  464. }
  465. }
  466. Int3 i3 = to!Int3(1);
  467. }
  468. // Bugzilla 6808
  469. @safe pure unittest
  470. {
  471. static struct FakeBigInt
  472. {
  473. this(string s) @safe pure {}
  474. }
  475. string s = "101";
  476. auto i3 = to!FakeBigInt(s);
  477. }
  478. /// ditto
  479. T toImpl(T, S)(S value)
  480. if (!isImplicitlyConvertible!(S, T) &&
  481. is(T == class) && is(typeof(new T(value))))
  482. {
  483. return new T(value);
  484. }
  485. @safe pure unittest
  486. {
  487. static struct S
  488. {
  489. int x;
  490. }
  491. static class C
  492. {
  493. int x;
  494. this(int x) @safe pure { this.x = x; }
  495. }
  496. static class B
  497. {
  498. int value;
  499. this(S src) @safe pure { value = src.x; }
  500. this(C src) @safe pure { value = src.x; }
  501. }
  502. S s = S(1);
  503. auto b1 = to!B(s); // == new B(s)
  504. assert(b1.value == 1);
  505. C c = new C(2);
  506. auto b2 = to!B(c); // == new B(c)
  507. assert(b2.value == 2);
  508. auto c2 = to!C(3); // == new C(3)
  509. assert(c2.x == 3);
  510. }
  511. @safe pure unittest
  512. {
  513. struct S
  514. {
  515. class A
  516. {
  517. this(B b) @safe pure {}
  518. }
  519. class B : A
  520. {
  521. this() @safe pure { super(this); }
  522. }
  523. }
  524. S.B b = new S.B();
  525. S.A a = to!(S.A)(b); // == cast(S.A)b
  526. // (do not run construction conversion like new S.A(b))
  527. assert(b is a);
  528. static class C : Object
  529. {
  530. this() @safe pure {}
  531. this(Object o) @safe pure {}
  532. }
  533. Object oc = new C();
  534. C a2 = to!C(oc); // == new C(a)
  535. // Construction conversion overrides down-casting conversion
  536. assert(a2 !is a); //
  537. }
  538. /**
  539. Object-to-object conversions by dynamic casting throw exception when the source is
  540. non-null and the target is null.
  541. */
  542. T toImpl(T, S)(S value)
  543. if (!isImplicitlyConvertible!(S, T) &&
  544. (is(S == class) || is(S == interface)) && !is(typeof(value.opCast!T()) : T) &&
  545. (is(T == class) || is(T == interface)) && !is(typeof(new T(value))))
  546. {
  547. static if (is(T == immutable))
  548. {
  549. // immutable <- immutable
  550. enum isModConvertible = is(S == immutable);
  551. }
  552. else static if (is(T == const))
  553. {
  554. static if (is(T == shared))
  555. {
  556. // shared const <- shared
  557. // shared const <- shared const
  558. // shared const <- immutable
  559. enum isModConvertible = is(S == shared) || is(S == immutable);
  560. }
  561. else
  562. {
  563. // const <- mutable
  564. // const <- immutable
  565. enum isModConvertible = !is(S == shared);
  566. }
  567. }
  568. else
  569. {
  570. static if (is(T == shared))
  571. {
  572. // shared <- shared mutable
  573. enum isModConvertible = is(S == shared) && !is(S == const);
  574. }
  575. else
  576. {
  577. // (mutable) <- (mutable)
  578. enum isModConvertible = is(Unqual!S == S);
  579. }
  580. }
  581. static assert(isModConvertible, "Bad modifier conversion: "~S.stringof~" to "~T.stringof);
  582. auto result = ()@trusted{ return cast(T) value; }();
  583. if (!result && value)
  584. {
  585. throw new ConvException("Cannot convert object of static type "
  586. ~S.classinfo.name~" and dynamic type "~value.classinfo.name
  587. ~" to type "~T.classinfo.name);
  588. }
  589. return result;
  590. }
  591. @safe pure unittest
  592. {
  593. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  594. // Testing object conversions
  595. class A {}
  596. class B : A {}
  597. class C : A {}
  598. A a1 = new A, a2 = new B, a3 = new C;
  599. assert(to!B(a2) is a2);
  600. assert(to!C(a3) is a3);
  601. assertThrown!ConvException(to!B(a3));
  602. }
  603. // Unittest for 6288
  604. @safe pure unittest
  605. {
  606. template Identity(T) { alias T Identity; }
  607. template toConst(T) { alias const(T) toConst; }
  608. template toShared(T) { alias shared(T) toShared; }
  609. template toSharedConst(T) { alias shared(const(T)) toSharedConst; }
  610. template toImmutable(T) { alias immutable(T) toImmutable; }
  611. template AddModifier(int n) if (0 <= n && n < 5)
  612. {
  613. static if (n == 0) alias Identity AddModifier;
  614. else static if (n == 1) alias toConst AddModifier;
  615. else static if (n == 2) alias toShared AddModifier;
  616. else static if (n == 3) alias toSharedConst AddModifier;
  617. else static if (n == 4) alias toImmutable AddModifier;
  618. }
  619. interface I {}
  620. interface J {}
  621. class A {}
  622. class B : A {}
  623. class C : B, I, J {}
  624. class D : I {}
  625. foreach (m1; TypeTuple!(0,1,2,3,4)) // enumerate modifiers
  626. foreach (m2; TypeTuple!(0,1,2,3,4)) // ditto
  627. {
  628. alias AddModifier!m1 srcmod;
  629. alias AddModifier!m2 tgtmod;
  630. //pragma(msg, srcmod!Object, " -> ", tgtmod!Object, ", convertible = ",
  631. // isImplicitlyConvertible!(srcmod!Object, tgtmod!Object));
  632. // Compile time convertible equals to modifier convertible.
  633. static if (isImplicitlyConvertible!(srcmod!Object, tgtmod!Object))
  634. {
  635. // Test runtime conversions: class to class, class to interface,
  636. // interface to class, and interface to interface
  637. // Check that the runtime conversion to succeed
  638. srcmod!A ac = new srcmod!C();
  639. srcmod!I ic = new srcmod!C();
  640. assert(to!(tgtmod!C)(ac) !is null); // A(c) to C
  641. assert(to!(tgtmod!I)(ac) !is null); // A(c) to I
  642. assert(to!(tgtmod!C)(ic) !is null); // I(c) to C
  643. assert(to!(tgtmod!J)(ic) !is null); // I(c) to J
  644. // Check that the runtime conversion fails
  645. srcmod!A ab = new srcmod!B();
  646. srcmod!I id = new srcmod!D();
  647. assertThrown(to!(tgtmod!C)(ab)); // A(b) to C
  648. assertThrown(to!(tgtmod!I)(ab)); // A(b) to I
  649. assertThrown(to!(tgtmod!C)(id)); // I(d) to C
  650. assertThrown(to!(tgtmod!J)(id)); // I(d) to J
  651. }
  652. else
  653. {
  654. // Check that the conversion is rejected statically
  655. static assert(!is(typeof(to!(tgtmod!C)(srcmod!A.init)))); // A to C
  656. static assert(!is(typeof(to!(tgtmod!I)(srcmod!A.init)))); // A to I
  657. static assert(!is(typeof(to!(tgtmod!C)(srcmod!I.init)))); // I to C
  658. static assert(!is(typeof(to!(tgtmod!J)(srcmod!I.init)))); // I to J
  659. }
  660. }
  661. }
  662. /**
  663. Stringize conversion from all types is supported.
  664. $(UL
  665. $(LI String _to string conversion works for any two string types having
  666. ($(D char), $(D wchar), $(D dchar)) character widths and any
  667. combination of qualifiers (mutable, $(D const), or $(D immutable)).)
  668. $(LI Converts array (other than strings) to string.
  669. Each element is converted by calling $(D to!T).)
  670. $(LI Associative array to string conversion.
  671. Each element is printed by calling $(D to!T).)
  672. $(LI Object to string conversion calls $(D toString) against the object or
  673. returns $(D "null") if the object is null.)
  674. $(LI Struct to string conversion calls $(D toString) against the struct if
  675. it is defined.)
  676. $(LI For structs that do not define $(D toString), the conversion to string
  677. produces the list of fields.)
  678. $(LI Enumerated types are converted to strings as their symbolic names.)
  679. $(LI Boolean values are printed as $(D "true") or $(D "false").)
  680. $(LI $(D char), $(D wchar), $(D dchar) to a string type.)
  681. $(LI Unsigned or signed integers to strings.
  682. $(DL $(DT [special case])
  683. $(DD Convert integral value to string in $(D_PARAM radix) radix.
  684. radix must be a value from 2 to 36.
  685. value is treated as a signed value only if radix is 10.
  686. The characters A through Z are used to represent values 10 through 36
  687. and their case is determined by the $(D_PARAM letterCase) parameter.)))
  688. $(LI All floating point types to all string types.)
  689. $(LI Pointer to string conversions prints the pointer as a $(D size_t) value.
  690. If pointer is $(D char*), treat it as C-style strings.
  691. In that case, this function is $(D @system).))
  692. */
  693. T toImpl(T, S)(S value)
  694. if (!(isImplicitlyConvertible!(S, T) &&
  695. !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
  696. isExactSomeString!T)
  697. {
  698. static if (isExactSomeString!S && value[0].sizeof == ElementEncodingType!T.sizeof)
  699. {
  700. // string-to-string with incompatible qualifier conversion
  701. static if (is(ElementEncodingType!T == immutable))
  702. {
  703. // conversion (mutable|const) -> immutable
  704. return value.idup;
  705. }
  706. else
  707. {
  708. // conversion (immutable|const) -> mutable
  709. return value.dup;
  710. }
  711. }
  712. else static if (isExactSomeString!S)
  713. {
  714. // other string-to-string
  715. //Use Appender directly instead of toStr, which also uses a formatedWrite
  716. auto w = appender!T();
  717. w.put(value);
  718. return w.data;
  719. }
  720. else static if (isIntegral!S && !is(S == enum))
  721. {
  722. // other integral-to-string conversions with default radix
  723. return toImpl!(T, S)(value, 10);
  724. }
  725. else static if (is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[]))
  726. {
  727. // Converting void array to string
  728. alias Unqual!(ElementEncodingType!T) Char;
  729. auto raw = cast(const(ubyte)[]) value;
  730. enforce(raw.length % Char.sizeof == 0,
  731. new ConvException("Alignment mismatch in converting a "
  732. ~ S.stringof ~ " to a "
  733. ~ T.stringof));
  734. auto result = new Char[raw.length / Char.sizeof];
  735. ()@trusted{ memcpy(result.ptr, value.ptr, value.length); }();
  736. return cast(T) result;
  737. }
  738. else static if (isPointer!S && is(S : const(char)*))
  739. {
  740. // It is unsafe because we cannot guarantee that the pointer is null terminated.
  741. return value ? cast(T) value[0 .. strlen(value)].dup : cast(string)null;
  742. }
  743. else static if (isSomeString!T && is(S == enum))
  744. {
  745. static if (isSwitchable!(OriginalType!S) && EnumMembers!S.length <= 50)
  746. {
  747. switch(value)
  748. {
  749. foreach (I, member; NoDuplicates!(EnumMembers!S))
  750. {
  751. case member:
  752. return to!T(enumRep!(immutable(T), S, I));
  753. }
  754. default:
  755. }
  756. }
  757. else
  758. {
  759. foreach (I, member; EnumMembers!S)
  760. {
  761. if (value == member)
  762. return to!T(enumRep!(immutable(T), S, I));
  763. }
  764. }
  765. import std.format : FormatSpec, formatValue;
  766. //Default case, delegate to format
  767. //Note: we don't call toStr directly, to avoid duplicate work.
  768. auto app = appender!T();
  769. app.put("cast(");
  770. app.put(S.stringof);
  771. app.put(')');
  772. FormatSpec!char f;
  773. formatValue(app, cast(OriginalType!S)value, f);
  774. return app.data;
  775. }
  776. else
  777. {
  778. // other non-string values runs formatting
  779. return toStr!T(value);
  780. }
  781. }
  782. /*
  783. Check whether type $(D T) can be used in a switch statement.
  784. This is useful for compile-time generation of switch case statements.
  785. */
  786. private template isSwitchable(E)
  787. {
  788. enum bool isSwitchable = is(typeof({
  789. switch (E.init) { default: }
  790. }));
  791. }
  792. //
  793. unittest
  794. {
  795. static assert(isSwitchable!int);
  796. static assert(!isSwitchable!double);
  797. static assert(!isSwitchable!real);
  798. }
  799. //Static representation of the index I of the enum S,
  800. //In representation T.
  801. //T must be an immutable string (avoids un-necessary initializations).
  802. private template enumRep(T, S, size_t I)
  803. if (is (T == immutable) && isExactSomeString!T && is(S == enum))
  804. {
  805. static T enumRep = to!T(__traits(allMembers, S)[I]);
  806. }
  807. @safe pure unittest
  808. {
  809. void dg()
  810. {
  811. // string to string conversion
  812. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  813. alias TypeTuple!(char, wchar, dchar) Chars;
  814. foreach (LhsC; Chars)
  815. {
  816. alias TypeTuple!(LhsC[], const(LhsC)[], immutable(LhsC)[]) LhStrings;
  817. foreach (Lhs; LhStrings)
  818. {
  819. foreach (RhsC; Chars)
  820. {
  821. alias TypeTuple!(RhsC[], const(RhsC)[], immutable(RhsC)[])
  822. RhStrings;
  823. foreach (Rhs; RhStrings)
  824. {
  825. Lhs s1 = to!Lhs("wyda");
  826. Rhs s2 = to!Rhs(s1);
  827. //writeln(Lhs.stringof, " -> ", Rhs.stringof);
  828. assert(s1 == to!Lhs(s2));
  829. }
  830. }
  831. }
  832. }
  833. foreach (T; Chars)
  834. {
  835. foreach (U; Chars)
  836. {
  837. T[] s1 = to!(T[])("Hello, world!");
  838. auto s2 = to!(U[])(s1);
  839. assert(s1 == to!(T[])(s2));
  840. auto s3 = to!(const(U)[])(s1);
  841. assert(s1 == to!(T[])(s3));
  842. auto s4 = to!(immutable(U)[])(s1);
  843. assert(s1 == to!(T[])(s4));
  844. }
  845. }
  846. }
  847. dg();
  848. assertCTFEable!dg;
  849. }
  850. @safe pure unittest
  851. {
  852. // Conversion reinterpreting void array to string
  853. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  854. auto a = "abcx"w;
  855. const(void)[] b = a;
  856. assert(b.length == 8);
  857. auto c = to!(wchar[])(b);
  858. assert(c == "abcx");
  859. }
  860. @system pure unittest
  861. {
  862. // char* to string conversion
  863. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  864. debug(conv) printf("string.to!string(char*).unittest\n");
  865. assert(to!string(cast(char*) null) == "");
  866. assert(to!string("foo\0".ptr) == "foo");
  867. }
  868. @safe pure unittest
  869. {
  870. // Conversion representing bool value with string
  871. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  872. bool b;
  873. assert(to!string(b) == "false");
  874. b = true;
  875. assert(to!string(b) == "true");
  876. }
  877. @safe pure unittest
  878. {
  879. // Conversion representing character value with string
  880. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  881. alias TypeTuple!(
  882. char, const( char), immutable( char),
  883. wchar, const(wchar), immutable(wchar),
  884. dchar, const(dchar), immutable(dchar)) AllChars;
  885. foreach (Char1; AllChars)
  886. {
  887. foreach (Char2; AllChars)
  888. {
  889. Char1 c = 'a';
  890. assert(to!(Char2[])(c)[0] == c);
  891. }
  892. uint x = 4;
  893. assert(to!(Char1[])(x) == "4");
  894. }
  895. string s = "foo";
  896. string s2;
  897. foreach (char c; s)
  898. {
  899. s2 ~= to!string(c);
  900. }
  901. //printf("%.*s", s2);
  902. assert(s2 == "foo");
  903. }
  904. @safe pure unittest
  905. {
  906. // Conversion representing integer values with string
  907. foreach (Int; TypeTuple!(ubyte, ushort, uint, ulong))
  908. {
  909. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  910. debug(conv) printf("string.to!string(%.*s).unittest\n", Int.stringof.length, Int.stringof.ptr);
  911. assert(to!string(to!Int(0)) == "0");
  912. assert(to!string(to!Int(9)) == "9");
  913. assert(to!string(to!Int(123)) == "123");
  914. }
  915. foreach (Int; TypeTuple!(byte, short, int, long))
  916. {
  917. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  918. debug(conv) printf("string.to!string(%.*s).unittest\n", Int.stringof.length, Int.stringof.ptr);
  919. assert(to!string(to!Int(0)) == "0");
  920. assert(to!string(to!Int(9)) == "9");
  921. assert(to!string(to!Int(123)) == "123");
  922. assert(to!string(to!Int(-0)) == "0");
  923. assert(to!string(to!Int(-9)) == "-9");
  924. assert(to!string(to!Int(-123)) == "-123");
  925. assert(to!string(to!(const Int)(6)) == "6");
  926. }
  927. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  928. assert(wtext(int.max) == "2147483647"w);
  929. assert(wtext(int.min) == "-2147483648"w);
  930. assert(to!string(0L) == "0");
  931. assertCTFEable!(
  932. {
  933. assert(to!string(1uL << 62) == "4611686018427387904");
  934. assert(to!string(0x100000000) == "4294967296");
  935. assert(to!string(-138L) == "-138");
  936. });
  937. }
  938. @safe pure unittest
  939. {
  940. // Conversion representing dynamic/static array with string
  941. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  942. long[] b = [ 1, 3, 5 ];
  943. auto s = to!string(b);
  944. assert(to!string(b) == "[1, 3, 5]", s);
  945. }
  946. /*@safe pure */unittest // sprintf issue
  947. {
  948. double[2] a = [ 1.5, 2.5 ];
  949. assert(to!string(a) == "[1.5, 2.5]");
  950. }
  951. /*@safe pure */unittest
  952. {
  953. // Conversion representing associative array with string
  954. int[string] a = ["0":1, "1":2];
  955. assert(to!string(a) == `["0":1, "1":2]`);
  956. }
  957. unittest
  958. {
  959. // Conversion representing class object with string
  960. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  961. class A
  962. {
  963. override string toString() const { return "an A"; }
  964. }
  965. A a;
  966. assert(to!string(a) == "null");
  967. a = new A;
  968. assert(to!string(a) == "an A");
  969. // Bug 7660
  970. class C { override string toString() const { return "C"; } }
  971. struct S { C c; alias c this; }
  972. S s; s.c = new C();
  973. assert(to!string(s) == "C");
  974. }
  975. unittest
  976. {
  977. // Conversion representing struct object with string
  978. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  979. struct S1
  980. {
  981. string toString() { return "wyda"; }
  982. }
  983. assert(to!string(S1()) == "wyda");
  984. struct S2
  985. {
  986. int a = 42;
  987. float b = 43.5;
  988. }
  989. S2 s2;
  990. assert(to!string(s2) == "S2(42, 43.5)");
  991. // Test for issue 8080
  992. struct S8080
  993. {
  994. short[4] data;
  995. alias data this;
  996. string toString() { return "<S>"; }
  997. }
  998. S8080 s8080;
  999. assert(to!string(s8080) == "<S>");
  1000. }
  1001. unittest
  1002. {
  1003. // Conversion representing enum value with string
  1004. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1005. enum EB : bool { a = true }
  1006. enum EU : uint { a = 0, b = 1, c = 2 } // base type is unsigned
  1007. enum EI : int { a = -1, b = 0, c = 1 } // base type is signed (bug 7909)
  1008. enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
  1009. enum EC : char { a = 'x', b = 'y' }
  1010. enum ES : string { a = "aaa", b = "bbb" }
  1011. foreach (E; TypeTuple!(EB, EU, EI, EF, EC, ES))
  1012. {
  1013. assert(to! string(E.a) == "a"c);
  1014. assert(to!wstring(E.a) == "a"w);
  1015. assert(to!dstring(E.a) == "a"d);
  1016. }
  1017. // Test an value not corresponding to an enum member.
  1018. auto o = cast(EU)5;
  1019. assert(to! string(o) == "cast(EU)5"c);
  1020. assert(to!wstring(o) == "cast(EU)5"w);
  1021. assert(to!dstring(o) == "cast(EU)5"d);
  1022. }
  1023. unittest
  1024. {
  1025. enum E
  1026. {
  1027. foo,
  1028. bar,
  1029. doo = foo, // check duplicate switch statements
  1030. }
  1031. foreach (S; TypeTuple!(string, wstring, dstring, const(char[]), const(wchar[]), const(dchar[])))
  1032. {
  1033. auto s1 = to!S(E.foo);
  1034. auto s2 = to!S(E.foo);
  1035. assert(s1 == s2);
  1036. // ensure we don't allocate when it's unnecessary
  1037. assert(s1 is s2);
  1038. }
  1039. foreach (S; TypeTuple!(char[], wchar[], dchar[]))
  1040. {
  1041. auto s1 = to!S(E.foo);
  1042. auto s2 = to!S(E.foo);
  1043. assert(s1 == s2);
  1044. // ensure each mutable array is unique
  1045. assert(s1 !is s2);
  1046. }
  1047. }
  1048. /// ditto
  1049. @trusted pure T toImpl(T, S)(S value, uint radix, LetterCase letterCase = LetterCase.upper)
  1050. if (isIntegral!S &&
  1051. isExactSomeString!T)
  1052. in
  1053. {
  1054. assert(radix >= 2 && radix <= 36);
  1055. }
  1056. body
  1057. {
  1058. alias EEType = Unqual!(ElementEncodingType!T);
  1059. T toStringRadixConvert(size_t bufLen, uint radix = 0, bool neg = false)(uint runtimeRadix = 0)
  1060. {
  1061. static if (neg)
  1062. ulong div = void, mValue = unsigned(-value);
  1063. else
  1064. Unsigned!(Unqual!S) div = void, mValue = unsigned(value);
  1065. size_t index = bufLen;
  1066. EEType[bufLen] buffer = void;
  1067. char baseChar = letterCase == LetterCase.lower ? 'a' : 'A';
  1068. char mod = void;
  1069. do
  1070. {
  1071. static if (radix == 0)
  1072. {
  1073. div = cast(S)(mValue / runtimeRadix );
  1074. mod = cast(ubyte)(mValue % runtimeRadix);
  1075. mod += mod < 10 ? '0' : baseChar - 10;
  1076. }
  1077. else static if (radix > 10)
  1078. {
  1079. div = cast(S)(mValue / radix );
  1080. mod = cast(ubyte)(mValue % radix);
  1081. mod += mod < 10 ? '0' : baseChar - 10;
  1082. }
  1083. else
  1084. {
  1085. div = cast(S)(mValue / radix);
  1086. mod = mValue % radix + '0';
  1087. }
  1088. buffer[--index] = cast(char)mod;
  1089. mValue = div;
  1090. } while (mValue);
  1091. static if (neg)
  1092. {
  1093. buffer[--index] = '-';
  1094. }
  1095. return cast(T)buffer[index .. $].dup;
  1096. }
  1097. enforce(radix >= 2 && radix <= 36, new ConvException("Radix error"));
  1098. switch(radix)
  1099. {
  1100. case 10:
  1101. if (value < 0)
  1102. return toStringRadixConvert!(S.sizeof * 3 + 1, 10, true)();
  1103. else
  1104. return toStringRadixConvert!(S.sizeof * 3, 10)();
  1105. case 16:
  1106. return toStringRadixConvert!(S.sizeof * 2, 16)();
  1107. case 2:
  1108. return toStringRadixConvert!(S.sizeof * 8, 2)();
  1109. case 8:
  1110. return toStringRadixConvert!(S.sizeof * 3, 8)();
  1111. default:
  1112. return toStringRadixConvert!(S.sizeof * 6)(radix);
  1113. }
  1114. }
  1115. @safe pure unittest
  1116. {
  1117. foreach (Int; TypeTuple!(uint, ulong))
  1118. {
  1119. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1120. debug(conv) printf("string.to!string(%.*s, uint).unittest\n", Int.stringof.length, Int.stringof.ptr);
  1121. assert(to!string(to!Int(16), 16) == "10");
  1122. assert(to!string(to!Int(15), 2u) == "1111");
  1123. assert(to!string(to!Int(1), 2u) == "1");
  1124. assert(to!string(to!Int(0x1234AF), 16u) == "1234AF");
  1125. assert(to!string(to!Int(0x1234BCD), 16u, LetterCase.upper) == "1234BCD");
  1126. assert(to!string(to!Int(0x1234AF), 16u, LetterCase.lower) == "1234af");
  1127. }
  1128. foreach (Int; TypeTuple!(int, long))
  1129. {
  1130. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1131. debug(conv) printf("string.to!string(%.*s, uint).unittest\n", Int.stringof.length, Int.stringof.ptr);
  1132. assert(to!string(to!Int(-10), 10u) == "-10");
  1133. }
  1134. assert(to!string(cast(byte)-10, 16) == "F6");
  1135. assert(to!string(long.min) == "-9223372036854775808");
  1136. assert(to!string(long.max) == "9223372036854775807");
  1137. }
  1138. /**
  1139. Narrowing numeric-numeric conversions throw when the value does not
  1140. fit in the narrower type.
  1141. */
  1142. T toImpl(T, S)(S value)
  1143. if (!isImplicitlyConvertible!(S, T) &&
  1144. (isNumeric!S || isSomeChar!S || isBoolean!S) &&
  1145. (isNumeric!T || isSomeChar!T || isBoolean!T) && !is(T == enum))
  1146. {
  1147. enum sSmallest = mostNegative!S;
  1148. enum tSmallest = mostNegative!T;
  1149. static if (sSmallest < 0)
  1150. {
  1151. // possible underflow converting from a signed
  1152. static if (tSmallest == 0)
  1153. {
  1154. immutable good = value >= 0;
  1155. }
  1156. else
  1157. {
  1158. static assert(tSmallest < 0);
  1159. immutable good = value >= tSmallest;
  1160. }
  1161. if (!good)
  1162. throw new ConvOverflowException("Conversion negative overflow");
  1163. }
  1164. static if (S.max > T.max)
  1165. {
  1166. // possible overflow
  1167. if (value > T.max)
  1168. throw new ConvOverflowException("Conversion positive overflow");
  1169. }
  1170. return (ref value)@trusted{ return cast(T) value; }(value);
  1171. }
  1172. @safe pure unittest
  1173. {
  1174. dchar a = ' ';
  1175. assert(to!char(a) == ' ');
  1176. a = 300;
  1177. assert(collectException(to!char(a)));
  1178. dchar from0 = 'A';
  1179. char to0 = to!char(from0);
  1180. wchar from1 = 'A';
  1181. char to1 = to!char(from1);
  1182. char from2 = 'A';
  1183. char to2 = to!char(from2);
  1184. char from3 = 'A';
  1185. wchar to3 = to!wchar(from3);
  1186. char from4 = 'A';
  1187. dchar to4 = to!dchar(from4);
  1188. }
  1189. unittest
  1190. {
  1191. // Narrowing conversions from enum -> integral should be allowed, but they
  1192. // should throw at runtime if the enum value doesn't fit in the target
  1193. // type.
  1194. enum E1 : ulong { A = 1, B = 1UL<<48, C = 0 }
  1195. assert(to!int(E1.A) == 1);
  1196. assert(to!bool(E1.A) == true);
  1197. assertThrown!ConvOverflowException(to!int(E1.B)); // E1.B overflows int
  1198. assertThrown!ConvOverflowException(to!bool(E1.B)); // E1.B overflows bool
  1199. assert(to!bool(E1.C) == false);
  1200. enum E2 : long { A = -1L<<48, B = -1<<31, C = 1<<31 }
  1201. assertThrown!ConvOverflowException(to!int(E2.A)); // E2.A overflows int
  1202. assertThrown!ConvOverflowException(to!uint(E2.B)); // E2.B overflows uint
  1203. assert(to!int(E2.B) == -1<<31); // but does not overflow int
  1204. assert(to!int(E2.C) == 1<<31); // E2.C does not overflow int
  1205. enum E3 : int { A = -1, B = 1, C = 255, D = 0 }
  1206. assertThrown!ConvOverflowException(to!ubyte(E3.A));
  1207. assertThrown!ConvOverflowException(to!bool(E3.A));
  1208. assert(to!byte(E3.A) == -1);
  1209. assert(to!byte(E3.B) == 1);
  1210. assert(to!ubyte(E3.C) == 255);
  1211. assert(to!bool(E3.B) == true);
  1212. assertThrown!ConvOverflowException(to!byte(E3.C));
  1213. assertThrown!ConvOverflowException(to!bool(E3.C));
  1214. assert(to!bool(E3.D) == false);
  1215. }
  1216. /**
  1217. Array-to-array conversion (except when target is a string type)
  1218. converts each element in turn by using $(D to).
  1219. */
  1220. T toImpl(T, S)(S value)
  1221. if (!isImplicitlyConvertible!(S, T) &&
  1222. !isSomeString!S && isDynamicArray!S &&
  1223. !isExactSomeString!T && isArray!T)
  1224. {
  1225. alias E = typeof(T.init[0]);
  1226. auto w = appender!(E[])();
  1227. w.reserve(value.length);
  1228. foreach (i, ref e; value)
  1229. {
  1230. w.put(to!E(e));
  1231. }
  1232. return w.data;
  1233. }
  1234. @safe pure unittest
  1235. {
  1236. // array to array conversions
  1237. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1238. uint[] a = ([ 1u, 2, 3 ]).dup;
  1239. auto b = to!(float[])(a);
  1240. assert(b == [ 1.0f, 2, 3 ]);
  1241. //auto c = to!(string[])(b);
  1242. //assert(c[0] == "1" && c[1] == "2" && c[2] == "3");
  1243. immutable(int)[3] d = [ 1, 2, 3 ];
  1244. b = to!(float[])(d);
  1245. assert(b == [ 1.0f, 2, 3 ]);
  1246. uint[][] e = [ a, a ];
  1247. auto f = to!(float[][])(e);
  1248. assert(f[0] == b && f[1] == b);
  1249. // Test for bug 8264
  1250. struct Wrap
  1251. {
  1252. string wrap;
  1253. alias wrap this;
  1254. }
  1255. Wrap[] warr = to!(Wrap[])(["foo", "bar"]); // should work
  1256. }
  1257. /*@safe pure */unittest
  1258. {
  1259. auto b = [ 1.0f, 2, 3 ];
  1260. auto c = to!(string[])(b);
  1261. assert(c[0] == "1" && c[1] == "2" && c[2] == "3");
  1262. }
  1263. /**
  1264. Associative array to associative array conversion converts each key
  1265. and each value in turn.
  1266. */
  1267. T toImpl(T, S)(S value)
  1268. if (isAssociativeArray!S &&
  1269. isAssociativeArray!T && !is(T == enum))
  1270. {
  1271. /* This code is potentially unsafe.
  1272. */
  1273. alias KeyType!T K2;
  1274. alias ValueType!T V2;
  1275. // While we are "building" the AA, we need to unqualify its values, and only re-qualify at the end
  1276. Unqual!V2[K2] result;
  1277. foreach (k1, v1; value)
  1278. {
  1279. // Cast values temporarily to Unqual!V2 to store them to result variable
  1280. result[to!K2(k1)] = cast(Unqual!V2) to!V2(v1);
  1281. }
  1282. // Cast back to original type
  1283. return cast(T)result;
  1284. }
  1285. @safe /*pure */unittest
  1286. {
  1287. // hash to hash conversions
  1288. int[string] a;
  1289. a["0"] = 1;
  1290. a["1"] = 2;
  1291. auto b = to!(double[dstring])(a);
  1292. assert(b["0"d] == 1 && b["1"d] == 2);
  1293. }
  1294. @safe /*pure */unittest // Bugzilla 8705, from doc
  1295. {
  1296. int[string][double[int[]]] a;
  1297. auto b = to!(short[wstring][string[double[]]])(a);
  1298. a = [null:["hello":int.max]];
  1299. assertThrown!ConvOverflowException(to!(short[wstring][string[double[]]])(a));
  1300. }
  1301. version(none) // masked by unexpected linker error in posix platforms
  1302. unittest // Extra cases for AA with qualifiers conversion
  1303. {
  1304. int[][int[]] a;// = [[], []];
  1305. auto b = to!(immutable(short[])[immutable short[]])(a);
  1306. double[dstring][int[long[]]] c;
  1307. auto d = to!(immutable(short[immutable wstring])[immutable string[double[]]])(c);
  1308. }
  1309. private void testIntegralToFloating(Integral, Floating)()
  1310. {
  1311. Integral a = 42;
  1312. auto b = to!Floating(a);
  1313. assert(a == b);
  1314. assert(a == to!Integral(b));
  1315. }
  1316. private void testFloatingToIntegral(Floating, Integral)()
  1317. {
  1318. bool convFails(Source, Target, E)(Source src)
  1319. {
  1320. try
  1321. auto t = to!Target(src);
  1322. catch (E)
  1323. return true;
  1324. return false;
  1325. }
  1326. // convert some value
  1327. Floating a = 4.2e1;
  1328. auto b = to!Integral(a);
  1329. assert(is(typeof(b) == Integral) && b == 42);
  1330. // convert some negative value (if applicable)
  1331. a = -4.2e1;
  1332. static if (Integral.min < 0)
  1333. {
  1334. b = to!Integral(a);
  1335. assert(is(typeof(b) == Integral) && b == -42);
  1336. }
  1337. else
  1338. {
  1339. // no go for unsigned types
  1340. assert(convFails!(Floating, Integral, ConvOverflowException)(a));
  1341. }
  1342. // convert to the smallest integral value
  1343. a = 0.0 + Integral.min;
  1344. static if (Integral.min < 0)
  1345. {
  1346. a = -a; // -Integral.min not representable as an Integral
  1347. assert(convFails!(Floating, Integral, ConvOverflowException)(a)
  1348. || Floating.sizeof <= Integral.sizeof);
  1349. }
  1350. a = 0.0 + Integral.min;
  1351. assert(to!Integral(a) == Integral.min);
  1352. --a; // no more representable as an Integral
  1353. assert(convFails!(Floating, Integral, ConvOverflowException)(a)
  1354. || Floating.sizeof <= Integral.sizeof);
  1355. a = 0.0 + Integral.max;
  1356. // fwritefln(stderr, "%s a=%g, %s conv=%s", Floating.stringof, a,
  1357. // Integral.stringof, to!Integral(a));
  1358. assert(to!Integral(a) == Integral.max || Floating.sizeof <= Integral.sizeof);
  1359. ++a; // no more representable as an Integral
  1360. assert(convFails!(Floating, Integral, ConvOverflowException)(a)
  1361. || Floating.sizeof <= Integral.sizeof);
  1362. // convert a value with a fractional part
  1363. a = 3.14;
  1364. assert(to!Integral(a) == 3);
  1365. a = 3.99;
  1366. assert(to!Integral(a) == 3);
  1367. static if (Integral.min < 0)
  1368. {
  1369. a = -3.14;
  1370. assert(to!Integral(a) == -3);
  1371. a = -3.99;
  1372. assert(to!Integral(a) == -3);
  1373. }
  1374. }
  1375. @safe pure unittest
  1376. {
  1377. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1378. alias AllInts = TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong);
  1379. alias AllFloats = TypeTuple!(float, double, real);
  1380. alias AllNumerics = TypeTuple!(AllInts, AllFloats);
  1381. // test with same type
  1382. {
  1383. foreach (T; AllNumerics)
  1384. {
  1385. T a = 42;
  1386. auto b = to!T(a);
  1387. assert(is(typeof(a) == typeof(b)) && a == b);
  1388. }
  1389. }
  1390. // test that floating-point numbers convert properly to largest ints
  1391. // see http://oregonstate.edu/~peterseb/mth351/docs/351s2001_fp80x87.html
  1392. // look for "largest fp integer with a predecessor"
  1393. {
  1394. // float
  1395. int a = 16_777_215; // 2^24 - 1
  1396. assert(to!int(to!float(a)) == a);
  1397. assert(to!int(to!float(-a)) == -a);
  1398. // double
  1399. long b = 9_007_199_254_740_991; // 2^53 - 1
  1400. assert(to!long(to!double(b)) == b);
  1401. assert(to!long(to!double(-b)) == -b);
  1402. // real
  1403. // @@@ BUG IN COMPILER @@@
  1404. // ulong c = 18_446_744_073_709_551_615UL; // 2^64 - 1
  1405. // assert(to!ulong(to!real(c)) == c);
  1406. // assert(to!ulong(-to!real(c)) == c);
  1407. }
  1408. // test conversions floating => integral
  1409. {
  1410. // AllInts[0 .. $ - 1] should be AllInts
  1411. // @@@ BUG IN COMPILER @@@
  1412. foreach (Integral; AllInts[0 .. $ - 1])
  1413. {
  1414. foreach (Floating; AllFloats)
  1415. {
  1416. testFloatingToIntegral!(Floating, Integral)();
  1417. }
  1418. }
  1419. }
  1420. // test conversion integral => floating
  1421. {
  1422. foreach (Integral; AllInts[0 .. $ - 1])
  1423. {
  1424. foreach (Floating; AllFloats)
  1425. {
  1426. testIntegralToFloating!(Integral, Floating)();
  1427. }
  1428. }
  1429. }
  1430. // test parsing
  1431. {
  1432. foreach (T; AllNumerics)
  1433. {
  1434. // from type immutable(char)[2]
  1435. auto a = to!T("42");
  1436. assert(a == 42);
  1437. // from type char[]
  1438. char[] s1 = "42".dup;
  1439. a = to!T(s1);
  1440. assert(a == 42);
  1441. // from type char[2]
  1442. char[2] s2;
  1443. s2[] = "42";
  1444. a = to!T(s2);
  1445. assert(a == 42);
  1446. // from type immutable(wchar)[2]
  1447. a = to!T("42"w);
  1448. assert(a == 42);
  1449. }
  1450. }
  1451. }
  1452. /*@safe pure */unittest
  1453. {
  1454. alias AllInts = TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong);
  1455. alias AllFloats = TypeTuple!(float, double, real);
  1456. alias AllNumerics = TypeTuple!(AllInts, AllFloats);
  1457. // test conversions to string
  1458. {
  1459. foreach (T; AllNumerics)
  1460. {
  1461. T a = 42;
  1462. assert(to!string(a) == "42");
  1463. //assert(to!wstring(a) == "42"w);
  1464. //assert(to!dstring(a) == "42"d);
  1465. // array test
  1466. // T[] b = new T[2];
  1467. // b[0] = 42;
  1468. // b[1] = 33;
  1469. // assert(to!string(b) == "[42,33]");
  1470. }
  1471. }
  1472. // test array to string conversion
  1473. foreach (T ; AllNumerics)
  1474. {
  1475. auto a = [to!T(1), 2, 3];
  1476. assert(to!string(a) == "[1, 2, 3]");
  1477. }
  1478. // test enum to int conversion
  1479. // enum Testing { Test1, Test2 };
  1480. // Testing t;
  1481. // auto a = to!string(t);
  1482. // assert(a == "0");
  1483. }
  1484. /**
  1485. String to non-string conversion runs parsing.
  1486. $(UL
  1487. $(LI When the source is a wide string, it is first converted to a narrow
  1488. string and then parsed.)
  1489. $(LI When the source is a narrow string, normal text parsing occurs.))
  1490. */
  1491. T toImpl(T, S)(S value)
  1492. if ( isExactSomeString!S && isDynamicArray!S &&
  1493. !isExactSomeString!T && is(typeof(parse!T(value))))
  1494. {
  1495. scope(success)
  1496. {
  1497. if (value.length)
  1498. {
  1499. throw convError!(S, T)(value);
  1500. }
  1501. }
  1502. return parse!T(value);
  1503. }
  1504. /// ditto
  1505. T toImpl(T, S)(S value, uint radix)
  1506. if ( isExactSomeString!S && isDynamicArray!S &&
  1507. !isExactSomeString!T && is(typeof(parse!T(value, radix))))
  1508. {
  1509. scope(success)
  1510. {
  1511. if (value.length)
  1512. {
  1513. throw convError!(S, T)(value);
  1514. }
  1515. }
  1516. return parse!T(value, radix);
  1517. }
  1518. @safe pure unittest
  1519. {
  1520. // Issue 6668 - ensure no collaterals thrown
  1521. try { to!uint("-1"); }
  1522. catch (ConvException e) { assert(e.next is null); }
  1523. }
  1524. @safe pure unittest
  1525. {
  1526. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1527. foreach (Str; TypeTuple!(string, wstring, dstring))
  1528. {
  1529. Str a = "123";
  1530. assert(to!int(a) == 123);
  1531. assert(to!double(a) == 123);
  1532. }
  1533. // 6255
  1534. auto n = to!int("FF", 16);
  1535. assert(n == 255);
  1536. }
  1537. /**
  1538. Convert a value that is implicitly convertible to the enum base type
  1539. into an Enum value. If the value does not match any enum member values
  1540. a ConvException is thrown.
  1541. Enums with floating-point or string base types are not supported.
  1542. */
  1543. T toImpl(T, S)(S value)
  1544. if (is(T == enum) && !is(S == enum)
  1545. && is(typeof(value == OriginalType!T.init))
  1546. && !isFloatingPoint!(OriginalType!T) && !isSomeString!(OriginalType!T))
  1547. {
  1548. foreach (Member; EnumMembers!T)
  1549. {
  1550. if (Member == value)
  1551. return Member;
  1552. }
  1553. throw new ConvException(format("Value (%s) does not match any member value of enum '%s'", value, T.stringof));
  1554. }
  1555. @safe pure unittest
  1556. {
  1557. enum En8143 : int { A = 10, B = 20, C = 30, D = 20 }
  1558. enum En8143[][] m3 = to!(En8143[][])([[10, 30], [30, 10]]);
  1559. static assert(m3 == [[En8143.A, En8143.C], [En8143.C, En8143.A]]);
  1560. En8143 en1 = to!En8143(10);
  1561. assert(en1 == En8143.A);
  1562. assertThrown!ConvException(to!En8143(5)); // matches none
  1563. En8143[][] m1 = to!(En8143[][])([[10, 30], [30, 10]]);
  1564. assert(m1 == [[En8143.A, En8143.C], [En8143.C, En8143.A]]);
  1565. }
  1566. /***************************************************************
  1567. Rounded conversion from floating point to integral.
  1568. Example:
  1569. ---------------
  1570. assert(roundTo!int(3.14) == 3);
  1571. assert(roundTo!int(3.49) == 3);
  1572. assert(roundTo!int(3.5) == 4);
  1573. assert(roundTo!int(3.999) == 4);
  1574. assert(roundTo!int(-3.14) == -3);
  1575. assert(roundTo!int(-3.49) == -3);
  1576. assert(roundTo!int(-3.5) == -4);
  1577. assert(roundTo!int(-3.999) == -4);
  1578. ---------------
  1579. Rounded conversions do not work with non-integral target types.
  1580. */
  1581. template roundTo(Target)
  1582. {
  1583. Target roundTo(Source)(Source value)
  1584. {
  1585. import std.math : trunc;
  1586. static assert(isFloatingPoint!Source);
  1587. static assert(isIntegral!Target);
  1588. return to!Target(trunc(value + (value < 0 ? -0.5L : 0.5L)));
  1589. }
  1590. }
  1591. unittest
  1592. {
  1593. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1594. assert(roundTo!int(3.14) == 3);
  1595. assert(roundTo!int(3.49) == 3);
  1596. assert(roundTo!int(3.5) == 4);
  1597. assert(roundTo!int(3.999) == 4);
  1598. assert(roundTo!int(-3.14) == -3);
  1599. assert(roundTo!int(-3.49) == -3);
  1600. assert(roundTo!int(-3.5) == -4);
  1601. assert(roundTo!int(-3.999) == -4);
  1602. assert(roundTo!(const int)(to!(const double)(-3.999)) == -4);
  1603. // boundary values
  1604. foreach (Int; TypeTuple!(byte, ubyte, short, ushort, int, uint))
  1605. {
  1606. assert(roundTo!Int(Int.min - 0.4L) == Int.min);
  1607. assert(roundTo!Int(Int.max + 0.4L) == Int.max);
  1608. assertThrown!ConvOverflowException(roundTo!Int(Int.min - 0.5L));
  1609. assertThrown!ConvOverflowException(roundTo!Int(Int.max + 0.5L));
  1610. }
  1611. }
  1612. /***************************************************************
  1613. * The $(D_PARAM parse) family of functions works quite like the
  1614. * $(D_PARAM to) family, except that (1) it only works with character ranges
  1615. * as input, (2) takes the input by reference and advances it to
  1616. * the position following the conversion, and (3) does not throw if it
  1617. * could not convert the entire input. It still throws if an overflow
  1618. * occurred during conversion or if no character of the input
  1619. * was meaningfully converted.
  1620. *
  1621. * Example:
  1622. * --------------
  1623. * string test = "123 \t 76.14";
  1624. * auto a = parse!uint(test);
  1625. * assert(a == 123);
  1626. * assert(test == " \t 76.14"); // parse bumps string
  1627. * munch(test, " \t\n\r"); // skip ws
  1628. * assert(test == "76.14");
  1629. * auto b = parse!double(test);
  1630. * assert(b == 76.14);
  1631. * assert(test == "");
  1632. * --------------
  1633. */
  1634. Target parse(Target, Source)(ref Source s)
  1635. if (isSomeChar!(ElementType!Source) &&
  1636. isIntegral!Target && !is(Target == enum))
  1637. {
  1638. static if (Target.sizeof < int.sizeof)
  1639. {
  1640. // smaller types are handled like integers
  1641. auto v = .parse!(Select!(Target.min < 0, int, uint))(s);
  1642. auto result = ()@trusted{ return cast(Target) v; }();
  1643. if (result != v)
  1644. goto Loverflow;
  1645. return result;
  1646. }
  1647. else
  1648. {
  1649. // Larger than int types
  1650. static if (Target.min < 0)
  1651. int sign = 0;
  1652. else
  1653. enum int sign = 0;
  1654. Target v = 0;
  1655. bool atStart = true;
  1656. enum char maxLastDigit = Target.min < 0 ? '7' : '5';
  1657. while (!s.empty)
  1658. {
  1659. immutable c = s.front;
  1660. if (c >= '0' && c <= '9')
  1661. {
  1662. if (v >= Target.max/10 &&
  1663. (v != Target.max/10 || c + sign > maxLastDigit))
  1664. goto Loverflow;
  1665. v = cast(Target) (v * 10 + (c - '0'));
  1666. s.popFront();
  1667. atStart = false;
  1668. }
  1669. else static if (Target.min < 0)
  1670. {
  1671. if (c == '-' && atStart)
  1672. {
  1673. s.popFront();
  1674. sign = -1;
  1675. }
  1676. else if (c == '+' && atStart)
  1677. s.popFront();
  1678. else
  1679. break;
  1680. }
  1681. else
  1682. break;
  1683. }
  1684. if (atStart)
  1685. goto Lerr;
  1686. static if (Target.min < 0)
  1687. {
  1688. if (sign == -1)
  1689. {
  1690. v = -v;
  1691. }
  1692. }
  1693. return v;
  1694. }
  1695. Loverflow:
  1696. throw new ConvOverflowException("Overflow in integral conversion");
  1697. Lerr:
  1698. throw convError!(Source, Target)(s);
  1699. }
  1700. @safe pure unittest
  1701. {
  1702. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1703. string s = "123";
  1704. auto a = parse!int(s);
  1705. }
  1706. @safe pure unittest
  1707. {
  1708. foreach (Int; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong))
  1709. {
  1710. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1711. debug(conv) printf("conv.to!%.*s.unittest\n", Int.stringof.length, Int.stringof.ptr);
  1712. {
  1713. assert(to!Int("0") == 0);
  1714. static if (isSigned!Int)
  1715. {
  1716. assert(to!Int("+0") == 0);
  1717. assert(to!Int("-0") == 0);
  1718. }
  1719. }
  1720. static if (Int.sizeof >= byte.sizeof)
  1721. {
  1722. assert(to!Int("6") == 6);
  1723. assert(to!Int("23") == 23);
  1724. assert(to!Int("68") == 68);
  1725. assert(to!Int("127") == 0x7F);
  1726. static if (isUnsigned!Int)
  1727. {
  1728. assert(to!Int("255") == 0xFF);
  1729. }
  1730. static if (isSigned!Int)
  1731. {
  1732. assert(to!Int("+6") == 6);
  1733. assert(to!Int("+23") == 23);
  1734. assert(to!Int("+68") == 68);
  1735. assert(to!Int("+127") == 0x7F);
  1736. assert(to!Int("-6") == -6);
  1737. assert(to!Int("-23") == -23);
  1738. assert(to!Int("-68") == -68);
  1739. assert(to!Int("-128") == -128);
  1740. }
  1741. }
  1742. static if (Int.sizeof >= short.sizeof)
  1743. {
  1744. assert(to!Int("468") == 468);
  1745. assert(to!Int("32767") == 0x7FFF);
  1746. static if (isUnsigned!Int)
  1747. {
  1748. assert(to!Int("65535") == 0xFFFF);
  1749. }
  1750. static if (isSigned!Int)
  1751. {
  1752. assert(to!Int("+468") == 468);
  1753. assert(to!Int("+32767") == 0x7FFF);
  1754. assert(to!Int("-468") == -468);
  1755. assert(to!Int("-32768") == -32768);
  1756. }
  1757. }
  1758. static if (Int.sizeof >= int.sizeof)
  1759. {
  1760. assert(to!Int("2147483647") == 0x7FFFFFFF);
  1761. static if (isUnsigned!Int)
  1762. {
  1763. assert(to!Int("4294967295") == 0xFFFFFFFF);
  1764. }
  1765. static if (isSigned!Int)
  1766. {
  1767. assert(to!Int("+2147483647") == 0x7FFFFFFF);
  1768. assert(to!Int("-2147483648") == -2147483648);
  1769. }
  1770. }
  1771. static if (Int.sizeof >= long.sizeof)
  1772. {
  1773. assert(to!Int("9223372036854775807") == 0x7FFFFFFFFFFFFFFF);
  1774. static if (isUnsigned!Int)
  1775. {
  1776. assert(to!Int("18446744073709551615") == 0xFFFFFFFFFFFFFFFF);
  1777. }
  1778. static if (isSigned!Int)
  1779. {
  1780. assert(to!Int("+9223372036854775807") == 0x7FFFFFFFFFFFFFFF);
  1781. assert(to!Int("-9223372036854775808") == 0x8000000000000000);
  1782. }
  1783. }
  1784. }
  1785. }
  1786. @safe pure unittest
  1787. {
  1788. // parsing error check
  1789. foreach (Int; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong))
  1790. {
  1791. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1792. debug(conv) printf("conv.to!%.*s.unittest (error)\n", Int.stringof.length, Int.stringof.ptr);
  1793. {
  1794. immutable string[] errors1 =
  1795. [
  1796. "",
  1797. "-",
  1798. "+",
  1799. "-+",
  1800. " ",
  1801. " 0",
  1802. "0 ",
  1803. "- 0",
  1804. "1-",
  1805. "xx",
  1806. "123h",
  1807. ];
  1808. foreach (j, s; errors1)
  1809. assertThrown!ConvException(to!Int(s));
  1810. }
  1811. // parse!SomeUnsigned cannot parse head sign.
  1812. static if (isUnsigned!Int)
  1813. {
  1814. immutable string[] errors2 =
  1815. [
  1816. "+5",
  1817. "-78",
  1818. ];
  1819. foreach (j, s; errors2)
  1820. assertThrown!ConvException(to!Int(s));
  1821. }
  1822. }
  1823. // positive overflow check
  1824. foreach (i, Int; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong))
  1825. {
  1826. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1827. debug(conv) printf("conv.to!%.*s.unittest (pos overflow)\n", Int.stringof.length, Int.stringof.ptr);
  1828. immutable string[] errors =
  1829. [
  1830. "128", // > byte.max
  1831. "256", // > ubyte.max
  1832. "32768", // > short.max
  1833. "65536", // > ushort.max
  1834. "2147483648", // > int.max
  1835. "4294967296", // > uint.max
  1836. "9223372036854775808", // > long.max
  1837. "18446744073709551616", // > ulong.max
  1838. ];
  1839. foreach (j, s; errors[i..$])
  1840. assertThrown!ConvOverflowException(to!Int(s));
  1841. }
  1842. // negative overflow check
  1843. foreach (i, Int; TypeTuple!(byte, short, int, long))
  1844. {
  1845. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1846. debug(conv) printf("conv.to!%.*s.unittest (neg overflow)\n", Int.stringof.length, Int.stringof.ptr);
  1847. immutable string[] errors =
  1848. [
  1849. "-129", // < byte.min
  1850. "-32769", // < short.min
  1851. "-2147483649", // < int.min
  1852. "-9223372036854775809", // < long.min
  1853. ];
  1854. foreach (j, s; errors[i..$])
  1855. assertThrown!ConvOverflowException(to!Int(s));
  1856. }
  1857. }
  1858. @safe pure unittest
  1859. {
  1860. assertCTFEable!({ string s = "1234abc"; assert(parse! int(s) == 1234 && s == "abc"); });
  1861. assertCTFEable!({ string s = "-1234abc"; assert(parse! int(s) == -1234 && s == "abc"); });
  1862. assertCTFEable!({ string s = "1234abc"; assert(parse!uint(s) == 1234 && s == "abc"); });
  1863. }
  1864. /// ditto
  1865. Target parse(Target, Source)(ref Source s, uint radix)
  1866. if (isSomeChar!(ElementType!Source) &&
  1867. isIntegral!Target && !is(Target == enum))
  1868. in
  1869. {
  1870. assert(radix >= 2 && radix <= 36);
  1871. }
  1872. body
  1873. {
  1874. if (radix == 10)
  1875. return parse!Target(s);
  1876. immutable uint beyond = (radix < 10 ? '0' : 'a'-10) + radix;
  1877. Target v = 0;
  1878. size_t atStart = true;
  1879. for (; !s.empty; s.popFront())
  1880. {
  1881. uint c = s.front;
  1882. if (c < '0')
  1883. break;
  1884. if (radix < 10)
  1885. {
  1886. if (c >= beyond)
  1887. break;
  1888. }
  1889. else
  1890. {
  1891. if (c > '9')
  1892. {
  1893. c |= 0x20;//poorman's tolower
  1894. if (c < 'a' || c >= beyond)
  1895. break;
  1896. c -= 'a'-10-'0';
  1897. }
  1898. }
  1899. auto blah = cast(Target) (v * radix + c - '0');
  1900. if (blah < v)
  1901. goto Loverflow;
  1902. v = blah;
  1903. atStart = false;
  1904. }
  1905. if (atStart)
  1906. goto Lerr;
  1907. return v;
  1908. Loverflow:
  1909. throw new ConvOverflowException("Overflow in integral conversion");
  1910. Lerr:
  1911. throw convError!(Source, Target)(s, radix);
  1912. }
  1913. @safe pure unittest
  1914. {
  1915. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1916. // @@@BUG@@@ the size of China
  1917. // foreach (i; 2..37)
  1918. // {
  1919. // assert(parse!int("0",i) == 0);
  1920. // assert(parse!int("1",i) == 1);
  1921. // assert(parse!byte("10",i) == i);
  1922. // }
  1923. foreach (i; 2..37)
  1924. {
  1925. string s = "0";
  1926. assert(parse!int(s,i) == 0);
  1927. s = "1";
  1928. assert(parse!int(s,i) == 1);
  1929. s = "10";
  1930. assert(parse!byte(s,i) == i);
  1931. }
  1932. // Same @@@BUG@@@ as above
  1933. //assert(parse!int("0011001101101", 2) == 0b0011001101101);
  1934. // assert(parse!int("765",8) == 0765);
  1935. // assert(parse!int("fCDe",16) == 0xfcde);
  1936. auto s = "0011001101101";
  1937. assert(parse!int(s, 2) == 0b0011001101101);
  1938. s = "765";
  1939. assert(parse!int(s, 8) == octal!765);
  1940. s = "fCDe";
  1941. assert(parse!int(s, 16) == 0xfcde);
  1942. // 6609
  1943. s = "-42";
  1944. assert(parse!int(s, 10) == -42);
  1945. }
  1946. @safe pure unittest // bugzilla 7302
  1947. {
  1948. auto r = cycle("2A!");
  1949. auto u = parse!uint(r, 16);
  1950. assert(u == 42);
  1951. assert(r.front == '!');
  1952. }
  1953. Target parse(Target, Source)(ref Source s)
  1954. if (isExactSomeString!Source &&
  1955. is(Target == enum))
  1956. {
  1957. Target result;
  1958. size_t longest_match = 0;
  1959. foreach (i, e; EnumMembers!Target)
  1960. {
  1961. auto ident = __traits(allMembers, Target)[i];
  1962. if (longest_match < ident.length && s.startsWith(ident))
  1963. {
  1964. result = e;
  1965. longest_match = ident.length ;
  1966. }
  1967. }
  1968. if (longest_match > 0)
  1969. {
  1970. s = s[longest_match .. $];
  1971. return result ;
  1972. }
  1973. throw new ConvException(
  1974. Target.stringof ~ " does not have a member named '"
  1975. ~ to!string(s) ~ "'");
  1976. }
  1977. unittest
  1978. {
  1979. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  1980. enum EB : bool { a = true, b = false, c = a }
  1981. enum EU { a, b, c }
  1982. enum EI { a = -1, b = 0, c = 1 }
  1983. enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
  1984. enum EC : char { a = 'a', b = 'b', c = 'c' }
  1985. enum ES : string { a = "aaa", b = "bbb", c = "ccc" }
  1986. foreach (E; TypeTuple!(EB, EU, EI, EF, EC, ES))
  1987. {
  1988. assert(to!E("a"c) == E.a);
  1989. assert(to!E("b"w) == E.b);
  1990. assert(to!E("c"d) == E.c);
  1991. assertThrown!ConvException(to!E("d"));
  1992. }
  1993. }
  1994. @safe pure unittest // bugzilla 4744
  1995. {
  1996. enum A { member1, member11, member111 }
  1997. assert(to!A("member1" ) == A.member1 );
  1998. assert(to!A("member11" ) == A.member11 );
  1999. assert(to!A("member111") == A.member111);
  2000. auto s = "member1111";
  2001. assert(parse!A(s) == A.member111 && s == "1");
  2002. }
  2003. Target parse(Target, Source)(ref Source p)
  2004. if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
  2005. isFloatingPoint!Target && !is(Target == enum))
  2006. {
  2007. static import core.stdc.math/* : HUGE_VAL*/;
  2008. static immutable real[14] negtab =
  2009. [ 1e-4096L,1e-2048L,1e-1024L,1e-512L,1e-256L,1e-128L,1e-64L,1e-32L,
  2010. 1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L ];
  2011. static immutable real[13] postab =
  2012. [ 1e+4096L,1e+2048L,1e+1024L,1e+512L,1e+256L,1e+128L,1e+64L,1e+32L,
  2013. 1e+16L,1e+8L,1e+4L,1e+2L,1e+1L ];
  2014. // static immutable string infinity = "infinity";
  2015. // static immutable string nans = "nans";
  2016. ConvException bailOut()(string msg = null, string fn = __FILE__, size_t ln = __LINE__)
  2017. {
  2018. if (!msg)
  2019. msg = "Floating point conversion error";
  2020. return new ConvException(text(msg, " for input \"", p, "\"."), fn, ln);
  2021. }
  2022. enforce(!p.empty, bailOut());
  2023. char sign = 0; /* indicating + */
  2024. switch (p.front)
  2025. {
  2026. case '-':
  2027. sign++;
  2028. p.popFront();
  2029. enforce(!p.empty, bailOut());
  2030. if (std.ascii.toLower(p.front) == 'i')
  2031. goto case 'i';
  2032. enforce(!p.empty, bailOut());
  2033. break;
  2034. case '+':
  2035. p.popFront();
  2036. enforce(!p.empty, bailOut());
  2037. break;
  2038. case 'i': case 'I':
  2039. p.popFront();
  2040. enforce(!p.empty, bailOut());
  2041. if (std.ascii.toLower(p.front) == 'n' &&
  2042. (p.popFront(), enforce(!p.empty, bailOut()), std.ascii.toLower(p.front) == 'f'))
  2043. {
  2044. // 'inf'
  2045. p.popFront();
  2046. return sign ? -Target.infinity : Target.infinity;
  2047. }
  2048. goto default;
  2049. default: {}
  2050. }
  2051. bool isHex = false;
  2052. bool startsWithZero = p.front == '0';
  2053. if(startsWithZero)
  2054. {
  2055. p.popFront();
  2056. if(p.empty)
  2057. {
  2058. return (sign) ? -0.0 : 0.0;
  2059. }
  2060. isHex = p.front == 'x' || p.front == 'X';
  2061. }
  2062. real ldval = 0.0;
  2063. char dot = 0; /* if decimal point has been seen */
  2064. int exp = 0;
  2065. long msdec = 0, lsdec = 0;
  2066. ulong msscale = 1;
  2067. if (isHex)
  2068. {
  2069. int guard = 0;
  2070. int anydigits = 0;
  2071. uint ndigits = 0;
  2072. p.popFront();
  2073. while (!p.empty)
  2074. {
  2075. int i = p.front;
  2076. while (isHexDigit(i))
  2077. {
  2078. anydigits = 1;
  2079. i = std.ascii.isAlpha(i) ? ((i & ~0x20) - ('A' - 10)) : i - '0';
  2080. if (ndigits < 16)
  2081. {
  2082. msdec = msdec * 16 + i;
  2083. if (msdec)
  2084. ndigits++;
  2085. }
  2086. else if (ndigits == 16)
  2087. {
  2088. while (msdec >= 0)
  2089. {
  2090. exp--;
  2091. msdec <<= 1;
  2092. i <<= 1;
  2093. if (i & 0x10)
  2094. msdec |= 1;
  2095. }
  2096. guard = i << 4;
  2097. ndigits++;
  2098. exp += 4;
  2099. }
  2100. else
  2101. {
  2102. guard |= i;
  2103. exp += 4;
  2104. }
  2105. exp -= dot;
  2106. p.popFront();
  2107. if (p.empty)
  2108. break;
  2109. i = p.front;
  2110. if (i == '_')
  2111. {
  2112. p.popFront();
  2113. if (p.empty)
  2114. break;
  2115. i = p.front;
  2116. }
  2117. }
  2118. if (i == '.' && !dot)
  2119. { p.popFront();
  2120. dot = 4;
  2121. }
  2122. else
  2123. break;
  2124. }
  2125. // Round up if (guard && (sticky || odd))
  2126. if (guard & 0x80 && (guard & 0x7F || msdec & 1))
  2127. {
  2128. msdec++;
  2129. if (msdec == 0) // overflow
  2130. { msdec = 0x8000000000000000L;
  2131. exp++;
  2132. }
  2133. }
  2134. enforce(anydigits, bailOut());
  2135. enforce(!p.empty && (p.front == 'p' || p.front == 'P'),
  2136. bailOut("Floating point parsing: exponent is required"));
  2137. char sexp;
  2138. int e;
  2139. sexp = 0;
  2140. p.popFront();
  2141. if (!p.empty)
  2142. {
  2143. switch (p.front)
  2144. { case '-': sexp++;
  2145. goto case;
  2146. case '+': p.popFront(); enforce(!p.empty,
  2147. new ConvException("Error converting input"
  2148. " to floating point"));
  2149. break;
  2150. default: {}
  2151. }
  2152. }
  2153. ndigits = 0;
  2154. e = 0;
  2155. while (!p.empty && isDigit(p.front))
  2156. {
  2157. if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow
  2158. {
  2159. e = e * 10 + p.front - '0';
  2160. }
  2161. p.popFront();
  2162. ndigits = 1;
  2163. }
  2164. exp += (sexp) ? -e : e;
  2165. enforce(ndigits, new ConvException("Error converting input"
  2166. " to floating point"));
  2167. if (msdec)
  2168. {
  2169. int e2 = 0x3FFF + 63;
  2170. // left justify mantissa
  2171. while (msdec >= 0)
  2172. { msdec <<= 1;
  2173. e2--;
  2174. }
  2175. // Stuff mantissa directly into real
  2176. ()@trusted{ *cast(long*)&ldval = msdec; }();
  2177. ()@trusted{ (cast(ushort*)&ldval)[4] = cast(ushort) e2; }();
  2178. import std.math : ldexp;
  2179. // Exponent is power of 2, not power of 10
  2180. ldval = ldexp(ldval, exp);
  2181. }
  2182. goto L6;
  2183. }
  2184. else // not hex
  2185. {
  2186. if (std.ascii.toUpper(p.front) == 'N' && !startsWithZero)
  2187. {
  2188. // nan
  2189. enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A')
  2190. && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'),
  2191. new ConvException("error converting input to floating point"));
  2192. // skip past the last 'n'
  2193. p.popFront();
  2194. return typeof(return).nan;
  2195. }
  2196. bool sawDigits = startsWithZero;
  2197. while (!p.empty)
  2198. {
  2199. int i = p.front;
  2200. while (isDigit(i))
  2201. {
  2202. sawDigits = true; /* must have at least 1 digit */
  2203. if (msdec < (0x7FFFFFFFFFFFL-10)/10)
  2204. msdec = msdec * 10 + (i - '0');
  2205. else if (msscale < (0xFFFFFFFF-10)/10)
  2206. { lsdec = lsdec * 10 + (i - '0');
  2207. msscale *= 10;
  2208. }
  2209. else
  2210. {
  2211. exp++;
  2212. }
  2213. exp -= dot;
  2214. p.popFront();
  2215. if (p.empty)
  2216. break;
  2217. i = p.front;
  2218. if (i == '_')
  2219. {
  2220. p.popFront();
  2221. if (p.empty)
  2222. break;
  2223. i = p.front;
  2224. }
  2225. }
  2226. if (i == '.' && !dot)
  2227. {
  2228. p.popFront();
  2229. dot++;
  2230. }
  2231. else
  2232. {
  2233. break;
  2234. }
  2235. }
  2236. enforce(sawDigits, new ConvException("no digits seen"));
  2237. }
  2238. if (!p.empty && (p.front == 'e' || p.front == 'E'))
  2239. {
  2240. char sexp;
  2241. int e;
  2242. sexp = 0;
  2243. p.popFront();
  2244. enforce(!p.empty, new ConvException("Unexpected end of input"));
  2245. switch (p.front)
  2246. { case '-': sexp++;
  2247. goto case;
  2248. case '+': p.popFront();
  2249. break;
  2250. default: {}
  2251. }
  2252. bool sawDigits = 0;
  2253. e = 0;
  2254. while (!p.empty && isDigit(p.front))
  2255. {
  2256. if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow
  2257. {
  2258. e = e * 10 + p.front - '0';
  2259. }
  2260. p.popFront();
  2261. sawDigits = 1;
  2262. }
  2263. exp += (sexp) ? -e : e;
  2264. enforce(sawDigits, new ConvException("No digits seen."));
  2265. }
  2266. ldval = msdec;
  2267. if (msscale != 1) /* if stuff was accumulated in lsdec */
  2268. ldval = ldval * msscale + lsdec;
  2269. if (ldval)
  2270. {
  2271. uint u = 0;
  2272. int pow = 4096;
  2273. while (exp > 0)
  2274. {
  2275. while (exp >= pow)
  2276. {
  2277. ldval *= postab[u];
  2278. exp -= pow;
  2279. }
  2280. pow >>= 1;
  2281. u++;
  2282. }
  2283. while (exp < 0)
  2284. {
  2285. while (exp <= -pow)
  2286. {
  2287. ldval *= negtab[u];
  2288. enforce(ldval != 0, new ConvException("Range error"));
  2289. exp += pow;
  2290. }
  2291. pow >>= 1;
  2292. u++;
  2293. }
  2294. }
  2295. L6: // if overflow occurred
  2296. enforce(ldval != core.stdc.math.HUGE_VAL, new ConvException("Range error"));
  2297. L1:
  2298. return (sign) ? -ldval : ldval;
  2299. }
  2300. unittest
  2301. {
  2302. import std.math : isnan, fabs;
  2303. // Compare reals with given precision
  2304. bool feq(in real rx, in real ry, in real precision = 0.000001L)
  2305. {
  2306. if (rx == ry)
  2307. return 1;
  2308. if (isnan(rx))
  2309. return cast(bool)isnan(ry);
  2310. if (isnan(ry))
  2311. return 0;
  2312. return cast(bool)(fabs(rx - ry) <= precision);
  2313. }
  2314. // Make given typed literal
  2315. F Literal(F)(F f)
  2316. {
  2317. return f;
  2318. }
  2319. foreach (Float; TypeTuple!(float, double, real))
  2320. {
  2321. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  2322. debug(conv) printf("conv.to!%.*s.unittest\n", Float.stringof.length, Float.stringof.ptr);
  2323. assert(to!Float("123") == Literal!Float(123));
  2324. assert(to!Float("+123") == Literal!Float(+123));
  2325. assert(to!Float("-123") == Literal!Float(-123));
  2326. assert(to!Float("123e2") == Literal!Float(123e2));
  2327. assert(to!Float("123e+2") == Literal!Float(123e+2));
  2328. assert(to!Float("123e-2") == Literal!Float(123e-2));
  2329. assert(to!Float("123.") == Literal!Float(123.0));
  2330. assert(to!Float(".375") == Literal!Float(.375));
  2331. assert(to!Float("1.23375E+2") == Literal!Float(1.23375E+2));
  2332. assert(to!Float("0") is 0.0);
  2333. assert(to!Float("-0") is -0.0);
  2334. assert(isnan(to!Float("nan")));
  2335. assertThrown!ConvException(to!Float("\x00"));
  2336. }
  2337. // min and max
  2338. float f = to!float("1.17549e-38");
  2339. assert(feq(cast(real)f, cast(real)1.17549e-38));
  2340. assert(feq(cast(real)f, cast(real)float.min_normal));
  2341. f = to!float("3.40282e+38");
  2342. assert(to!string(f) == to!string(3.40282e+38));
  2343. // min and max
  2344. double d = to!double("2.22508e-308");
  2345. assert(feq(cast(real)d, cast(real)2.22508e-308));
  2346. assert(feq(cast(real)d, cast(real)double.min_normal));
  2347. d = to!double("1.79769e+308");
  2348. assert(to!string(d) == to!string(1.79769e+308));
  2349. assert(to!string(d) == to!string(double.max));
  2350. assert(to!string(to!real(to!string(real.max / 2L))) == to!string(real.max / 2L));
  2351. // min and max
  2352. real r = to!real(to!string(real.min_normal));
  2353. assert(to!string(r) == to!string(real.min_normal));
  2354. r = to!real(to!string(real.max));
  2355. assert(to!string(r) == to!string(real.max));
  2356. }
  2357. unittest
  2358. {
  2359. import core.stdc.errno;
  2360. import core.stdc.stdlib;
  2361. errno = 0; // In case it was set by another unittest in a different module.
  2362. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  2363. struct longdouble
  2364. {
  2365. ushort[5] value;
  2366. }
  2367. real ld;
  2368. longdouble x;
  2369. real ld1;
  2370. longdouble x1;
  2371. int i;
  2372. string s = "0x1.FFFFFFFFFFFFFFFEp-16382";
  2373. ld = parse!real(s);
  2374. assert(s.empty);
  2375. x = *cast(longdouble *)&ld;
  2376. ld1 = strtold("0x1.FFFFFFFFFFFFFFFEp-16382", null);
  2377. x1 = *cast(longdouble *)&ld1;
  2378. assert(x1 == x && ld1 == ld);
  2379. // for (i = 4; i >= 0; i--)
  2380. // {
  2381. // printf("%04x ", x.value[i]);
  2382. // }
  2383. // printf("\n");
  2384. assert(!errno);
  2385. s = "1.0e5";
  2386. ld = parse!real(s);
  2387. assert(s.empty);
  2388. x = *cast(longdouble *)&ld;
  2389. ld1 = strtold("1.0e5", null);
  2390. x1 = *cast(longdouble *)&ld1;
  2391. // for (i = 4; i >= 0; i--)
  2392. // {
  2393. // printf("%04x ", x.value[i]);
  2394. // }
  2395. // printf("\n");
  2396. }
  2397. @safe pure unittest
  2398. {
  2399. // Bugzilla 4959
  2400. {
  2401. auto s = "0 ";
  2402. auto x = parse!double(s);
  2403. assert(s == " ");
  2404. assert(x == 0.0);
  2405. }
  2406. // Bugzilla 3369
  2407. assert(to!float("inf") == float.infinity);
  2408. assert(to!float("-inf") == -float.infinity);
  2409. // Bugzilla 6160
  2410. assert(6_5.536e3L == to!real("6_5.536e3")); // 2^16
  2411. assert(0x1000_000_000_p10 == to!real("0x1000_000_000_p10")); // 7.03687e+13
  2412. // Bugzilla 6258
  2413. assertThrown!ConvException(to!real("-"));
  2414. assertThrown!ConvException(to!real("in"));
  2415. // Bugzilla 7055
  2416. assertThrown!ConvException(to!float("INF2"));
  2417. //extra stress testing
  2418. auto ssOK = ["1.", "1.1.1", "1.e5", "2e1e", "2a", "2e1_1",
  2419. "inf", "-inf", "infa", "-infa", "inf2e2", "-inf2e2"];
  2420. auto ssKO = ["", " ", "2e", "2e+", "2e-", "2ee", "2e++1", "2e--1", "2e_1", "+inf"];
  2421. foreach (s; ssOK)
  2422. parse!double(s);
  2423. foreach (s; ssKO)
  2424. assertThrown!ConvException(parse!double(s));
  2425. }
  2426. /**
  2427. Parsing one character off a string returns the character and bumps the
  2428. string up one position.
  2429. */
  2430. Target parse(Target, Source)(ref Source s)
  2431. if (isExactSomeString!Source &&
  2432. staticIndexOf!(Unqual!Target, dchar, Unqual!(ElementEncodingType!Source)) >= 0)
  2433. {
  2434. if (s.empty)
  2435. throw convError!(Source, Target)(s);
  2436. static if (is(Unqual!Target == dchar))
  2437. {
  2438. Target result = s.front;
  2439. s.popFront();
  2440. return result;
  2441. }
  2442. else
  2443. {
  2444. // Special case: okay so parse a Char off a Char[]
  2445. Target result = s[0];
  2446. s = s[1 .. $];
  2447. return result;
  2448. }
  2449. }
  2450. @safe pure unittest
  2451. {
  2452. foreach (Str; TypeTuple!(string, wstring, dstring))
  2453. {
  2454. foreach (Char; TypeTuple!(char, wchar, dchar))
  2455. {
  2456. static if (is(Unqual!Char == dchar) ||
  2457. Char.sizeof == ElementEncodingType!Str.sizeof)
  2458. {
  2459. Str s = "aaa";
  2460. assert(parse!Char(s) == 'a');
  2461. assert(s == "aa");
  2462. }
  2463. }
  2464. }
  2465. }
  2466. Target parse(Target, Source)(ref Source s)
  2467. if (!isSomeString!Source && isInputRange!Source && isSomeChar!(ElementType!Source) &&
  2468. isSomeChar!Target && Target.sizeof >= ElementType!Source.sizeof && !is(Target == enum))
  2469. {
  2470. if (s.empty)
  2471. throw convError!(Source, Target)(s);
  2472. Target result = s.front;
  2473. s.popFront();
  2474. return result;
  2475. }
  2476. // string to bool conversions
  2477. Target parse(Target, Source)(ref Source s)
  2478. if (isExactSomeString!Source &&
  2479. is(Unqual!Target == bool))
  2480. {
  2481. if (s.length >= 4 && icmp(s[0 .. 4], "true") == 0)
  2482. {
  2483. s = s[4 .. $];
  2484. return true;
  2485. }
  2486. if (s.length >= 5 && icmp(s[0 .. 5], "false") == 0)
  2487. {
  2488. s = s[5 .. $];
  2489. return false;
  2490. }
  2491. throw parseError("bool should be case-insensitive 'true' or 'false'");
  2492. }
  2493. /*
  2494. Tests for to!bool and parse!bool
  2495. */
  2496. @safe pure unittest
  2497. {
  2498. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  2499. debug(conv) printf("conv.to!bool.unittest\n");
  2500. assert (to!bool("TruE") == true);
  2501. assert (to!bool("faLse"d) == false);
  2502. assertThrown!ConvException(to!bool("maybe"));
  2503. auto t = "TrueType";
  2504. assert (parse!bool(t) == true);
  2505. assert (t == "Type");
  2506. auto f = "False killer whale"d;
  2507. assert (parse!bool(f) == false);
  2508. assert (f == " killer whale"d);
  2509. auto m = "maybe";
  2510. assertThrown!ConvException(parse!bool(m));
  2511. assert (m == "maybe"); // m shouldn't change on failure
  2512. auto s = "true";
  2513. auto b = parse!(const(bool))(s);
  2514. assert(b == true);
  2515. }
  2516. // string to null literal conversions
  2517. Target parse(Target, Source)(ref Source s)
  2518. if (isExactSomeString!Source &&
  2519. is(Unqual!Target == typeof(null)))
  2520. {
  2521. if (s.length >= 4 && icmp(s[0 .. 4], "null") == 0)
  2522. {
  2523. s = s[4 .. $];
  2524. return null;
  2525. }
  2526. throw parseError("null should be case-insensitive 'null'");
  2527. }
  2528. @safe pure unittest
  2529. {
  2530. alias typeof(null) NullType;
  2531. auto s1 = "null";
  2532. assert(parse!NullType(s1) is null);
  2533. assert(s1 == "");
  2534. auto s2 = "NUll"d;
  2535. assert(parse!NullType(s2) is null);
  2536. assert(s2 == "");
  2537. auto m = "maybe";
  2538. assertThrown!ConvException(parse!NullType(m));
  2539. assert(m == "maybe"); // m shouldn't change on failure
  2540. auto s = "NULL";
  2541. assert(parse!(const NullType)(s) is null);
  2542. }
  2543. //Used internally by parse Array/AA, to remove ascii whites
  2544. package void skipWS(R)(ref R r)
  2545. {
  2546. static if (isSomeString!R)
  2547. {
  2548. //Implementation inspired from stripLeft.
  2549. foreach (i, dchar c; r)
  2550. {
  2551. if (!std.ascii.isWhite(c))
  2552. {
  2553. r = r[i .. $];
  2554. return;
  2555. }
  2556. }
  2557. r = r[0 .. 0]; //Empty string with correct type.
  2558. return;
  2559. }
  2560. else
  2561. {
  2562. for (; !r.empty && std.ascii.isWhite(r.front); r.popFront())
  2563. {}
  2564. }
  2565. }
  2566. /**
  2567. * Parses an array from a string given the left bracket (default $(D
  2568. * '[')), right bracket (default $(D ']')), and element separator (by
  2569. * default $(D ',')).
  2570. */
  2571. Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
  2572. if (isExactSomeString!Source &&
  2573. isDynamicArray!Target && !is(Target == enum))
  2574. {
  2575. Target result;
  2576. parseCheck!s(lbracket);
  2577. skipWS(s);
  2578. if (s.empty)
  2579. throw convError!(Source, Target)(s);
  2580. if (s.front == rbracket)
  2581. {
  2582. s.popFront();
  2583. return result;
  2584. }
  2585. for (;; s.popFront(), skipWS(s))
  2586. {
  2587. result ~= parseElement!(ElementType!Target)(s);
  2588. skipWS(s);
  2589. if (s.empty)
  2590. throw convError!(Source, Target)(s);
  2591. if (s.front != comma)
  2592. break;
  2593. }
  2594. parseCheck!s(rbracket);
  2595. return result;
  2596. }
  2597. unittest
  2598. {
  2599. int[] a = [1, 2, 3, 4, 5];
  2600. auto s = to!string(a);
  2601. assert(to!(int[])(s) == a);
  2602. }
  2603. unittest
  2604. {
  2605. int[][] a = [ [1, 2] , [3], [4, 5] ];
  2606. auto s = to!string(a);
  2607. assert(to!(int[][])(s) == a);
  2608. }
  2609. unittest
  2610. {
  2611. int[][][] ia = [ [[1,2],[3,4],[5]] , [[6],[],[7,8,9]] , [[]] ];
  2612. char[] s = to!(char[])(ia);
  2613. int[][][] ia2;
  2614. ia2 = to!(typeof(ia2))(s);
  2615. assert( ia == ia2);
  2616. }
  2617. @safe pure unittest
  2618. {
  2619. auto s1 = `[['h', 'e', 'l', 'l', 'o'], "world"]`;
  2620. auto a1 = parse!(string[])(s1);
  2621. assert(a1 == ["hello", "world"]);
  2622. auto s2 = `["aaa", "bbb", "ccc"]`;
  2623. auto a2 = parse!(string[])(s2);
  2624. assert(a2 == ["aaa", "bbb", "ccc"]);
  2625. }
  2626. @safe pure unittest
  2627. {
  2628. //Check proper failure
  2629. auto s = "[ 1 , 2 , 3 ]";
  2630. foreach (i ; 0..s.length-1)
  2631. {
  2632. auto ss = s[0 .. i];
  2633. assertThrown!ConvException(parse!(int[])(ss));
  2634. }
  2635. int[] arr = parse!(int[])(s);
  2636. }
  2637. @safe pure unittest
  2638. {
  2639. //Checks parsing of strings with escaped characters
  2640. string s1 = `[
  2641. "Contains a\0null!",
  2642. "tab\there",
  2643. "line\nbreak",
  2644. "backslash \\ slash / question \?",
  2645. "number \x35 five",
  2646. "unicode \u65E5 sun",
  2647. "very long \U000065E5 sun"
  2648. ]`;
  2649. //Note: escaped characters purposefully replaced and isolated to guarantee
  2650. //there are no typos in the escape syntax
  2651. string[] s2 = [
  2652. "Contains a" ~ '\0' ~ "null!",
  2653. "tab" ~ '\t' ~ "here",
  2654. "line" ~ '\n' ~ "break",
  2655. "backslash " ~ '\\' ~ " slash / question ?",
  2656. "number 5 five",
  2657. "unicode æ—¥ sun",
  2658. "very long æ—¥ sun"
  2659. ];
  2660. assert(s2 == parse!(string[])(s1));
  2661. assert(s1.empty);
  2662. }
  2663. /// ditto
  2664. Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
  2665. if (isExactSomeString!Source &&
  2666. isStaticArray!Target && !is(Target == enum))
  2667. {
  2668. static if (hasIndirections!Target)
  2669. Target result = Target.init[0].init;
  2670. else
  2671. Target result = void;
  2672. parseCheck!s(lbracket);
  2673. skipWS(s);
  2674. if (s.empty)
  2675. throw convError!(Source, Target)(s);
  2676. if (s.front == rbracket)
  2677. {
  2678. static if (result.length != 0)
  2679. goto Lmanyerr;
  2680. else
  2681. {
  2682. s.popFront();
  2683. return result;
  2684. }
  2685. }
  2686. for (size_t i = 0; ; s.popFront(), skipWS(s))
  2687. {
  2688. if (i == result.length)
  2689. goto Lmanyerr;
  2690. result[i++] = parseElement!(ElementType!Target)(s);
  2691. skipWS(s);
  2692. if (s.empty)
  2693. throw convError!(Source, Target)(s);
  2694. if (s.front != comma)
  2695. {
  2696. if (i != result.length)
  2697. goto Lfewerr;
  2698. break;
  2699. }
  2700. }
  2701. parseCheck!s(rbracket);
  2702. return result;
  2703. Lmanyerr:
  2704. throw parseError(text("Too many elements in input, ", result.length, " elements expected."));
  2705. Lfewerr:
  2706. throw parseError(text("Too few elements in input, ", result.length, " elements expected."));
  2707. }
  2708. @safe pure unittest
  2709. {
  2710. auto s1 = "[1,2,3,4]";
  2711. auto sa1 = parse!(int[4])(s1);
  2712. assert(sa1 == [1,2,3,4]);
  2713. auto s2 = "[[1],[2,3],[4]]";
  2714. auto sa2 = parse!(int[][3])(s2);
  2715. assert(sa2 == [[1],[2,3],[4]]);
  2716. auto s3 = "[1,2,3]";
  2717. assertThrown!ConvException(parse!(int[4])(s3));
  2718. auto s4 = "[1,2,3,4,5]";
  2719. assertThrown!ConvException(parse!(int[4])(s4));
  2720. }
  2721. /**
  2722. * Parses an associative array from a string given the left bracket (default $(D
  2723. * '[')), right bracket (default $(D ']')), key-value separator (default $(D
  2724. * ':')), and element seprator (by default $(D ',')).
  2725. */
  2726. Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar keyval = ':', dchar comma = ',')
  2727. if (isExactSomeString!Source &&
  2728. isAssociativeArray!Target && !is(Target == enum))
  2729. {
  2730. alias KeyType = typeof(Target.init.keys[0]);
  2731. alias ValType = typeof(Target.init.values[0]);
  2732. Target result;
  2733. parseCheck!s(lbracket);
  2734. skipWS(s);
  2735. if (s.empty)
  2736. throw convError!(Source, Target)(s);
  2737. if (s.front == rbracket)
  2738. {
  2739. s.popFront();
  2740. return result;
  2741. }
  2742. for (;; s.popFront(), skipWS(s))
  2743. {
  2744. auto key = parseElement!KeyType(s);
  2745. skipWS(s);
  2746. parseCheck!s(keyval);
  2747. skipWS(s);
  2748. auto val = parseElement!ValType(s);
  2749. skipWS(s);
  2750. result[key] = val;
  2751. if (s.empty)
  2752. throw convError!(Source, Target)(s);
  2753. if (s.front != comma)
  2754. break;
  2755. }
  2756. parseCheck!s(rbracket);
  2757. return result;
  2758. }
  2759. @safe pure unittest
  2760. {
  2761. auto s1 = "[1:10, 2:20, 3:30]";
  2762. auto aa1 = parse!(int[int])(s1);
  2763. assert(aa1 == [1:10, 2:20, 3:30]);
  2764. auto s2 = `["aaa":10, "bbb":20, "ccc":30]`;
  2765. auto aa2 = parse!(int[string])(s2);
  2766. assert(aa2 == ["aaa":10, "bbb":20, "ccc":30]);
  2767. auto s3 = `["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]`;
  2768. auto aa3 = parse!(int[][string])(s3);
  2769. assert(aa3 == ["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]);
  2770. }
  2771. @safe pure unittest
  2772. {
  2773. //Check proper failure
  2774. auto s = "[1:10, 2:20, 3:30]";
  2775. foreach (i ; 0 .. s.length-1)
  2776. {
  2777. auto ss = s[0 .. i];
  2778. assertThrown!ConvException(parse!(int[int])(ss));
  2779. }
  2780. int[int] aa = parse!(int[int])(s);
  2781. }
  2782. private dchar parseEscape(Source)(ref Source s)
  2783. if (isInputRange!Source && isSomeChar!(ElementType!Source))
  2784. {
  2785. parseCheck!s('\\');
  2786. if (s.empty)
  2787. throw parseError("Unterminated escape sequence");
  2788. dchar getHexDigit()(ref Source s_ = s) // workaround
  2789. {
  2790. if (s_.empty)
  2791. throw parseError("Unterminated escape sequence");
  2792. s_.popFront();
  2793. if (s_.empty)
  2794. throw parseError("Unterminated escape sequence");
  2795. dchar c = s_.front;
  2796. if (!isHexDigit(c))
  2797. throw parseError("Hex digit is missing");
  2798. return std.ascii.isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0';
  2799. }
  2800. dchar result;
  2801. switch (s.front)
  2802. {
  2803. case '"': result = '\"'; break;
  2804. case '\'': result = '\''; break;
  2805. case '0': result = '\0'; break;
  2806. case '?': result = '\?'; break;
  2807. case '\\': result = '\\'; break;
  2808. case 'a': result = '\a'; break;
  2809. case 'b': result = '\b'; break;
  2810. case 'f': result = '\f'; break;
  2811. case 'n': result = '\n'; break;
  2812. case 'r': result = '\r'; break;
  2813. case 't': result = '\t'; break;
  2814. case 'v': result = '\v'; break;
  2815. case 'x':
  2816. result = getHexDigit() << 4;
  2817. result |= getHexDigit();
  2818. break;
  2819. case 'u':
  2820. result = getHexDigit() << 12;
  2821. result |= getHexDigit() << 8;
  2822. result |= getHexDigit() << 4;
  2823. result |= getHexDigit();
  2824. break;
  2825. case 'U':
  2826. result = getHexDigit() << 28;
  2827. result |= getHexDigit() << 24;
  2828. result |= getHexDigit() << 20;
  2829. result |= getHexDigit() << 16;
  2830. result |= getHexDigit() << 12;
  2831. result |= getHexDigit() << 8;
  2832. result |= getHexDigit() << 4;
  2833. result |= getHexDigit();
  2834. break;
  2835. default:
  2836. throw parseError("Unknown escape character " ~ to!string(s.front));
  2837. }
  2838. if (s.empty)
  2839. throw parseError("Unterminated escape sequence");
  2840. s.popFront();
  2841. return result;
  2842. }
  2843. @safe pure unittest
  2844. {
  2845. string[] s1 = [
  2846. `\"`, `\'`, `\?`, `\\`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v`, //Normal escapes
  2847. //`\141`, //@@@9621@@@ Octal escapes.
  2848. `\x61`,
  2849. `\u65E5`, `\U00012456`
  2850. //`\&amp;`, `\&quot;`, //@@@9621@@@ Named Character Entities.
  2851. ];
  2852. const(dchar)[] s2 = [
  2853. '\"', '\'', '\?', '\\', '\a', '\b', '\f', '\n', '\r', '\t', '\v', //Normal escapes
  2854. //'\141', //@@@9621@@@ Octal escapes.
  2855. '\x61',
  2856. '\u65E5', '\U00012456'
  2857. //'\&amp;', '\&quot;', //@@@9621@@@ Named Character Entities.
  2858. ];
  2859. foreach (i ; 0 .. s1.length)
  2860. {
  2861. assert(s2[i] == parseEscape(s1[i]));
  2862. assert(s1[i].empty);
  2863. }
  2864. }
  2865. @safe pure unittest
  2866. {
  2867. string[] ss = [
  2868. `hello!`, //Not an escape
  2869. `\`, //Premature termination
  2870. `\/`, //Not an escape
  2871. `\gggg`, //Not an escape
  2872. `\xzz`, //Not an hex
  2873. `\x0`, //Premature hex end
  2874. `\XB9`, //Not legal hex syntax
  2875. `\u!!`, //Not a unicode hex
  2876. `\777`, //Octal is larger than a byte //Note: Throws, but simply because octals are unsupported
  2877. `\u123`, //Premature hex end
  2878. `\U123123` //Premature hex end
  2879. ];
  2880. foreach (s ; ss)
  2881. assertThrown!ConvException(parseEscape(s));
  2882. }
  2883. // Undocumented
  2884. Target parseElement(Target, Source)(ref Source s)
  2885. if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
  2886. isExactSomeString!Target)
  2887. {
  2888. auto result = appender!Target();
  2889. // parse array of chars
  2890. if (s.empty)
  2891. throw convError!(Source, Target)(s);
  2892. if (s.front == '[')
  2893. return parse!Target(s);
  2894. parseCheck!s('\"');
  2895. if (s.empty)
  2896. throw convError!(Source, Target)(s);
  2897. if (s.front == '\"')
  2898. {
  2899. s.popFront();
  2900. return result.data;
  2901. }
  2902. while (true)
  2903. {
  2904. if (s.empty)
  2905. throw parseError("Unterminated quoted string");
  2906. switch (s.front)
  2907. {
  2908. case '\"':
  2909. s.popFront();
  2910. return result.data;
  2911. case '\\':
  2912. result.put(parseEscape(s));
  2913. break;
  2914. default:
  2915. result.put(s.front);
  2916. s.popFront();
  2917. break;
  2918. }
  2919. }
  2920. assert(0);
  2921. }
  2922. // ditto
  2923. Target parseElement(Target, Source)(ref Source s)
  2924. if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
  2925. isSomeChar!Target && !is(Target == enum))
  2926. {
  2927. Target c;
  2928. parseCheck!s('\'');
  2929. if (s.empty)
  2930. throw convError!(Source, Target)(s);
  2931. if (s.front != '\\')
  2932. {
  2933. c = s.front;
  2934. s.popFront();
  2935. }
  2936. else
  2937. c = parseEscape(s);
  2938. parseCheck!s('\'');
  2939. return c;
  2940. }
  2941. // ditto
  2942. Target parseElement(Target, Source)(ref Source s)
  2943. if (isInputRange!Source && isSomeChar!(ElementType!Source) &&
  2944. !isSomeString!Target && !isSomeChar!Target)
  2945. {
  2946. return parse!Target(s);
  2947. }
  2948. /***************************************************************
  2949. * Convenience functions for converting any number and types of
  2950. * arguments into _text (the three character widths).
  2951. */
  2952. string text(T...)(T args) { return textImpl!string(args); }
  2953. ///ditto
  2954. wstring wtext(T...)(T args) { return textImpl!wstring(args); }
  2955. ///ditto
  2956. dstring dtext(T...)(T args) { return textImpl!dstring(args); }
  2957. private S textImpl(S, U...)(U args)
  2958. {
  2959. static if (U.length == 0)
  2960. {
  2961. return null;
  2962. }
  2963. else
  2964. {
  2965. auto result = to!S(args[0]);
  2966. foreach (arg; args[1 .. $])
  2967. result ~= to!S(arg);
  2968. return result;
  2969. }
  2970. }
  2971. ///
  2972. unittest
  2973. {
  2974. assert( text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"c);
  2975. assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w);
  2976. assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d);
  2977. }
  2978. unittest
  2979. {
  2980. assert(text() is null);
  2981. assert(wtext() is null);
  2982. assert(dtext() is null);
  2983. }
  2984. /***************************************************************
  2985. The $(D octal) facility is intended as an experimental facility to
  2986. replace _octal literals starting with $(D '0'), which many find
  2987. confusing. Using $(D octal!177) or $(D octal!"177") instead of $(D
  2988. 0177) as an _octal literal makes code clearer and the intent more
  2989. visible. If use of this facility becomes preponderent, a future
  2990. version of the language may deem old-style _octal literals deprecated.
  2991. The rules for strings are the usual for literals: If it can fit in an
  2992. $(D int), it is an $(D int). Otherwise, it is a $(D long). But, if the
  2993. user specifically asks for a $(D long) with the $(D L) suffix, always
  2994. give the $(D long). Give an unsigned iff it is asked for with the $(D
  2995. U) or $(D u) suffix. _Octals created from integers preserve the type
  2996. of the passed-in integral.
  2997. Example:
  2998. ----
  2999. // same as 0177
  3000. auto x = octal!177;
  3001. // octal is a compile-time device
  3002. enum y = octal!160;
  3003. // Create an unsigned octal
  3004. auto z = octal!"1_000_000u";
  3005. ----
  3006. */
  3007. @property int octal(string num)()
  3008. if((octalFitsInInt!(num) && !literalIsLong!(num)) && !literalIsUnsigned!(num))
  3009. {
  3010. return octal!(int, num);
  3011. }
  3012. /// Ditto
  3013. @property long octal(string num)()
  3014. if((!octalFitsInInt!(num) || literalIsLong!(num)) && !literalIsUnsigned!(num))
  3015. {
  3016. return octal!(long, num);
  3017. }
  3018. /// Ditto
  3019. @property uint octal(string num)()
  3020. if((octalFitsInInt!(num) && !literalIsLong!(num)) && literalIsUnsigned!(num))
  3021. {
  3022. return octal!(int, num);
  3023. }
  3024. /// Ditto
  3025. @property ulong octal(string num)()
  3026. if((!octalFitsInInt!(num) || literalIsLong!(num)) && literalIsUnsigned!(num))
  3027. {
  3028. return octal!(long, num);
  3029. }
  3030. /// Ditto
  3031. template octal(alias s)
  3032. if (isIntegral!(typeof(s)))
  3033. {
  3034. enum auto octal = octal!(typeof(s), to!string(s));
  3035. }
  3036. /*
  3037. Takes a string, num, which is an octal literal, and returns its
  3038. value, in the type T specified.
  3039. So:
  3040. int a = octal!(int, "10");
  3041. assert(a == 8);
  3042. */
  3043. @property T octal(T, string num)()
  3044. if (isOctalLiteral!num)
  3045. {
  3046. ulong pow = 1;
  3047. T value = 0;
  3048. for (int pos = num.length - 1; pos >= 0; pos--)
  3049. {
  3050. char s = num[pos];
  3051. if (s < '0' || s > '7') // we only care about digits; skip the rest
  3052. // safe to skip - this is checked out in the assert so these
  3053. // are just suffixes
  3054. continue;
  3055. value += pow * (s - '0');
  3056. pow *= 8;
  3057. }
  3058. return value;
  3059. }
  3060. /*
  3061. Take a look at int.max and int.max+1 in octal and the logic for this
  3062. function follows directly.
  3063. */
  3064. template octalFitsInInt(string octalNum)
  3065. {
  3066. // note it is important to strip the literal of all
  3067. // non-numbers. kill the suffix and underscores lest they mess up
  3068. // the number of digits here that we depend on.
  3069. enum bool octalFitsInInt = strippedOctalLiteral(octalNum).length < 11 ||
  3070. strippedOctalLiteral(octalNum).length == 11 &&
  3071. strippedOctalLiteral(octalNum)[0] == '1';
  3072. }
  3073. string strippedOctalLiteral(string original)
  3074. {
  3075. string stripped = "";
  3076. foreach (c; original)
  3077. if (c >= '0' && c <= '7')
  3078. stripped ~= c;
  3079. return stripped;
  3080. }
  3081. template literalIsLong(string num)
  3082. {
  3083. static if (num.length > 1)
  3084. // can be xxL or xxLu according to spec
  3085. enum literalIsLong = (num[$-1] == 'L' || num[$-2] == 'L');
  3086. else
  3087. enum literalIsLong = false;
  3088. }
  3089. template literalIsUnsigned(string num)
  3090. {
  3091. static if (num.length > 1)
  3092. // can be xxU or xxUL according to spec
  3093. enum literalIsUnsigned = (num[$-1] == 'u' || num[$-2] == 'u')
  3094. // both cases are allowed too
  3095. || (num[$-1] == 'U' || num[$-2] == 'U');
  3096. else
  3097. enum literalIsUnsigned = false;
  3098. }
  3099. /*
  3100. Returns if the given string is a correctly formatted octal literal.
  3101. The format is specified in lex.html. The leading zero is allowed, but
  3102. not required.
  3103. */
  3104. bool isOctalLiteralString(string num)
  3105. {
  3106. if (num.length == 0)
  3107. return false;
  3108. // Must start with a number. To avoid confusion, literals that
  3109. // start with a '0' are not allowed
  3110. if (num[0] == '0' && num.length > 1)
  3111. return false;
  3112. if (num[0] < '0' || num[0] > '7')
  3113. return false;
  3114. foreach (i, c; num)
  3115. {
  3116. if ((c < '0' || c > '7') && c != '_') // not a legal character
  3117. {
  3118. if (i < num.length - 2)
  3119. return false;
  3120. else // gotta check for those suffixes
  3121. {
  3122. if (c != 'U' && c != 'u' && c != 'L')
  3123. return false;
  3124. if (i != num.length - 1)
  3125. {
  3126. // if we're not the last one, the next one must
  3127. // also be a suffix to be valid
  3128. char c2 = num[$-1];
  3129. if (c2 != 'U' && c2 != 'u' && c2 != 'L')
  3130. return false; // spam at the end of the string
  3131. if (c2 == c)
  3132. return false; // repeats are disallowed
  3133. }
  3134. }
  3135. }
  3136. }
  3137. return true;
  3138. }
  3139. /*
  3140. Returns true if the given compile time string is an octal literal.
  3141. */
  3142. template isOctalLiteral(string num)
  3143. {
  3144. enum bool isOctalLiteral = isOctalLiteralString(num);
  3145. }
  3146. unittest
  3147. {
  3148. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  3149. // ensure that you get the right types, even with embedded underscores
  3150. auto w = octal!"100_000_000_000";
  3151. static assert(!is(typeof(w) == int));
  3152. auto w2 = octal!"1_000_000_000";
  3153. static assert(is(typeof(w2) == int));
  3154. static assert(octal!"45" == 37);
  3155. static assert(octal!"0" == 0);
  3156. static assert(octal!"7" == 7);
  3157. static assert(octal!"10" == 8);
  3158. static assert(octal!"666" == 438);
  3159. static assert(octal!45 == 37);
  3160. static assert(octal!0 == 0);
  3161. static assert(octal!7 == 7);
  3162. static assert(octal!10 == 8);
  3163. static assert(octal!666 == 438);
  3164. static assert(octal!"66_6" == 438);
  3165. static assert(octal!2520046213 == 356535435);
  3166. static assert(octal!"2520046213" == 356535435);
  3167. static assert(octal!17777777777 == int.max);
  3168. static assert(!__traits(compiles, octal!823));
  3169. static assert(!__traits(compiles, octal!"823"));
  3170. static assert(!__traits(compiles, octal!"_823"));
  3171. static assert(!__traits(compiles, octal!"spam"));
  3172. static assert(!__traits(compiles, octal!"77%"));
  3173. int a;
  3174. long b;
  3175. // biggest value that should fit in an it
  3176. static assert(__traits(compiles, a = octal!"17777777777"));
  3177. // should not fit in the int
  3178. static assert(!__traits(compiles, a = octal!"20000000000"));
  3179. // ... but should fit in a long
  3180. static assert(__traits(compiles, b = octal!"20000000000"));
  3181. static assert(!__traits(compiles, a = octal!"1L"));
  3182. // this should pass, but it doesn't, since the int converter
  3183. // doesn't pass along its suffix to helper templates
  3184. //static assert(!__traits(compiles, a = octal!1L));
  3185. static assert(__traits(compiles, b = octal!"1L"));
  3186. static assert(__traits(compiles, b = octal!1L));
  3187. }
  3188. // emplace
  3189. /**
  3190. Given a pointer $(D chunk) to uninitialized memory (but already typed
  3191. as $(D T)), constructs an object of non-$(D class) type $(D T) at that
  3192. address.
  3193. Returns: A pointer to the newly constructed object (which is the same
  3194. as $(D chunk)).
  3195. */
  3196. T* emplace(T)(T* chunk) @safe nothrow pure
  3197. {
  3198. static assert (is(T* : void*),
  3199. format("Cannot emplace a %s because it is qualified.", T.stringof));
  3200. static assert (is(typeof({static T i;})),
  3201. format("Cannot emplace a %1$s because %1$s.this() is annotated with @disable.", T.stringof));
  3202. return emplaceInitializer(chunk);
  3203. }
  3204. version(unittest) private struct __conv_EmplaceTest
  3205. {
  3206. int i = 3;
  3207. this(int i)
  3208. {
  3209. assert(this.i == 3 && i == 5);
  3210. this.i = i;
  3211. }
  3212. this(int i, ref int j)
  3213. {
  3214. assert(i == 5 && j == 6);
  3215. this.i = i;
  3216. ++j;
  3217. }
  3218. @disable:
  3219. this();
  3220. this(this);
  3221. void opAssign();
  3222. }
  3223. version(unittest) private class __conv_EmplaceTestClass
  3224. {
  3225. int i = 3;
  3226. this(int i)
  3227. {
  3228. assert(this.i == 3 && i == 5);
  3229. this.i = i;
  3230. }
  3231. this(int i, ref int j)
  3232. {
  3233. assert(i == 5 && j == 6);
  3234. this.i = i;
  3235. ++j;
  3236. }
  3237. }
  3238. unittest
  3239. {
  3240. struct S { @disable this(); }
  3241. S s = void;
  3242. static assert(!__traits(compiles, emplace(&s)));
  3243. static assert( __traits(compiles, emplace(&s, S.init)));
  3244. }
  3245. unittest
  3246. {
  3247. interface I {}
  3248. class K : I {}
  3249. K k = void;
  3250. emplace(&k);
  3251. assert(k is null);
  3252. I i = void;
  3253. emplace(&i);
  3254. assert(i is null);
  3255. }
  3256. unittest
  3257. {
  3258. static struct S {int i = 5;}
  3259. S[2] s2 = void;
  3260. emplace(&s2);
  3261. assert(s2[0].i == 5 && s2[1].i == 5);
  3262. }
  3263. unittest
  3264. {
  3265. struct S1
  3266. {}
  3267. struct S2
  3268. {
  3269. void opAssign(S2);
  3270. }
  3271. S1 s1 = void;
  3272. S2 s2 = void;
  3273. S1[2] as1 = void;
  3274. S2[2] as2 = void;
  3275. emplace(&s1);
  3276. emplace(&s2);
  3277. emplace(&as1);
  3278. emplace(&as2);
  3279. }
  3280. unittest
  3281. {
  3282. static struct S1
  3283. {
  3284. this(this) @disable;
  3285. }
  3286. static struct S2
  3287. {
  3288. this() @disable;
  3289. }
  3290. S1[2] ss1 = void;
  3291. S2[2] ss2 = void;
  3292. static assert( __traits(compiles, emplace(&ss1)));
  3293. static assert(!__traits(compiles, emplace(&ss2)));
  3294. S1 s1 = S1.init;
  3295. S2 s2 = S2.init;
  3296. static assert(!__traits(compiles, emplace(&ss1, s1)));
  3297. static assert( __traits(compiles, emplace(&ss2, s2)));
  3298. }
  3299. unittest
  3300. {
  3301. struct S
  3302. {
  3303. immutable int i;
  3304. }
  3305. S s = void;
  3306. S[2] ss1 = void;
  3307. S[2] ss2 = void;
  3308. emplace(&s, 5);
  3309. emplace(&ss1, s);
  3310. emplace(&ss2, ss1);
  3311. }
  3312. /**
  3313. Given a pointer $(D chunk) to uninitialized memory (but already typed
  3314. as a non-class type $(D T)), constructs an object of type $(D T) at
  3315. that address from arguments $(D args).
  3316. This function can be $(D @trusted) if the corresponding constructor of
  3317. $(D T) is $(D @safe).
  3318. Returns: A pointer to the newly constructed object (which is the same
  3319. as $(D chunk)).
  3320. */
  3321. T* emplace(T, Args...)(T* chunk, auto ref Args args)
  3322. if (!is(T == struct) && Args.length == 1)
  3323. {
  3324. alias Arg = Args[0];
  3325. alias arg = args[0];
  3326. static assert (is(T* : void*),
  3327. format("Cannot emplace a %s because it is qualified.", T.stringof));
  3328. static assert(is(typeof({T t = args[0];})),
  3329. format("%s cannot be emplaced from a %s.", T.stringof, Arg.stringof));
  3330. static if (isStaticArray!T)
  3331. {
  3332. alias UArg = Unqual!Arg;
  3333. alias E = typeof(chunk.ptr[0]);
  3334. enum N = T.length;
  3335. static if (is(Arg : T))
  3336. {
  3337. //Matching static array
  3338. static if (isAssignable!(T, Arg) && !hasElaborateAssign!T)
  3339. *chunk = arg;
  3340. else static if (is(UArg == T))
  3341. {
  3342. memcpy(chunk, &arg, T.sizeof);
  3343. static if (hasElaborateCopyConstructor!T)
  3344. typeid(T).postblit(cast(void*)&chunk);
  3345. }
  3346. else
  3347. emplace(chunk, cast(T)arg);
  3348. }
  3349. else static if (is(Arg : E[]))
  3350. {
  3351. //Matching dynamic array
  3352. static if (is(typeof((*chunk)[] = arg[])) && !hasElaborateAssign!T)
  3353. (*chunk)[] = arg[];
  3354. else static if (is(UArg == E[]))
  3355. {
  3356. assert(N == chunk.length, "Array length missmatch in emplace");
  3357. memcpy(cast(void*)chunk, arg.ptr, T.sizeof);
  3358. static if (hasElaborateCopyConstructor!T)
  3359. typeid(T).postblit(cast(void*)&chunk);
  3360. }
  3361. else
  3362. emplace(chunk, cast(E[])arg);
  3363. }
  3364. else static if (is(Arg : E))
  3365. {
  3366. //Case matching single element to array.
  3367. static if (is(typeof((*chunk)[] = arg)) && !hasElaborateAssign!T)
  3368. (*chunk)[] = arg;
  3369. else static if (is(UArg == E))
  3370. {
  3371. //Note: We copy everything, and then postblit just once.
  3372. //This is as exception safe as what druntime can provide us.
  3373. foreach(i; 0 .. N)
  3374. memcpy(cast(void*)(chunk.ptr + i), &arg, E.sizeof);
  3375. static if (hasElaborateCopyConstructor!T)
  3376. typeid(T).postblit(chunk);
  3377. }
  3378. else
  3379. //Alias this. Coerce.
  3380. emplace(chunk, cast(E)arg);
  3381. }
  3382. else static if (is(typeof(emplace(chunk.ptr, arg))))
  3383. {
  3384. //Final case for everything else:
  3385. //Types that don't match (int to uint[2])
  3386. //Recursion for multidimensions
  3387. static if (is(typeof((*chunk)[] = arg)) && !hasElaborateAssign!T)
  3388. (*chunk)[] = arg;
  3389. foreach(i; 0 .. N)
  3390. emplace(chunk.ptr + i, arg);
  3391. }
  3392. else
  3393. static assert(0, format("Sorry, this implementation doesn't know how to emplace a %s with a %s", T.stringof, Arg.stringof));
  3394. return chunk;
  3395. }
  3396. else
  3397. {
  3398. *chunk = arg;
  3399. return chunk;
  3400. }
  3401. }
  3402. unittest
  3403. {
  3404. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  3405. int a;
  3406. int b = 42;
  3407. assert(*emplace!int(&a, b) == 42);
  3408. }
  3409. unittest
  3410. {
  3411. interface I {}
  3412. class K : I {}
  3413. K k = null, k2 = new K;
  3414. assert(k !is k2);
  3415. emplace!K(&k, k2);
  3416. assert(k is k2);
  3417. I i = null;
  3418. assert(i !is k);
  3419. emplace!I(&i, k);
  3420. assert(i is k);
  3421. }
  3422. unittest
  3423. {
  3424. static struct S
  3425. {
  3426. int i = 5;
  3427. void opAssign(S){assert(0);}
  3428. }
  3429. S[2] sa = void;
  3430. S[2] sb;
  3431. emplace(&sa, sb);
  3432. assert(sa[0].i == 5 && sa[1].i == 5);
  3433. }
  3434. /// ditto
  3435. T* emplace(T, Args...)(T* chunk, auto ref Args args)
  3436. if (is(T == struct))
  3437. {
  3438. static assert (is(T* : void*),
  3439. format("Cannot emplace a %s because it is qualified.", T.stringof));
  3440. static if (Args.length == 1 && is(Args[0] : T) &&
  3441. is (typeof({T t = args[0];})) //Check for legal postblit
  3442. )
  3443. {
  3444. static if (is(T == Unqual!(Args[0])))
  3445. {
  3446. //Types match exactly: we postblit
  3447. static if (isAssignable!T && !hasElaborateAssign!T)
  3448. *chunk = args[0];
  3449. else
  3450. {
  3451. memcpy(chunk, &args[0], T.sizeof);
  3452. static if (hasElaborateCopyConstructor!T)
  3453. typeid(T).postblit(chunk);
  3454. }
  3455. }
  3456. else
  3457. //Alias this. Coerce to type T.
  3458. emplace(chunk, cast(T)args[0]);
  3459. }
  3460. else static if (is(typeof(chunk.__ctor(args))))
  3461. {
  3462. // T defines a genuine constructor accepting args
  3463. // Go the classic route: write .init first, then call ctor
  3464. emplaceInitializer(chunk);
  3465. chunk.__ctor(args);
  3466. }
  3467. else static if (is(typeof(T.opCall(args))))
  3468. {
  3469. //Can be built calling opCall
  3470. emplaceOpCaller(chunk, args); //emplaceOpCaller is deprecated
  3471. }
  3472. else static if (is(typeof(T(args))))
  3473. {
  3474. // Struct without constructor that has one matching field for
  3475. // each argument. Individually emplace each field
  3476. emplaceInitializer(chunk);
  3477. foreach (i, ref field; chunk.tupleof[0 .. Args.length])
  3478. emplace(emplaceGetAddr(field), args[i]);
  3479. }
  3480. else
  3481. {
  3482. //We can't emplace. Try to diagnose a disabled postblit.
  3483. static assert(!(Args.length == 1 && is(Args[0] : T)),
  3484. format("Cannot emplace a %1$s because %1$s.this(this) is annotated with @disable.", T.stringof));
  3485. //We can't emplace.
  3486. static assert(false,
  3487. format("%s cannot be emplaced from %s.", T.stringof, Args[].stringof));
  3488. }
  3489. return chunk;
  3490. }
  3491. //emplace helper functions
  3492. private T* emplaceInitializer(T)(T* chunk) @trusted pure nothrow
  3493. {
  3494. static if (isAssignable!T && !hasElaborateAssign!T)
  3495. *chunk = T.init;
  3496. else
  3497. {
  3498. static immutable T init = T.init;
  3499. memcpy(chunk, &init, T.sizeof);
  3500. }
  3501. return chunk;
  3502. }
  3503. private deprecated("Using static opCall for emplace is deprecated. Plase use emplace(chunk, T(args)) instead.")
  3504. T* emplaceOpCaller(T, Args...)(T* chunk, auto ref Args args)
  3505. {
  3506. static assert (is(typeof({T t = T.opCall(args);})),
  3507. format("%s.opCall does not return adequate data for construction.", T.stringof));
  3508. return emplace(chunk, chunk.opCall(args));
  3509. }
  3510. private
  3511. {
  3512. //Helper to keep simple aggregate emplace safe.
  3513. auto emplaceGetAddr(T)(ref T t) @trusted
  3514. if (is(T == Unqual!T))
  3515. {
  3516. return &t;
  3517. }
  3518. auto emplaceGetAddr(T)(ref T t)
  3519. if (!is(T == Unqual!T))
  3520. {
  3521. return cast(Unqual!T*)&t;
  3522. }
  3523. }
  3524. // Test constructor branch
  3525. unittest
  3526. {
  3527. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  3528. struct S
  3529. {
  3530. double x = 5, y = 6;
  3531. this(int a, int b)
  3532. {
  3533. assert(x == 5 && y == 6);
  3534. x = a;
  3535. y = b;
  3536. }
  3537. }
  3538. auto s1 = new void[S.sizeof];
  3539. auto s2 = S(42, 43);
  3540. assert(*emplace!S(cast(S*) s1.ptr, s2) == s2);
  3541. assert(*emplace!S(cast(S*) s1, 44, 45) == S(44, 45));
  3542. }
  3543. unittest
  3544. {
  3545. __conv_EmplaceTest k = void;
  3546. emplace(&k, 5);
  3547. assert(k.i == 5);
  3548. }
  3549. unittest
  3550. {
  3551. int var = 6;
  3552. __conv_EmplaceTest k = void;
  3553. emplace(&k, 5, var);
  3554. assert(k.i == 5);
  3555. assert(var == 7);
  3556. }
  3557. // Test matching fields branch
  3558. unittest
  3559. {
  3560. struct S { uint n; }
  3561. S s;
  3562. emplace!S(&s, 2U);
  3563. assert(s.n == 2);
  3564. }
  3565. unittest
  3566. {
  3567. struct S { int a, b; this(int){} }
  3568. S s;
  3569. static assert(!__traits(compiles, emplace!S(&s, 2, 3)));
  3570. }
  3571. unittest
  3572. {
  3573. struct S { int a, b = 7; }
  3574. S s1 = void, s2 = void;
  3575. emplace!S(&s1, 2);
  3576. assert(s1.a == 2 && s1.b == 7);
  3577. emplace!S(&s2, 2, 3);
  3578. assert(s2.a == 2 && s2.b == 3);
  3579. }
  3580. //opAssign
  3581. unittest
  3582. {
  3583. static struct S
  3584. {
  3585. int i = 5;
  3586. void opAssign(int){assert(0);}
  3587. void opAssign(S){assert(0);}
  3588. }
  3589. S sa1 = void;
  3590. S sa2 = void;
  3591. S sb1 = S(1);
  3592. emplace(&sa1, sb1);
  3593. emplace(&sa2, 2);
  3594. assert(sa1.i == 1);
  3595. assert(sa2.i == 2);
  3596. }
  3597. //postblit precedence
  3598. unittest
  3599. {
  3600. //Works, but breaks in "-w -O" because of @@@9332@@@.
  3601. //Uncomment test when 9332 is fixed.
  3602. static struct S
  3603. {
  3604. int i;
  3605. this(S other){assert(false);}
  3606. this(int i){this.i = i;}
  3607. this(this){}
  3608. }
  3609. S a = void;
  3610. assert(is(typeof({S b = a;}))); //Postblit
  3611. assert(is(typeof({S b = S(a);}))); //Constructor
  3612. auto b = S(5);
  3613. emplace(&a, b);
  3614. assert(a.i == 5);
  3615. static struct S2
  3616. {
  3617. int* p;
  3618. this(const S2){};
  3619. }
  3620. static assert(!is(immutable S2 : S2));
  3621. S2 s2 = void;
  3622. immutable is2 = (immutable S2).init;
  3623. emplace(&s2, is2);
  3624. }
  3625. //nested structs and postblit
  3626. unittest
  3627. {
  3628. static struct S
  3629. {
  3630. int* p;
  3631. this(int i){p = [i].ptr;}
  3632. this(this)
  3633. {
  3634. if (p)
  3635. p = [*p].ptr;
  3636. }
  3637. }
  3638. static struct SS
  3639. {
  3640. S s;
  3641. void opAssign(const SS)
  3642. {
  3643. assert(0);
  3644. }
  3645. }
  3646. SS ssa = void;
  3647. SS ssb = SS(S(5));
  3648. emplace(&ssa, ssb);
  3649. assert(*ssa.s.p == 5);
  3650. assert(ssa.s.p != ssb.s.p);
  3651. }
  3652. //disabled postblit
  3653. unittest
  3654. {
  3655. static struct S1
  3656. {
  3657. int i;
  3658. @disable this(this);
  3659. }
  3660. S1 s1 = void;
  3661. static assert( __traits(compiles, emplace(&s1, 1)));
  3662. static assert(!__traits(compiles, emplace(&s1, S1.init)));
  3663. static struct S2
  3664. {
  3665. int i;
  3666. @disable this(this);
  3667. this(ref S2){}
  3668. }
  3669. S2 s2 = void;
  3670. static assert(!__traits(compiles, emplace(&s2, 1)));
  3671. static assert( __traits(compiles, emplace(&s2, S2.init)));
  3672. static struct SS1
  3673. {
  3674. S1 s;
  3675. }
  3676. SS1 ss1 = void;
  3677. static assert( __traits(compiles, emplace(&ss1)));
  3678. static assert(!__traits(compiles, emplace(&ss1, SS1.init)));
  3679. static struct SS2
  3680. {
  3681. S2 s;
  3682. }
  3683. SS2 ss2 = void;
  3684. static assert( __traits(compiles, emplace(&ss2)));
  3685. static assert(!__traits(compiles, emplace(&ss2, SS2.init)));
  3686. // SS1 sss1 = s1; //This doesn't compile
  3687. // SS1 sss1 = SS1(s1); //This doesn't compile
  3688. // So emplace shouldn't compile either
  3689. static assert(!__traits(compiles, emplace(&sss1, s1)));
  3690. static assert(!__traits(compiles, emplace(&sss2, s2)));
  3691. }
  3692. //Imutability
  3693. unittest
  3694. {
  3695. //Castable immutability
  3696. {
  3697. static struct S1
  3698. {
  3699. int i;
  3700. }
  3701. static assert(is( immutable(S1) : S1));
  3702. S1 sa = void;
  3703. auto sb = immutable(S1)(5);
  3704. emplace(&sa, sb);
  3705. assert(sa.i == 5);
  3706. }
  3707. //Un-castable immutability
  3708. {
  3709. static struct S2
  3710. {
  3711. int* p;
  3712. }
  3713. static assert(!is(immutable(S2) : S2));
  3714. S2 sa = void;
  3715. auto sb = immutable(S2)(null);
  3716. assert(!__traits(compiles, emplace(&sa, sb)));
  3717. }
  3718. }
  3719. unittest
  3720. {
  3721. static struct S
  3722. {
  3723. immutable int i;
  3724. immutable(int)* j;
  3725. }
  3726. S s = void;
  3727. emplace(&s, 1, null);
  3728. emplace(&s, 2, &s.i);
  3729. assert(s is S(2, &s.i));
  3730. }
  3731. //Context pointer
  3732. unittest
  3733. {
  3734. int i = 0;
  3735. {
  3736. struct S1
  3737. {
  3738. void foo(){++i;}
  3739. }
  3740. S1 sa = void;
  3741. S1 sb;
  3742. emplace(&sa, sb);
  3743. sa.foo();
  3744. assert(i == 1);
  3745. }
  3746. {
  3747. struct S2
  3748. {
  3749. void foo(){++i;}
  3750. this(this){}
  3751. }
  3752. S2 sa = void;
  3753. S2 sb;
  3754. emplace(&sa, sb);
  3755. sa.foo();
  3756. assert(i == 2);
  3757. }
  3758. ////NOTE: THESE WILL COMPILE
  3759. ////But will not correctly emplace the context pointer
  3760. ////The problem lies with voldemort, and not emplace.
  3761. //{
  3762. // struct S3
  3763. // {
  3764. // int k;
  3765. // void foo(){++i;}
  3766. // }
  3767. //}
  3768. //S3 s3 = void;
  3769. //emplace(&s3); //S3.init has no context pointer information
  3770. //emplace(&s3, 1); //No way to obtain context pointer once inside emplace
  3771. }
  3772. //Alias this
  3773. unittest
  3774. {
  3775. static struct S
  3776. {
  3777. int i;
  3778. }
  3779. //By Ref
  3780. {
  3781. static struct SS1
  3782. {
  3783. int j;
  3784. S s;
  3785. alias s this;
  3786. }
  3787. S s = void;
  3788. SS1 ss = SS1(1, S(2));
  3789. emplace(&s, ss);
  3790. assert(s.i == 2);
  3791. }
  3792. //By Value
  3793. {
  3794. static struct SS2
  3795. {
  3796. int j;
  3797. S s;
  3798. S foo() @property{return s;}
  3799. alias foo this;
  3800. }
  3801. S s = void;
  3802. SS2 ss = SS2(1, S(2));
  3803. emplace(&s, ss);
  3804. assert(s.i == 2);
  3805. }
  3806. }
  3807. version(unittest)
  3808. {
  3809. //Ambiguity
  3810. struct __std_conv_S
  3811. {
  3812. int i;
  3813. this(__std_conv_SS ss) {assert(0);}
  3814. static opCall(__std_conv_SS ss)
  3815. {
  3816. __std_conv_S s; s.i = ss.j;
  3817. return s;
  3818. }
  3819. }
  3820. struct __std_conv_SS
  3821. {
  3822. int j;
  3823. __std_conv_S s;
  3824. ref __std_conv_S foo() @property {s.i = j; return s;}
  3825. alias foo this;
  3826. }
  3827. static assert(is(__std_conv_SS : __std_conv_S));
  3828. unittest
  3829. {
  3830. __std_conv_S s = void;
  3831. __std_conv_SS ss = __std_conv_SS(1);
  3832. __std_conv_S sTest1 = ss; //this calls "SS alias this" (and not "S.this(SS)")
  3833. emplace(&s, ss); //"alias this" should take precedence in emplace over "opCall"
  3834. assert(s.i == 1);
  3835. }
  3836. }
  3837. //Nested classes
  3838. unittest
  3839. {
  3840. class A{}
  3841. static struct S
  3842. {
  3843. A a;
  3844. }
  3845. S s1 = void;
  3846. S s2 = S(new A);
  3847. emplace(&s1, s2);
  3848. assert(s1.a is s2.a);
  3849. }
  3850. //safety & nothrow & CTFE
  3851. unittest
  3852. {
  3853. //emplace should be safe for anything with no elaborate opassign
  3854. static struct S1
  3855. {
  3856. int i;
  3857. }
  3858. static struct S2
  3859. {
  3860. int i;
  3861. this(int j)@safe nothrow{i = j;}
  3862. }
  3863. int i;
  3864. S1 s1 = void;
  3865. S2 s2 = void;
  3866. auto pi = &i;
  3867. auto ps1 = &s1;
  3868. auto ps2 = &s2;
  3869. void foo() @safe nothrow
  3870. {
  3871. emplace(pi);
  3872. emplace(pi, 5);
  3873. emplace(ps1);
  3874. emplace(ps1, 5);
  3875. emplace(ps1, S1.init);
  3876. emplace(ps2);
  3877. emplace(ps2, 5);
  3878. emplace(ps2, S2.init);
  3879. }
  3880. T bar(T)() @property
  3881. {
  3882. T t/+ = void+/; //CTFE void illegal
  3883. emplace(&t, 5);
  3884. return t;
  3885. }
  3886. enum a = bar!int;
  3887. enum b = bar!S1;
  3888. enum c = bar!S2;
  3889. }
  3890. unittest
  3891. {
  3892. struct S
  3893. {
  3894. int[2] get(){return [1, 2];}
  3895. alias get this;
  3896. }
  3897. struct SS
  3898. {
  3899. int[2] ii;
  3900. }
  3901. struct ISS
  3902. {
  3903. int[2] ii;
  3904. }
  3905. S s;
  3906. SS ss = void;
  3907. ISS iss = void;
  3908. emplace(&ss, s);
  3909. emplace(&iss, s);
  3910. assert(ss.ii == [1, 2]);
  3911. assert(iss.ii == [1, 2]);
  3912. }
  3913. //disable opAssign
  3914. unittest
  3915. {
  3916. static struct S
  3917. {
  3918. @disable void opAssign(S);
  3919. }
  3920. S s;
  3921. emplace(&s, S.init);
  3922. }
  3923. //opCall
  3924. unittest
  3925. {
  3926. int i;
  3927. //Without constructor
  3928. {
  3929. static struct S1
  3930. {
  3931. int i;
  3932. static S1 opCall(int*){assert(0);}
  3933. }
  3934. S1 s = void;
  3935. static assert(!__traits(compiles, emplace(&s, 1)));
  3936. static assert( __traits(compiles, emplace(&s, &i))); //(works, but deprected)
  3937. }
  3938. //With constructor
  3939. {
  3940. static struct S2
  3941. {
  3942. int i = 0;
  3943. static S2 opCall(int*){assert(0);}
  3944. static S2 opCall(int){assert(0);}
  3945. this(int i){this.i = i;}
  3946. }
  3947. S2 s = void;
  3948. static assert( __traits(compiles, emplace(&s, 1))); //(works, but deprected)
  3949. static assert( __traits(compiles, emplace(&s, &i))); //(works, but deprected)
  3950. emplace(&s, 1);
  3951. assert(s.i == 1);
  3952. }
  3953. //With postblit ambiguity
  3954. {
  3955. static struct S3
  3956. {
  3957. int i = 0;
  3958. static S3 opCall(ref S3){assert(0);}
  3959. }
  3960. S3 s = void;
  3961. static assert( __traits(compiles, emplace(&s, S3.init)));
  3962. }
  3963. }
  3964. unittest //@@@9559@@@
  3965. {
  3966. alias Nullable!int I;
  3967. auto ints = [0, 1, 2].map!(i => i & 1 ? I.init : I(i))();
  3968. auto asArray = std.array.array(ints);
  3969. }
  3970. unittest //http://forum.dlang.org/thread/nxbdgtdlmwscocbiypjs@forum.dlang.org
  3971. {
  3972. import std.array : array;
  3973. import std.datetime : SysTime, UTC;
  3974. import std.math : isNaN;
  3975. static struct A
  3976. {
  3977. double i;
  3978. }
  3979. static struct B
  3980. {
  3981. invariant()
  3982. {
  3983. if(j == 0)
  3984. assert(a.i.isNaN, "why is 'j' zero?? and i is not NaN?");
  3985. else
  3986. assert(!a.i.isNaN);
  3987. }
  3988. SysTime when; // comment this line avoid the breakage
  3989. int j;
  3990. A a;
  3991. }
  3992. B b1 = B.init;
  3993. assert(&b1); // verify that default eyes invariants are ok;
  3994. auto b2 = B(SysTime(0, UTC()), 1, A(1));
  3995. assert(&b2);
  3996. auto b3 = B(SysTime(0, UTC()), 1, A(1));
  3997. assert(&b3);
  3998. auto arr = [b2, b3];
  3999. assert(arr[0].j == 1);
  4000. assert(arr[1].j == 1);
  4001. auto a2 = arr.array(); // << bang, invariant is raised, also if b2 and b3 are good
  4002. }
  4003. //static arrays
  4004. unittest
  4005. {
  4006. static struct S
  4007. {
  4008. int[2] ii;
  4009. }
  4010. static struct IS
  4011. {
  4012. immutable int[2] ii;
  4013. }
  4014. int[2] ii;
  4015. S s = void;
  4016. IS ims = void;
  4017. ubyte ub = 2;
  4018. emplace(&s, ub);
  4019. emplace(&s, ii);
  4020. emplace(&ims, ub);
  4021. emplace(&ims, ii);
  4022. uint[2] uu;
  4023. static assert(!__traits(compiles, {S ss = S(uu);}));
  4024. static assert(!__traits(compiles, emplace(&s, uu)));
  4025. }
  4026. unittest
  4027. {
  4028. int[2] sii;
  4029. int[2] sii2;
  4030. uint[2] uii;
  4031. uint[2] uii2;
  4032. emplace(&sii, 1);
  4033. emplace(&sii, 1U);
  4034. emplace(&uii, 1);
  4035. emplace(&uii, 1U);
  4036. emplace(&sii, sii2);
  4037. //emplace(&sii, uii2); //Sorry, this implementation doesn't know how to...
  4038. //emplace(&uii, sii2); //Sorry, this implementation doesn't know how to...
  4039. emplace(&uii, uii2);
  4040. emplace(&sii, sii2[]);
  4041. //emplace(&sii, uii2[]); //Sorry, this implementation doesn't know how to...
  4042. //emplace(&uii, sii2[]); //Sorry, this implementation doesn't know how to...
  4043. emplace(&uii, uii2[]);
  4044. }
  4045. unittest
  4046. {
  4047. bool allowDestruction = false;
  4048. struct S
  4049. {
  4050. int i;
  4051. this(this){}
  4052. ~this(){assert(allowDestruction);}
  4053. }
  4054. S s = S(1);
  4055. S[2] ss1 = void;
  4056. S[2] ss2 = void;
  4057. S[2] ss3 = void;
  4058. emplace(&ss1, s);
  4059. emplace(&ss2, ss1);
  4060. emplace(&ss3, ss2[]);
  4061. assert(ss1[1] == s);
  4062. assert(ss2[1] == s);
  4063. assert(ss3[1] == s);
  4064. allowDestruction = true;
  4065. }
  4066. unittest
  4067. {
  4068. //Checks postblit, construction, and context pointer
  4069. int count = 0;
  4070. struct S
  4071. {
  4072. this(this)
  4073. {
  4074. ++count;
  4075. }
  4076. ~this()
  4077. {
  4078. --count;
  4079. }
  4080. }
  4081. S s;
  4082. {
  4083. S[4] ss = void;
  4084. emplace(&ss, s);
  4085. assert(count == 4);
  4086. }
  4087. assert(count == 0);
  4088. }
  4089. unittest
  4090. {
  4091. struct S
  4092. {
  4093. int i;
  4094. }
  4095. S s;
  4096. S[2][2][2] sss = void;
  4097. emplace(&sss, s);
  4098. }
  4099. private void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment, string typeName)
  4100. {
  4101. enforceEx!ConvException(chunk.length >= typeSize,
  4102. format("emplace: Chunk size too small: %s < %s size = %s",
  4103. chunk.length, typeName, typeSize));
  4104. enforceEx!ConvException((cast(size_t) chunk.ptr) % typeAlignment == 0,
  4105. format("emplace: Misaligned memory block (0x%X): it must be %s-byte aligned for type %s",
  4106. chunk.ptr, typeAlignment, typeName));
  4107. }
  4108. /**
  4109. Given a raw memory area $(D chunk), constructs an object of $(D class)
  4110. type $(D T) at that address. The constructor is passed the arguments
  4111. $(D Args). The $(D chunk) must be as least as large as $(D T) needs
  4112. and should have an alignment multiple of $(D T)'s alignment. (The size
  4113. of a $(D class) instance is obtained by using $(D
  4114. __traits(classInstanceSize, T))).
  4115. This function can be $(D @trusted) if the corresponding constructor of
  4116. $(D T) is $(D @safe).
  4117. Returns: A pointer to the newly constructed object.
  4118. */
  4119. T emplace(T, Args...)(void[] chunk, auto ref Args args)
  4120. if (is(T == class))
  4121. {
  4122. enum classSize = __traits(classInstanceSize, T);
  4123. testEmplaceChunk(chunk, classSize, classInstanceAlignment!T, T.stringof);
  4124. auto result = cast(T) chunk.ptr;
  4125. // Initialize the object in its pre-ctor state
  4126. (cast(byte[]) chunk)[0 .. classSize] = typeid(T).init[];
  4127. // Call the ctor if any
  4128. static if (is(typeof(result.__ctor(args))))
  4129. {
  4130. // T defines a genuine constructor accepting args
  4131. // Go the classic route: write .init first, then call ctor
  4132. result.__ctor(args);
  4133. }
  4134. else
  4135. {
  4136. static assert(args.length == 0 && !is(typeof(&T.__ctor)),
  4137. "Don't know how to initialize an object of type "
  4138. ~ T.stringof ~ " with arguments " ~ Args.stringof);
  4139. }
  4140. return result;
  4141. }
  4142. unittest
  4143. {
  4144. int var = 6;
  4145. auto k = emplace!__conv_EmplaceTestClass(new void[__traits(classInstanceSize, __conv_EmplaceTestClass)], 5, var);
  4146. assert(k.i == 5);
  4147. assert(var == 7);
  4148. }
  4149. /**
  4150. Given a raw memory area $(D chunk), constructs an object of non-$(D
  4151. class) type $(D T) at that address. The constructor is passed the
  4152. arguments $(D args), if any. The $(D chunk) must be as least as large
  4153. as $(D T) needs and should have an alignment multiple of $(D T)'s
  4154. alignment.
  4155. This function can be $(D @trusted) if the corresponding constructor of
  4156. $(D T) is $(D @safe).
  4157. Returns: A pointer to the newly constructed object.
  4158. */
  4159. T* emplace(T, Args...)(void[] chunk, auto ref Args args)
  4160. if (!is(T == class))
  4161. {
  4162. testEmplaceChunk(chunk, T.sizeof, T.alignof, T.stringof);
  4163. return emplace(cast(T*) chunk.ptr, args);
  4164. }
  4165. unittest
  4166. {
  4167. struct S
  4168. {
  4169. int a, b;
  4170. }
  4171. auto p = new void[S.sizeof];
  4172. S s;
  4173. s.a = 42;
  4174. s.b = 43;
  4175. auto s1 = emplace!S(p, s);
  4176. assert(s1.a == 42 && s1.b == 43);
  4177. }
  4178. unittest
  4179. {
  4180. int var = 6;
  4181. auto k = emplace!__conv_EmplaceTest(new void[__conv_EmplaceTest.sizeof], 5, var);
  4182. assert(k.i == 5);
  4183. assert(var == 7);
  4184. }
  4185. unittest
  4186. {
  4187. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  4188. class A
  4189. {
  4190. int x = 5;
  4191. int y = 42;
  4192. this(int z)
  4193. {
  4194. assert(x == 5 && y == 42);
  4195. x = y = z;
  4196. }
  4197. }
  4198. void[] buf;
  4199. static byte[__traits(classInstanceSize, A)] sbuf;
  4200. buf = sbuf[];
  4201. auto a = emplace!A(buf, 55);
  4202. assert(a.x == 55 && a.y == 55);
  4203. // emplace in bigger buffer
  4204. buf = new byte[](__traits(classInstanceSize, A) + 10);
  4205. a = emplace!A(buf, 55);
  4206. assert(a.x == 55 && a.y == 55);
  4207. // need ctor args
  4208. static assert(!is(typeof(emplace!A(buf))));
  4209. }
  4210. unittest
  4211. {
  4212. debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded.");
  4213. // Check fix for http://d.puremagic.com/issues/show_bug.cgi?id=2971
  4214. assert(equal(map!(to!int)(["42", "34", "345"]), [42, 34, 345]));
  4215. }
  4216. // Undocumented for the time being
  4217. void toTextRange(T, W)(T value, W writer)
  4218. if (isIntegral!T && isOutputRange!(W, char))
  4219. {
  4220. char[value.sizeof * 4] buffer = void;
  4221. uint i = cast(uint) (buffer.length - 1);
  4222. bool negative = value < 0;
  4223. Unqual!(Unsigned!T) v = negative ? -value : value;
  4224. while (v >= 10)
  4225. {
  4226. auto c = cast(uint) (v % 10);
  4227. v /= 10;
  4228. buffer[i--] = cast(char) (c + '0');
  4229. }
  4230. buffer[i] = cast(char) (v + '0'); //hexDigits[cast(uint) v];
  4231. if (negative)
  4232. buffer[--i] = '-';
  4233. put(writer, buffer[i .. $]);
  4234. }
  4235. unittest
  4236. {
  4237. auto result = appender!(char[])();
  4238. toTextRange(-1, result);
  4239. assert(result.data == "-1");
  4240. }
  4241. /**
  4242. Returns the corresponding unsigned value for $(D x) (e.g. if $(D x) has type
  4243. $(D int), it returns $(D cast(uint) x)). The advantage compared to the cast
  4244. is that you do not need to rewrite the cast if $(D x) later changes type
  4245. (e.g from $(D int) to $(D long)).
  4246. Note that the result is always mutable even if the original type was const
  4247. or immutable. In order to retain the constness, use $(XREF traits, Unsigned).
  4248. */
  4249. auto unsigned(T)(T x) if (isIntegral!T)
  4250. {
  4251. return cast(Unqual!(Unsigned!T))x;
  4252. }
  4253. ///
  4254. unittest
  4255. {
  4256. uint s = 42;
  4257. auto u1 = unsigned(s); //not qualified
  4258. Unsigned!(typeof(s)) u2 = unsigned(s); //same qualification
  4259. immutable u3 = unsigned(s); //totally qualified
  4260. }
  4261. unittest
  4262. {
  4263. foreach(T; TypeTuple!(byte, ubyte))
  4264. {
  4265. static assert(is(typeof(unsigned(cast(T)1)) == ubyte));
  4266. static assert(is(typeof(unsigned(cast(const T)1)) == ubyte));
  4267. static assert(is(typeof(unsigned(cast(immutable T)1)) == ubyte));
  4268. }
  4269. foreach(T; TypeTuple!(short, ushort))
  4270. {
  4271. static assert(is(typeof(unsigned(cast(T)1)) == ushort));
  4272. static assert(is(typeof(unsigned(cast(const T)1)) == ushort));
  4273. static assert(is(typeof(unsigned(cast(immutable T)1)) == ushort));
  4274. }
  4275. foreach(T; TypeTuple!(int, uint))
  4276. {
  4277. static assert(is(typeof(unsigned(cast(T)1)) == uint));
  4278. static assert(is(typeof(unsigned(cast(const T)1)) == uint));
  4279. static assert(is(typeof(unsigned(cast(immutable T)1)) == uint));
  4280. }
  4281. foreach(T; TypeTuple!(long, ulong))
  4282. {
  4283. static assert(is(typeof(unsigned(cast(T)1)) == ulong));
  4284. static assert(is(typeof(unsigned(cast(const T)1)) == ulong));
  4285. static assert(is(typeof(unsigned(cast(immutable T)1)) == ulong));
  4286. }
  4287. }
  4288. auto unsigned(T)(T x) if (isSomeChar!T)
  4289. {
  4290. // All characters are unsigned
  4291. static assert(T.min == 0);
  4292. return cast(Unqual!T) x;
  4293. }
  4294. unittest
  4295. {
  4296. foreach(T; TypeTuple!(char, wchar, dchar))
  4297. {
  4298. static assert(is(typeof(unsigned(cast(T)'A')) == T));
  4299. static assert(is(typeof(unsigned(cast(const T)'A')) == T));
  4300. static assert(is(typeof(unsigned(cast(immutable T)'A')) == T));
  4301. }
  4302. }
  4303. /**
  4304. Returns the corresponding signed value for $(D x) (e.g. if $(D x) has type
  4305. $(D uint), it returns $(D cast(int) x)). The advantage compared to the cast
  4306. is that you do not need to rewrite the cast if $(D x) later changes type
  4307. (e.g from $(D uint) to $(D ulong)).
  4308. Note that the result is always mutable even if the original type was const
  4309. or immutable. In order to retain the constness, use $(XREF traits, Signed).
  4310. */
  4311. auto signed(T)(T x) if (isIntegral!T)
  4312. {
  4313. return cast(Unqual!(Signed!T))x;
  4314. }
  4315. ///
  4316. unittest
  4317. {
  4318. uint u = 42;
  4319. auto s1 = unsigned(u); //not qualified
  4320. Unsigned!(typeof(u)) s2 = unsigned(u); //same qualification
  4321. immutable s3 = unsigned(u); //totally qualified
  4322. }
  4323. unittest
  4324. {
  4325. foreach(T; TypeTuple!(byte, ubyte))
  4326. {
  4327. static assert(is(typeof(signed(cast(T)1)) == byte));
  4328. static assert(is(typeof(signed(cast(const T)1)) == byte));
  4329. static assert(is(typeof(signed(cast(immutable T)1)) == byte));
  4330. }
  4331. foreach(T; TypeTuple!(short, ushort))
  4332. {
  4333. static assert(is(typeof(signed(cast(T)1)) == short));
  4334. static assert(is(typeof(signed(cast(const T)1)) == short));
  4335. static assert(is(typeof(signed(cast(immutable T)1)) == short));
  4336. }
  4337. foreach(T; TypeTuple!(int, uint))
  4338. {
  4339. static assert(is(typeof(signed(cast(T)1)) == int));
  4340. static assert(is(typeof(signed(cast(const T)1)) == int));
  4341. static assert(is(typeof(signed(cast(immutable T)1)) == int));
  4342. }
  4343. foreach(T; TypeTuple!(long, ulong))
  4344. {
  4345. static assert(is(typeof(signed(cast(T)1)) == long));
  4346. static assert(is(typeof(signed(cast(const T)1)) == long));
  4347. static assert(is(typeof(signed(cast(immutable T)1)) == long));
  4348. }
  4349. }
  4350. unittest
  4351. {
  4352. // issue 10874
  4353. enum Test { a = 0 }
  4354. ulong l = 0;
  4355. auto t = l.to!Test;
  4356. }