PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/unported/tango/core/rt/compiler/gdc/rt/aApplyR.d

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