PageRenderTime 28ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 1ms

/runtime/internal/aApplyR.d

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