comparison druntime/src/compiler/dmd/aApplyR.d @ 759:d3eb054172f9

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