1 /**
2  * This code handles decoding UTF strings for foreach loops.  There are 6
3  * combinations of conversions between char, wchar, and dchar, and 2 of each
4  * of those.
5  *
6  * Copyright: Copyright Digital Mars 2004 - 2010.
7  * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
8  * Authors:   Walter Bright
9  * Source: $(DRUNTIMESRC src/rt/_aApply.d)
10  */
11 module rt.aApply;
12 
13 private import rt.util.utf : decode, toUTF8;
14 
15 /**********************************************/
16 /* 1 argument versions */
17 
18 // dg is D, but _aApplycd() is C
19 extern (D) alias int delegate(void *) dg_t;
20 
_aApplycd1(in char[]aa,dg_t dg)21 extern (C) int _aApplycd1(in char[] aa, dg_t dg)
22 {
23     int result;
24     size_t len = aa.length;
25 
26     debug(apply) printf("_aApplycd1(), len = %d\n", len);
27     for (size_t i = 0; i < len; )
28     {
29         dchar d = aa[i];
30         if (d & 0x80)
31             d = decode(aa, i);
32         else
33             ++i;
34         result = dg(cast(void *)&d);
35         if (result)
36             break;
37     }
38     return result;
39 }
40 
41 unittest
42 {
43     debug(apply) printf("_aApplycd1.unittest\n");
44 
45     auto s = "hello"c[];
46     int i;
47 
foreach(dchar d;s)48     foreach (dchar d; s)
49     {
50         switch (i)
51         {
52             case 0:     assert(d == 'h'); break;
53             case 1:     assert(d == 'e'); break;
54             case 2:     assert(d == 'l'); break;
55             case 3:     assert(d == 'l'); break;
56             case 4:     assert(d == 'o'); break;
57             default:    assert(0);
58         }
59         i++;
60     }
61     assert(i == 5);
62 
63     s = "a\u1234\U000A0456b";
64     i = 0;
foreach(dchar d;s)65     foreach (dchar d; s)
66     {
67         //printf("i = %d, d = %x\n", i, d);
68         switch (i)
69         {
70             case 0:     assert(d == 'a'); break;
71             case 1:     assert(d == '\u1234'); break;
72             case 2:     assert(d == '\U000A0456'); break;
73             case 3:     assert(d == 'b'); break;
74             default:    assert(0);
75         }
76         i++;
77     }
78     assert(i == 4);
79 }
80 
81 /*****************************/
82 
_aApplywd1(in wchar[]aa,dg_t dg)83 extern (C) int _aApplywd1(in wchar[] aa, dg_t dg)
84 {
85     int result;
86     size_t len = aa.length;
87 
88     debug(apply) printf("_aApplywd1(), len = %d\n", len);
89     for (size_t i = 0; i < len; )
90     {
91         dchar d = aa[i];
92         if (d >= 0xD800)
93             d = decode(aa, i);
94         else
95             ++i;
96         result = dg(cast(void *)&d);
97         if (result)
98             break;
99     }
100     return result;
101 }
102 
103 unittest
104 {
105     debug(apply) printf("_aApplywd1.unittest\n");
106 
107     auto s = "hello"w[];
108     int i;
109 
foreach(dchar d;s)110     foreach (dchar d; s)
111     {
112         switch (i)
113         {
114             case 0:     assert(d == 'h'); break;
115             case 1:     assert(d == 'e'); break;
116             case 2:     assert(d == 'l'); break;
117             case 3:     assert(d == 'l'); break;
118             case 4:     assert(d == 'o'); break;
119             default:    assert(0);
120         }
121         i++;
122     }
123     assert(i == 5);
124 
125     s = "a\u1234\U000A0456b";
126     i = 0;
foreach(dchar d;s)127     foreach (dchar d; s)
128     {
129         //printf("i = %d, d = %x\n", i, d);
130         switch (i)
131         {
132             case 0:     assert(d == 'a'); break;
133             case 1:     assert(d == '\u1234'); break;
134             case 2:     assert(d == '\U000A0456'); break;
135             case 3:     assert(d == 'b'); break;
136             default:    assert(0);
137         }
138         i++;
139     }
140     assert(i == 4);
141 }
142 
143 /*****************************/
144 
_aApplycw1(in char[]aa,dg_t dg)145 extern (C) int _aApplycw1(in char[] aa, dg_t dg)
146 {
147     int result;
148     size_t len = aa.length;
149 
150     debug(apply) printf("_aApplycw1(), len = %d\n", len);
151     for (size_t i = 0; i < len; )
152     {
153         wchar w = aa[i];
154         if (w & 0x80)
155         {
156             dchar d = decode(aa, i);
157             if (d <= 0xFFFF)
158                 w = cast(wchar) d;
159             else
160             {
161                 w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
162                 result = dg(cast(void *)&w);
163                 if (result)
164                     break;
165                 w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
166             }
167         }
168         else
169             ++i;
170         result = dg(cast(void *)&w);
171         if (result)
172             break;
173     }
174     return result;
175 }
176 
177 unittest
178 {
179     debug(apply) printf("_aApplycw1.unittest\n");
180 
181     auto s = "hello"c[];
182     int i;
183 
foreach(wchar d;s)184     foreach (wchar d; s)
185     {
186         switch (i)
187         {
188             case 0:     assert(d == 'h'); break;
189             case 1:     assert(d == 'e'); break;
190             case 2:     assert(d == 'l'); break;
191             case 3:     assert(d == 'l'); break;
192             case 4:     assert(d == 'o'); break;
193             default:    assert(0);
194         }
195         i++;
196     }
197     assert(i == 5);
198 
199     s = "a\u1234\U000A0456b";
200     i = 0;
foreach(wchar d;s)201     foreach (wchar d; s)
202     {
203         //printf("i = %d, d = %x\n", i, d);
204         switch (i)
205         {
206             case 0:     assert(d == 'a'); break;
207             case 1:     assert(d == 0x1234); break;
208             case 2:     assert(d == 0xDA41); break;
209             case 3:     assert(d == 0xDC56); break;
210             case 4:     assert(d == 'b'); break;
211             default:    assert(0);
212         }
213         i++;
214     }
215     assert(i == 5);
216 }
217 
218 /*****************************/
219 
_aApplywc1(in wchar[]aa,dg_t dg)220 extern (C) int _aApplywc1(in wchar[] aa, dg_t dg)
221 {
222     int result;
223     size_t len = aa.length;
224 
225     debug(apply) printf("_aApplywc1(), len = %d\n", len);
226     for (size_t i = 0; i < len; )
227     {
228         wchar w = aa[i];
229         if (w & ~0x7F)
230         {
231             char[4] buf = void;
232 
233             dchar d = decode(aa, i);
234             auto b = toUTF8(buf, d);
235             foreach (char c2; b)
236             {
237                 result = dg(cast(void *)&c2);
238                 if (result)
239                     return result;
240             }
241         }
242         else
243         {
244             char c = cast(char)w;
245             ++i;
246             result = dg(cast(void *)&c);
247             if (result)
248                 break;
249         }
250     }
251     return result;
252 }
253 
254 unittest
255 {
256     debug(apply) printf("_aApplywc1.unittest\n");
257 
258     auto s = "hello"w[];
259     int i;
260 
foreach(char d;s)261     foreach (char d; s)
262     {
263         switch (i)
264         {
265             case 0:     assert(d == 'h'); break;
266             case 1:     assert(d == 'e'); break;
267             case 2:     assert(d == 'l'); break;
268             case 3:     assert(d == 'l'); break;
269             case 4:     assert(d == 'o'); break;
270             default:    assert(0);
271         }
272         i++;
273     }
274     assert(i == 5);
275 
276     s = "a\u1234\U000A0456b";
277     i = 0;
foreach(char d;s)278     foreach (char d; s)
279     {
280         //printf("i = %d, d = %x\n", i, d);
281         switch (i)
282         {
283             case 0:     assert(d == 'a'); break;
284             case 1:     assert(d == 0xE1); break;
285             case 2:     assert(d == 0x88); break;
286             case 3:     assert(d == 0xB4); break;
287             case 4:     assert(d == 0xF2); break;
288             case 5:     assert(d == 0xA0); break;
289             case 6:     assert(d == 0x91); break;
290             case 7:     assert(d == 0x96); break;
291             case 8:     assert(d == 'b'); break;
292             default:    assert(0);
293         }
294         i++;
295     }
296     assert(i == 9);
297 }
298 
299 /*****************************/
300 
_aApplydc1(in dchar[]aa,dg_t dg)301 extern (C) int _aApplydc1(in dchar[] aa, dg_t dg)
302 {
303     int result;
304 
305     debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
306     foreach (dchar d; aa)
307     {
308         if (d & ~0x7F)
309         {
310             char[4] buf = void;
311 
312             auto b = toUTF8(buf, d);
313             foreach (char c2; b)
314             {
315                 result = dg(cast(void *)&c2);
316                 if (result)
317                     return result;
318             }
319         }
320         else
321         {
322             char c = cast(char)d;
323             result = dg(cast(void *)&c);
324             if (result)
325                 break;
326         }
327     }
328     return result;
329 }
330 
331 unittest
332 {
333     debug(apply) printf("_aApplyRdc1.unittest\n");
334 
335     auto s = "hello"d[];
336     int i;
337 
foreach(char d;s)338     foreach (char d; s)
339     {
340         switch (i)
341         {
342             case 0:     assert(d == 'h'); break;
343             case 1:     assert(d == 'e'); break;
344             case 2:     assert(d == 'l'); break;
345             case 3:     assert(d == 'l'); break;
346             case 4:     assert(d == 'o'); break;
347             default:    assert(0);
348         }
349         i++;
350     }
351     assert(i == 5);
352 
353     s = "a\u1234\U000A0456b";
354     i = 0;
foreach(char d;s)355     foreach (char d; s)
356     {
357         //printf("i = %d, d = %x\n", i, d);
358         switch (i)
359         {
360             case 0:     assert(d == 'a'); break;
361             case 1:     assert(d == 0xE1); break;
362             case 2:     assert(d == 0x88); break;
363             case 3:     assert(d == 0xB4); break;
364             case 4:     assert(d == 0xF2); break;
365             case 5:     assert(d == 0xA0); break;
366             case 6:     assert(d == 0x91); break;
367             case 7:     assert(d == 0x96); break;
368             case 8:     assert(d == 'b'); break;
369             default:    assert(0);
370         }
371         i++;
372     }
373     assert(i == 9);
374 }
375 
376 /*****************************/
377 
_aApplydw1(in dchar[]aa,dg_t dg)378 extern (C) int _aApplydw1(in dchar[] aa, dg_t dg)
379 {
380     int result;
381 
382     debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
383     foreach (dchar d; aa)
384     {
385         wchar w;
386 
387         if (d <= 0xFFFF)
388             w = cast(wchar) d;
389         else
390         {
391             w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
392             result = dg(cast(void *)&w);
393             if (result)
394                 break;
395             w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
396         }
397         result = dg(cast(void *)&w);
398         if (result)
399             break;
400     }
401     return result;
402 }
403 
404 unittest
405 {
406     debug(apply) printf("_aApplydw1.unittest\n");
407 
408     auto s = "hello"d[];
409     int i;
410 
foreach(wchar d;s)411     foreach (wchar d; s)
412     {
413         switch (i)
414         {
415             case 0:     assert(d == 'h'); break;
416             case 1:     assert(d == 'e'); break;
417             case 2:     assert(d == 'l'); break;
418             case 3:     assert(d == 'l'); break;
419             case 4:     assert(d == 'o'); break;
420             default:    assert(0);
421         }
422         i++;
423     }
424     assert(i == 5);
425 
426     s = "a\u1234\U000A0456b";
427     i = 0;
foreach(wchar d;s)428     foreach (wchar d; s)
429     {
430         //printf("i = %d, d = %x\n", i, d);
431         switch (i)
432         {
433             case 0:     assert(d == 'a'); break;
434             case 1:     assert(d == 0x1234); break;
435             case 2:     assert(d == 0xDA41); break;
436             case 3:     assert(d == 0xDC56); break;
437             case 4:     assert(d == 'b'); break;
438             default:    assert(0);
439         }
440         i++;
441     }
442     assert(i == 5);
443 }
444 
445 
446 /****************************************************************************/
447 /* 2 argument versions */
448 
449 // dg is D, but _aApplycd2() is C
450 extern (D) alias int delegate(void *, void *) dg2_t;
451 
_aApplycd2(in char[]aa,dg2_t dg)452 extern (C) int _aApplycd2(in char[] aa, dg2_t dg)
453 {
454     int result;
455     size_t len = aa.length;
456 
457     debug(apply) printf("_aApplycd2(), len = %d\n", len);
458     size_t n;
459     for (size_t i = 0; i < len; i += n)
460     {
461         dchar d = aa[i];
462         if (d & 0x80)
463         {
464             n = i;
465             d = decode(aa, n);
466             n -= i;
467         }
468         else
469             n = 1;
470         result = dg(&i, cast(void *)&d);
471         if (result)
472             break;
473     }
474     return result;
475 }
476 
477 unittest
478 {
479     debug(apply) printf("_aApplycd2.unittest\n");
480 
481     auto s = "hello"c[];
482     int i;
483 
foreach(k,dchar d;s)484     foreach (k, dchar d; s)
485     {
486         //printf("i = %d, k = %d, d = %x\n", i, k, d);
487         assert(k == i);
488         switch (i)
489         {
490             case 0:     assert(d == 'h'); break;
491             case 1:     assert(d == 'e'); break;
492             case 2:     assert(d == 'l'); break;
493             case 3:     assert(d == 'l'); break;
494             case 4:     assert(d == 'o'); break;
495             default:    assert(0);
496         }
497         i++;
498     }
499     assert(i == 5);
500 
501     s = "a\u1234\U000A0456b";
502     i = 0;
foreach(k,dchar d;s)503     foreach (k, dchar d; s)
504     {
505         //printf("i = %d, k = %d, d = %x\n", i, k, d);
506         switch (i)
507         {
508             case 0:     assert(d == 'a'); assert(k == 0); break;
509             case 1:     assert(d == '\u1234'); assert(k == 1); break;
510             case 2:     assert(d == '\U000A0456'); assert(k == 4); break;
511             case 3:     assert(d == 'b'); assert(k == 8); break;
512             default:    assert(0);
513         }
514         i++;
515     }
516     assert(i == 4);
517 }
518 
519 /*****************************/
520 
_aApplywd2(in wchar[]aa,dg2_t dg)521 extern (C) int _aApplywd2(in wchar[] aa, dg2_t dg)
522 {
523     int result;
524     size_t len = aa.length;
525 
526     debug(apply) printf("_aApplywd2(), len = %d\n", len);
527     size_t n;
528     for (size_t i = 0; i < len; i += n)
529     {
530         dchar d = aa[i];
531         if (d & ~0x7F)
532         {
533             n = i;
534             d = decode(aa, n);
535             n -= i;
536         }
537         else
538             n = 1;
539         result = dg(&i, cast(void *)&d);
540         if (result)
541             break;
542     }
543     return result;
544 }
545 
546 unittest
547 {
548     debug(apply) printf("_aApplywd2.unittest\n");
549 
550     auto s = "hello"w[];
551     int i;
552 
foreach(k,dchar d;s)553     foreach (k, dchar d; s)
554     {
555         //printf("i = %d, k = %d, d = %x\n", i, k, d);
556         assert(k == i);
557         switch (i)
558         {
559             case 0:     assert(d == 'h'); break;
560             case 1:     assert(d == 'e'); break;
561             case 2:     assert(d == 'l'); break;
562             case 3:     assert(d == 'l'); break;
563             case 4:     assert(d == 'o'); break;
564             default:    assert(0);
565         }
566         i++;
567     }
568     assert(i == 5);
569 
570     s = "a\u1234\U000A0456b";
571     i = 0;
foreach(k,dchar d;s)572     foreach (k, dchar d; s)
573     {
574         //printf("i = %d, k = %d, d = %x\n", i, k, d);
575         switch (i)
576         {
577             case 0:     assert(k == 0); assert(d == 'a'); break;
578             case 1:     assert(k == 1); assert(d == '\u1234'); break;
579             case 2:     assert(k == 2); assert(d == '\U000A0456'); break;
580             case 3:     assert(k == 4); assert(d == 'b'); break;
581             default:    assert(0);
582         }
583         i++;
584     }
585     assert(i == 4);
586 }
587 
588 /*****************************/
589 
_aApplycw2(in char[]aa,dg2_t dg)590 extern (C) int _aApplycw2(in char[] aa, dg2_t dg)
591 {
592     int result;
593     size_t len = aa.length;
594 
595     debug(apply) printf("_aApplycw2(), len = %d\n", len);
596     size_t n;
597     for (size_t i = 0; i < len; i += n)
598     {
599         wchar w = aa[i];
600         if (w & 0x80)
601         {
602             n = i;
603             dchar d = decode(aa, n);
604             n -= i;
605             if (d <= 0xFFFF)
606                 w = cast(wchar) d;
607             else
608             {
609                 w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
610                 result = dg(&i, cast(void *)&w);
611                 if (result)
612                     break;
613                 w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
614             }
615         }
616         else
617             n = 1;
618         result = dg(&i, cast(void *)&w);
619         if (result)
620             break;
621     }
622     return result;
623 }
624 
625 unittest
626 {
627     debug(apply) printf("_aApplycw2.unittest\n");
628 
629     auto s = "hello"c[];
630     int i;
631 
foreach(k,wchar d;s)632     foreach (k, wchar d; s)
633     {
634         //printf("i = %d, k = %d, d = %x\n", i, k, d);
635         assert(k == i);
636         switch (i)
637         {
638             case 0:     assert(d == 'h'); break;
639             case 1:     assert(d == 'e'); break;
640             case 2:     assert(d == 'l'); break;
641             case 3:     assert(d == 'l'); break;
642             case 4:     assert(d == 'o'); break;
643             default:    assert(0);
644         }
645         i++;
646     }
647     assert(i == 5);
648 
649     s = "a\u1234\U000A0456b";
650     i = 0;
foreach(k,wchar d;s)651     foreach (k, wchar d; s)
652     {
653         //printf("i = %d, k = %d, d = %x\n", i, k, d);
654         switch (i)
655         {
656             case 0:     assert(k == 0); assert(d == 'a'); break;
657             case 1:     assert(k == 1); assert(d == 0x1234); break;
658             case 2:     assert(k == 4); assert(d == 0xDA41); break;
659             case 3:     assert(k == 4); assert(d == 0xDC56); break;
660             case 4:     assert(k == 8); assert(d == 'b'); break;
661             default:    assert(0);
662         }
663         i++;
664     }
665     assert(i == 5);
666 }
667 
668 /*****************************/
669 
_aApplywc2(in wchar[]aa,dg2_t dg)670 extern (C) int _aApplywc2(in wchar[] aa, dg2_t dg)
671 {
672     int result;
673     size_t len = aa.length;
674 
675     debug(apply) printf("_aApplywc2(), len = %d\n", len);
676     size_t n;
677     for (size_t i = 0; i < len; i += n)
678     {
679         wchar w = aa[i];
680         if (w & ~0x7F)
681         {
682             char[4] buf = void;
683 
684             n = i;
685             dchar d = decode(aa, n);
686             n -= i;
687             auto b = toUTF8(buf, d);
688             foreach (char c2; b)
689             {
690                 result = dg(&i, cast(void *)&c2);
691                 if (result)
692                     return result;
693             }
694         }
695         else
696         {
697             char c = cast(char)w;
698             n = 1;
699             result = dg(&i, cast(void *)&c);
700             if (result)
701                 break;
702         }
703     }
704     return result;
705 }
706 
707 unittest
708 {
709     debug(apply) printf("_aApplywc2.unittest\n");
710 
711     auto s = "hello"w[];
712     int i;
713 
foreach(k,char d;s)714     foreach (k, char d; s)
715     {
716         //printf("i = %d, k = %d, d = %x\n", i, k, d);
717         assert(k == i);
718         switch (i)
719         {
720             case 0:     assert(d == 'h'); break;
721             case 1:     assert(d == 'e'); break;
722             case 2:     assert(d == 'l'); break;
723             case 3:     assert(d == 'l'); break;
724             case 4:     assert(d == 'o'); break;
725             default:    assert(0);
726         }
727         i++;
728     }
729     assert(i == 5);
730 
731     s = "a\u1234\U000A0456b";
732     i = 0;
foreach(k,char d;s)733     foreach (k, char d; s)
734     {
735         //printf("i = %d, k = %d, d = %x\n", i, k, d);
736         switch (i)
737         {
738             case 0:     assert(k == 0); assert(d == 'a'); break;
739             case 1:     assert(k == 1); assert(d == 0xE1); break;
740             case 2:     assert(k == 1); assert(d == 0x88); break;
741             case 3:     assert(k == 1); assert(d == 0xB4); break;
742             case 4:     assert(k == 2); assert(d == 0xF2); break;
743             case 5:     assert(k == 2); assert(d == 0xA0); break;
744             case 6:     assert(k == 2); assert(d == 0x91); break;
745             case 7:     assert(k == 2); assert(d == 0x96); break;
746             case 8:     assert(k == 4); assert(d == 'b'); break;
747             default:    assert(0);
748         }
749         i++;
750     }
751     assert(i == 9);
752 }
753 
754 /*****************************/
755 
_aApplydc2(in dchar[]aa,dg2_t dg)756 extern (C) int _aApplydc2(in dchar[] aa, dg2_t dg)
757 {
758     int result;
759     size_t len = aa.length;
760 
761     debug(apply) printf("_aApplydc2(), len = %d\n", len);
762     for (size_t i = 0; i < len; i++)
763     {
764         dchar d = aa[i];
765         if (d & ~0x7F)
766         {
767             char[4] buf = void;
768 
769             auto b = toUTF8(buf, d);
770             foreach (char c2; b)
771             {
772                 result = dg(&i, cast(void *)&c2);
773                 if (result)
774                     return result;
775             }
776         }
777         else
778         {
779             char c = cast(char)d;
780             result = dg(&i, cast(void *)&c);
781             if (result)
782                 break;
783         }
784     }
785     return result;
786 }
787 
788 unittest
789 {
790     debug(apply) printf("_aApplydc2.unittest\n");
791 
792     auto s = "hello"d[];
793     int i;
794 
foreach(k,char d;s)795     foreach (k, char d; s)
796     {
797         //printf("i = %d, k = %d, d = %x\n", i, k, d);
798         assert(k == i);
799         switch (i)
800         {
801             case 0:     assert(d == 'h'); break;
802             case 1:     assert(d == 'e'); break;
803             case 2:     assert(d == 'l'); break;
804             case 3:     assert(d == 'l'); break;
805             case 4:     assert(d == 'o'); break;
806             default:    assert(0);
807         }
808         i++;
809     }
810     assert(i == 5);
811 
812     s = "a\u1234\U000A0456b";
813     i = 0;
foreach(k,char d;s)814     foreach (k, char d; s)
815     {
816         //printf("i = %d, k = %d, d = %x\n", i, k, d);
817         switch (i)
818         {
819             case 0:     assert(k == 0); assert(d == 'a'); break;
820             case 1:     assert(k == 1); assert(d == 0xE1); break;
821             case 2:     assert(k == 1); assert(d == 0x88); break;
822             case 3:     assert(k == 1); assert(d == 0xB4); break;
823             case 4:     assert(k == 2); assert(d == 0xF2); break;
824             case 5:     assert(k == 2); assert(d == 0xA0); break;
825             case 6:     assert(k == 2); assert(d == 0x91); break;
826             case 7:     assert(k == 2); assert(d == 0x96); break;
827             case 8:     assert(k == 3); assert(d == 'b'); break;
828             default:    assert(0);
829         }
830         i++;
831     }
832     assert(i == 9);
833 }
834 
835 /*****************************/
836 
_aApplydw2(in dchar[]aa,dg2_t dg)837 extern (C) int _aApplydw2(in dchar[] aa, dg2_t dg)
838 {   int result;
839 
840     debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
841     foreach (size_t i, dchar d; aa)
842     {
843         wchar w;
844         auto j = i;
845 
846         if (d <= 0xFFFF)
847             w = cast(wchar) d;
848         else
849         {
850             w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
851             result = dg(&j, cast(void *)&w);
852             if (result)
853                 break;
854             w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
855         }
856         result = dg(&j, cast(void *)&w);
857         if (result)
858             break;
859     }
860     return result;
861 }
862 
863 unittest
864 {
865     debug(apply) printf("_aApplydw2.unittest\n");
866 
867     auto s = "hello"d[];
868     int i;
869 
foreach(k,wchar d;s)870     foreach (k, wchar d; s)
871     {
872         //printf("i = %d, k = %d, d = %x\n", i, k, d);
873         assert(k == i);
874         switch (i)
875         {
876             case 0:     assert(d == 'h'); break;
877             case 1:     assert(d == 'e'); break;
878             case 2:     assert(d == 'l'); break;
879             case 3:     assert(d == 'l'); break;
880             case 4:     assert(d == 'o'); break;
881             default:    assert(0);
882         }
883         i++;
884     }
885     assert(i == 5);
886 
887     s = "a\u1234\U000A0456b";
888     i = 0;
foreach(k,wchar d;s)889     foreach (k, wchar d; s)
890     {
891         //printf("i = %d, k = %d, d = %x\n", i, k, d);
892         switch (i)
893         {
894             case 0:     assert(k == 0); assert(d == 'a'); break;
895             case 1:     assert(k == 1); assert(d == 0x1234); break;
896             case 2:     assert(k == 2); assert(d == 0xDA41); break;
897             case 3:     assert(k == 2); assert(d == 0xDC56); break;
898             case 4:     assert(k == 3); assert(d == 'b'); break;
899             default:    assert(0);
900         }
901         i++;
902     }
903     assert(i == 5);
904 }
905