slsr: Use simple_dce_from_worklist in SLSR [PR116554]
[official-gcc.git] / libphobos / libdruntime / rt / aApplyR.d
blob560025c636d8ce1858eff91ccd9e291e9c28aabd
1 /**
2 * This code handles decoding UTF strings for `foreach_reverse` loops.
4 * Copyright: Copyright Digital Mars 2004 - 2010.
5 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 * Authors: Walter Bright, Sean Kelly
7 * Source: $(DRUNTIMESRC rt/_aApplyR.d)
8 */
9 module rt.aApplyR;
11 import core.internal.utf;
13 /**********************************************/
14 /* 1 argument versions */
16 // Note: dg is extern(D), but _aApplyRcd() is extern(C)
18 /**
19 Delegate type corresponding to transformed loop body
21 The parameter is a pointer to the current `char`, `wchar` or `dchar`
23 Returns: non-zero when a `break` statement is hit
25 extern (D) alias dg_t = int delegate(void* c);
27 /**
28 Same as `_aApplyXXX` functions, but for `foreach_reverse`
30 Params:
31 aa = input string
32 dg = foreach body transformed into a delegate, similar to `opApply`
34 Returns:
35 non-zero when the loop was exited through a `break`
37 extern (C) int _aApplyRcd1(scope const(char)[] aa, dg_t dg)
38 { int result;
40 debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
41 for (size_t i = aa.length; i != 0; )
42 { dchar d;
44 i--;
45 d = aa[i];
46 if (d & 0x80)
47 { char c = cast(char)d;
48 uint j;
49 uint m = 0x3F;
50 d = 0;
51 while ((c & 0xC0) != 0xC0)
52 { if (i == 0)
53 onUnicodeError("Invalid UTF-8 sequence", 0);
54 i--;
55 d |= (c & 0x3F) << j;
56 j += 6;
57 m >>= 1;
58 c = aa[i];
60 d |= (c & m) << j;
62 result = dg(cast(void *)&d);
63 if (result)
64 break;
66 return result;
69 unittest
71 debug(apply) printf("_aApplyRcd1.unittest\n");
73 auto s = "hello"c[];
74 int i;
76 foreach_reverse (dchar d; s)
78 switch (i)
80 case 0: assert(d == 'o'); break;
81 case 1: assert(d == 'l'); break;
82 case 2: assert(d == 'l'); break;
83 case 3: assert(d == 'e'); break;
84 case 4: assert(d == 'h'); break;
85 default: assert(0);
87 i++;
89 assert(i == 5);
91 s = "a\u1234\U000A0456b";
92 i = 0;
93 foreach_reverse (dchar d; s)
95 //printf("i = %d, d = %x\n", i, d);
96 switch (i)
98 case 0: assert(d == 'b'); break;
99 case 1: assert(d == '\U000A0456'); break;
100 case 2: assert(d == '\u1234'); break;
101 case 3: assert(d == 'a'); break;
102 default: assert(0);
104 i++;
106 assert(i == 4);
109 /// ditto
110 extern (C) int _aApplyRwd1(scope const(wchar)[] aa, dg_t dg)
111 { int result;
113 debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
114 for (size_t i = aa.length; i != 0; )
115 { dchar d;
117 i--;
118 d = aa[i];
119 if (d >= 0xDC00 && d <= 0xDFFF)
120 { if (i == 0)
121 onUnicodeError("Invalid UTF-16 sequence", 0);
122 i--;
123 d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
125 result = dg(cast(void *)&d);
126 if (result)
127 break;
129 return result;
132 unittest
134 debug(apply) printf("_aApplyRwd1.unittest\n");
136 auto s = "hello"w[];
137 int i;
139 foreach_reverse (dchar d; s)
141 switch (i)
143 case 0: assert(d == 'o'); break;
144 case 1: assert(d == 'l'); break;
145 case 2: assert(d == 'l'); break;
146 case 3: assert(d == 'e'); break;
147 case 4: assert(d == 'h'); break;
148 default: assert(0);
150 i++;
152 assert(i == 5);
154 s = "a\u1234\U000A0456b";
155 i = 0;
156 foreach_reverse (dchar d; s)
158 //printf("i = %d, d = %x\n", i, d);
159 switch (i)
161 case 0: assert(d == 'b'); break;
162 case 1: assert(d == '\U000A0456'); break;
163 case 2: assert(d == '\u1234'); break;
164 case 3: assert(d == 'a'); break;
165 default: assert(0);
167 i++;
169 assert(i == 4);
172 /// ditto
173 extern (C) int _aApplyRcw1(scope const(char)[] aa, dg_t dg)
174 { int result;
176 debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
177 for (size_t i = aa.length; i != 0; )
178 { dchar d;
179 wchar w;
181 i--;
182 w = aa[i];
183 if (w & 0x80)
184 { char c = cast(char)w;
185 uint j;
186 uint m = 0x3F;
187 d = 0;
188 while ((c & 0xC0) != 0xC0)
189 { if (i == 0)
190 onUnicodeError("Invalid UTF-8 sequence", 0);
191 i--;
192 d |= (c & 0x3F) << j;
193 j += 6;
194 m >>= 1;
195 c = aa[i];
197 d |= (c & m) << j;
199 if (d <= 0xFFFF)
200 w = cast(wchar) d;
201 else
203 w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
204 result = dg(cast(void *)&w);
205 if (result)
206 break;
207 w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
210 result = dg(cast(void *)&w);
211 if (result)
212 break;
214 return result;
217 unittest
219 debug(apply) printf("_aApplyRcw1.unittest\n");
221 auto s = "hello"c[];
222 int i;
224 foreach_reverse (wchar d; s)
226 switch (i)
228 case 0: assert(d == 'o'); break;
229 case 1: assert(d == 'l'); break;
230 case 2: assert(d == 'l'); break;
231 case 3: assert(d == 'e'); break;
232 case 4: assert(d == 'h'); break;
233 default: assert(0);
235 i++;
237 assert(i == 5);
239 s = "a\u1234\U000A0456b";
240 i = 0;
241 foreach_reverse (wchar d; s)
243 //printf("i = %d, d = %x\n", i, d);
244 switch (i)
246 case 0: assert(d == 'b'); break;
247 case 1: assert(d == 0xDA41); break;
248 case 2: assert(d == 0xDC56); break;
249 case 3: assert(d == 0x1234); break;
250 case 4: assert(d == 'a'); break;
251 default: assert(0);
253 i++;
255 assert(i == 5);
258 /// ditto
259 extern (C) int _aApplyRwc1(scope const(wchar)[] aa, dg_t dg)
260 { int result;
262 debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
263 for (size_t i = aa.length; i != 0; )
264 { dchar d;
265 char c;
267 i--;
268 d = aa[i];
269 if (d >= 0xDC00 && d <= 0xDFFF)
270 { if (i == 0)
271 onUnicodeError("Invalid UTF-16 sequence", 0);
272 i--;
273 d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
276 if (d & ~0x7F)
278 char[4] buf = void;
280 auto b = toUTF8(buf, d);
281 foreach (char c2; b)
283 result = dg(cast(void *)&c2);
284 if (result)
285 return result;
287 continue;
289 c = cast(char)d;
290 result = dg(cast(void *)&c);
291 if (result)
292 break;
294 return result;
297 unittest
299 debug(apply) printf("_aApplyRwc1.unittest\n");
301 auto s = "hello"w[];
302 int i;
304 foreach_reverse (char d; s)
306 switch (i)
308 case 0: assert(d == 'o'); break;
309 case 1: assert(d == 'l'); break;
310 case 2: assert(d == 'l'); break;
311 case 3: assert(d == 'e'); break;
312 case 4: assert(d == 'h'); break;
313 default: assert(0);
315 i++;
317 assert(i == 5);
319 s = "a\u1234\U000A0456b";
320 i = 0;
321 foreach_reverse (char d; s)
323 //printf("i = %d, d = %x\n", i, d);
324 switch (i)
326 case 0: assert(d == 'b'); break;
327 case 1: assert(d == 0xF2); break;
328 case 2: assert(d == 0xA0); break;
329 case 3: assert(d == 0x91); break;
330 case 4: assert(d == 0x96); break;
331 case 5: assert(d == 0xE1); break;
332 case 6: assert(d == 0x88); break;
333 case 7: assert(d == 0xB4); break;
334 case 8: assert(d == 'a'); break;
335 default: assert(0);
337 i++;
339 assert(i == 9);
342 /// ditto
343 extern (C) int _aApplyRdc1(scope const(dchar)[] aa, dg_t dg)
344 { int result;
346 debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
347 for (size_t i = aa.length; i != 0;)
348 { dchar d = aa[--i];
349 char c;
351 if (d & ~0x7F)
353 char[4] buf = void;
355 auto b = toUTF8(buf, d);
356 foreach (char c2; b)
358 result = dg(cast(void *)&c2);
359 if (result)
360 return result;
362 continue;
364 else
366 c = cast(char)d;
368 result = dg(cast(void *)&c);
369 if (result)
370 break;
372 return result;
375 unittest
377 debug(apply) printf("_aApplyRdc1.unittest\n");
379 auto s = "hello"d[];
380 int i;
382 foreach_reverse (char d; s)
384 switch (i)
386 case 0: assert(d == 'o'); break;
387 case 1: assert(d == 'l'); break;
388 case 2: assert(d == 'l'); break;
389 case 3: assert(d == 'e'); break;
390 case 4: assert(d == 'h'); break;
391 default: assert(0);
393 i++;
395 assert(i == 5);
397 s = "a\u1234\U000A0456b";
398 i = 0;
399 foreach_reverse (char d; s)
401 //printf("i = %d, d = %x\n", i, d);
402 switch (i)
404 case 0: assert(d == 'b'); break;
405 case 1: assert(d == 0xF2); break;
406 case 2: assert(d == 0xA0); break;
407 case 3: assert(d == 0x91); break;
408 case 4: assert(d == 0x96); break;
409 case 5: assert(d == 0xE1); break;
410 case 6: assert(d == 0x88); break;
411 case 7: assert(d == 0xB4); break;
412 case 8: assert(d == 'a'); break;
413 default: assert(0);
415 i++;
417 assert(i == 9);
420 /// ditto
421 extern (C) int _aApplyRdw1(scope const(dchar)[] aa, dg_t dg)
422 { int result;
424 debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
425 for (size_t i = aa.length; i != 0; )
426 { dchar d = aa[--i];
427 wchar w;
429 if (d <= 0xFFFF)
430 w = cast(wchar) d;
431 else
433 w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
434 result = dg(cast(void *)&w);
435 if (result)
436 break;
437 w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
439 result = dg(cast(void *)&w);
440 if (result)
441 break;
443 return result;
446 unittest
448 debug(apply) printf("_aApplyRdw1.unittest\n");
450 auto s = "hello"d[];
451 int i;
453 foreach_reverse (wchar d; s)
455 switch (i)
457 case 0: assert(d == 'o'); break;
458 case 1: assert(d == 'l'); break;
459 case 2: assert(d == 'l'); break;
460 case 3: assert(d == 'e'); break;
461 case 4: assert(d == 'h'); break;
462 default: assert(0);
464 i++;
466 assert(i == 5);
468 s = "a\u1234\U000A0456b";
469 i = 0;
470 foreach_reverse (wchar d; s)
472 //printf("i = %d, d = %x\n", i, d);
473 switch (i)
475 case 0: assert(d == 'b'); break;
476 case 1: assert(d == 0xDA41); break;
477 case 2: assert(d == 0xDC56); break;
478 case 3: assert(d == 0x1234); break;
479 case 4: assert(d == 'a'); break;
480 default: assert(0);
482 i++;
484 assert(i == 5);
488 /****************************************************************************/
489 /* 2 argument versions */
492 Delegate type corresponding to transformed loop body
494 Parameters are pointers to a `size_t` loop index, and the current `char`, `wchar` or `dchar`.
496 Returns: non-zero when a `break` statement is hit
498 extern (D) alias dg2_t = int delegate(void* i, void* c);
500 // Note: dg is extern(D), but _aApplyRcd2() is extern(C)
503 Variants of _aApplyRXXX that include a loop index.
505 extern (C) int _aApplyRcd2(scope const(char)[] aa, dg2_t dg)
506 { int result;
507 size_t i;
508 size_t len = aa.length;
510 debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
511 for (i = len; i != 0; )
512 { dchar d;
514 i--;
515 d = aa[i];
516 if (d & 0x80)
517 { char c = cast(char)d;
518 uint j;
519 uint m = 0x3F;
520 d = 0;
521 while ((c & 0xC0) != 0xC0)
522 { if (i == 0)
523 onUnicodeError("Invalid UTF-8 sequence", 0);
524 i--;
525 d |= (c & 0x3F) << j;
526 j += 6;
527 m >>= 1;
528 c = aa[i];
530 d |= (c & m) << j;
532 result = dg(&i, cast(void *)&d);
533 if (result)
534 break;
536 return result;
539 unittest
541 debug(apply) printf("_aApplyRcd2.unittest\n");
543 auto s = "hello"c[];
544 int i;
546 foreach_reverse (k, dchar d; s)
548 assert(k == 4 - i);
549 switch (i)
551 case 0: assert(d == 'o'); break;
552 case 1: assert(d == 'l'); break;
553 case 2: assert(d == 'l'); break;
554 case 3: assert(d == 'e'); break;
555 case 4: assert(d == 'h'); break;
556 default: assert(0);
558 i++;
560 assert(i == 5);
562 s = "a\u1234\U000A0456b";
563 i = 0;
564 foreach_reverse (k, dchar d; s)
566 //printf("i = %d, k = %d, d = %x\n", i, k, d);
567 switch (i)
569 case 0: assert(d == 'b'); assert(k == 8); break;
570 case 1: assert(d == '\U000A0456'); assert(k == 4); break;
571 case 2: assert(d == '\u1234'); assert(k == 1); break;
572 case 3: assert(d == 'a'); assert(k == 0); break;
573 default: assert(0);
575 i++;
577 assert(i == 4);
580 /// ditto
581 extern (C) int _aApplyRwd2(scope const(wchar)[] aa, dg2_t dg)
582 { int result;
584 debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
585 for (size_t i = aa.length; i != 0; )
586 { dchar d;
588 i--;
589 d = aa[i];
590 if (d >= 0xDC00 && d <= 0xDFFF)
591 { if (i == 0)
592 onUnicodeError("Invalid UTF-16 sequence", 0);
593 i--;
594 d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
596 result = dg(&i, cast(void *)&d);
597 if (result)
598 break;
600 return result;
603 unittest
605 debug(apply) printf("_aApplyRwd2.unittest\n");
607 auto s = "hello"w[];
608 int i;
610 foreach_reverse (k, dchar d; s)
612 //printf("i = %d, k = %d, d = %x\n", i, k, d);
613 assert(k == 4 - i);
614 switch (i)
616 case 0: assert(d == 'o'); break;
617 case 1: assert(d == 'l'); break;
618 case 2: assert(d == 'l'); break;
619 case 3: assert(d == 'e'); break;
620 case 4: assert(d == 'h'); break;
621 default: assert(0);
623 i++;
625 assert(i == 5);
627 s = "a\u1234\U000A0456b";
628 i = 0;
629 foreach_reverse (k, dchar d; s)
631 //printf("i = %d, k = %d, d = %x\n", i, k, d);
632 switch (i)
634 case 0: assert(k == 4); assert(d == 'b'); break;
635 case 1: assert(k == 2); assert(d == '\U000A0456'); break;
636 case 2: assert(k == 1); assert(d == '\u1234'); break;
637 case 3: assert(k == 0); assert(d == 'a'); break;
638 default: assert(0);
640 i++;
642 assert(i == 4);
645 /// ditto
646 extern (C) int _aApplyRcw2(scope const(char)[] aa, dg2_t dg)
647 { int result;
649 debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
650 for (size_t i = aa.length; i != 0; )
651 { dchar d;
652 wchar w;
654 i--;
655 w = aa[i];
656 if (w & 0x80)
657 { char c = cast(char)w;
658 uint j;
659 uint m = 0x3F;
660 d = 0;
661 while ((c & 0xC0) != 0xC0)
662 { if (i == 0)
663 onUnicodeError("Invalid UTF-8 sequence", 0);
664 i--;
665 d |= (c & 0x3F) << j;
666 j += 6;
667 m >>= 1;
668 c = aa[i];
670 d |= (c & m) << j;
672 if (d <= 0xFFFF)
673 w = cast(wchar) d;
674 else
676 w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
677 result = dg(&i, cast(void *)&w);
678 if (result)
679 break;
680 w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
683 result = dg(&i, cast(void *)&w);
684 if (result)
685 break;
687 return result;
690 unittest
692 debug(apply) printf("_aApplyRcw2.unittest\n");
694 auto s = "hello"c[];
695 int i;
697 foreach_reverse (k, wchar d; s)
699 //printf("i = %d, k = %d, d = %x\n", i, k, d);
700 assert(k == 4 - i);
701 switch (i)
703 case 0: assert(d == 'o'); break;
704 case 1: assert(d == 'l'); break;
705 case 2: assert(d == 'l'); break;
706 case 3: assert(d == 'e'); break;
707 case 4: assert(d == 'h'); break;
708 default: assert(0);
710 i++;
712 assert(i == 5);
714 s = "a\u1234\U000A0456b";
715 i = 0;
716 foreach_reverse (k, wchar d; s)
718 //printf("i = %d, k = %d, d = %x\n", i, k, d);
719 switch (i)
721 case 0: assert(k == 8); assert(d == 'b'); break;
722 case 1: assert(k == 4); assert(d == 0xDA41); break;
723 case 2: assert(k == 4); assert(d == 0xDC56); break;
724 case 3: assert(k == 1); assert(d == 0x1234); break;
725 case 4: assert(k == 0); assert(d == 'a'); break;
726 default: assert(0);
728 i++;
730 assert(i == 5);
733 /// ditto
734 extern (C) int _aApplyRwc2(scope const(wchar)[] aa, dg2_t dg)
735 { int result;
737 debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
738 for (size_t i = aa.length; i != 0; )
739 { dchar d;
740 char c;
742 i--;
743 d = aa[i];
744 if (d >= 0xDC00 && d <= 0xDFFF)
745 { if (i == 0)
746 onUnicodeError("Invalid UTF-16 sequence", 0);
747 i--;
748 d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
751 if (d & ~0x7F)
753 char[4] buf = void;
755 auto b = toUTF8(buf, d);
756 foreach (char c2; b)
758 result = dg(&i, cast(void *)&c2);
759 if (result)
760 return result;
762 continue;
764 c = cast(char)d;
765 result = dg(&i, cast(void *)&c);
766 if (result)
767 break;
769 return result;
772 unittest
774 debug(apply) printf("_aApplyRwc2.unittest\n");
776 auto s = "hello"w[];
777 int i;
779 foreach_reverse (k, char d; s)
781 //printf("i = %d, k = %d, d = %x\n", i, k, d);
782 assert(k == 4 - i);
783 switch (i)
785 case 0: assert(d == 'o'); break;
786 case 1: assert(d == 'l'); break;
787 case 2: assert(d == 'l'); break;
788 case 3: assert(d == 'e'); break;
789 case 4: assert(d == 'h'); break;
790 default: assert(0);
792 i++;
794 assert(i == 5);
796 s = "a\u1234\U000A0456b";
797 i = 0;
798 foreach_reverse (k, char d; s)
800 //printf("i = %d, k = %d, d = %x\n", i, k, d);
801 switch (i)
803 case 0: assert(k == 4); assert(d == 'b'); break;
804 case 1: assert(k == 2); assert(d == 0xF2); break;
805 case 2: assert(k == 2); assert(d == 0xA0); break;
806 case 3: assert(k == 2); assert(d == 0x91); break;
807 case 4: assert(k == 2); assert(d == 0x96); break;
808 case 5: assert(k == 1); assert(d == 0xE1); break;
809 case 6: assert(k == 1); assert(d == 0x88); break;
810 case 7: assert(k == 1); assert(d == 0xB4); break;
811 case 8: assert(k == 0); assert(d == 'a'); break;
812 default: assert(0);
814 i++;
816 assert(i == 9);
819 /// ditto
820 extern (C) int _aApplyRdc2(scope const(dchar)[] aa, dg2_t dg)
821 { int result;
823 debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
824 for (size_t i = aa.length; i != 0; )
825 { dchar d = aa[--i];
826 char c;
828 if (d & ~0x7F)
830 char[4] buf = void;
832 auto b = toUTF8(buf, d);
833 foreach (char c2; b)
835 result = dg(&i, cast(void *)&c2);
836 if (result)
837 return result;
839 continue;
841 else
842 { c = cast(char)d;
844 result = dg(&i, cast(void *)&c);
845 if (result)
846 break;
848 return result;
851 unittest
853 debug(apply) printf("_aApplyRdc2.unittest\n");
855 auto s = "hello"d[];
856 int i;
858 foreach_reverse (k, char d; s)
860 //printf("i = %d, k = %d, d = %x\n", i, k, d);
861 assert(k == 4 - i);
862 switch (i)
864 case 0: assert(d == 'o'); break;
865 case 1: assert(d == 'l'); break;
866 case 2: assert(d == 'l'); break;
867 case 3: assert(d == 'e'); break;
868 case 4: assert(d == 'h'); break;
869 default: assert(0);
871 i++;
873 assert(i == 5);
875 s = "a\u1234\U000A0456b";
876 i = 0;
877 foreach_reverse (k, char d; s)
879 //printf("i = %d, k = %d, d = %x\n", i, k, d);
880 switch (i)
882 case 0: assert(k == 3); assert(d == 'b'); break;
883 case 1: assert(k == 2); assert(d == 0xF2); break;
884 case 2: assert(k == 2); assert(d == 0xA0); break;
885 case 3: assert(k == 2); assert(d == 0x91); break;
886 case 4: assert(k == 2); assert(d == 0x96); break;
887 case 5: assert(k == 1); assert(d == 0xE1); break;
888 case 6: assert(k == 1); assert(d == 0x88); break;
889 case 7: assert(k == 1); assert(d == 0xB4); break;
890 case 8: assert(k == 0); assert(d == 'a'); break;
891 default: assert(0);
893 i++;
895 assert(i == 9);
898 /// ditto
899 extern (C) int _aApplyRdw2(scope const(dchar)[] aa, dg2_t dg)
900 { int result;
902 debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
903 for (size_t i = aa.length; i != 0; )
904 { dchar d = aa[--i];
905 wchar w;
907 if (d <= 0xFFFF)
908 w = cast(wchar) d;
909 else
911 w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
912 result = dg(&i, cast(void *)&w);
913 if (result)
914 break;
915 w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
917 result = dg(&i, cast(void *)&w);
918 if (result)
919 break;
921 return result;
924 unittest
926 debug(apply) printf("_aApplyRdw2.unittest\n");
928 auto s = "hello"d[];
929 int i;
931 foreach_reverse (k, wchar d; s)
933 //printf("i = %d, k = %d, d = %x\n", i, k, d);
934 assert(k == 4 - i);
935 switch (i)
937 case 0: assert(d == 'o'); break;
938 case 1: assert(d == 'l'); break;
939 case 2: assert(d == 'l'); break;
940 case 3: assert(d == 'e'); break;
941 case 4: assert(d == 'h'); break;
942 default: assert(0);
944 i++;
946 assert(i == 5);
948 s = "a\u1234\U000A0456b";
949 i = 0;
950 foreach_reverse (k, wchar d; s)
952 //printf("i = %d, k = %d, d = %x\n", i, k, d);
953 switch (i)
955 case 0: assert(k == 3); assert(d == 'b'); break;
956 case 1: assert(k == 2); assert(d == 0xDA41); break;
957 case 2: assert(k == 2); assert(d == 0xDC56); break;
958 case 3: assert(k == 1); assert(d == 0x1234); break;
959 case 4: assert(k == 0); assert(d == 'a'); break;
960 default: assert(0);
962 i++;
964 assert(i == 5);