PageRenderTime 61ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/d/phobos/internal/aApplyR.d

https://bitbucket.org/fearog/gdc-nacl
D | 977 lines | 800 code | 114 blank | 63 comment | 310 complexity | 08764be28f693f6f3c19992a519d388c MD5 | raw file
Possible License(s): GPL-2.0, 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. /* This code handles decoding UTF strings for foreach_reverse loops.
  27. * There are 6 combinations of conversions between char, wchar,
  28. * and dchar, and 2 of each of those.
  29. */
  30. import std.utf;
  31. //debug=apply;
  32. /**********************************************/
  33. /* 1 argument versions */
  34. // dg is D, but _aApplyRcd() is C
  35. extern (D) typedef int delegate(void *) dg_t;
  36. extern (C) int _aApplyRcd1(char[] aa, dg_t dg)
  37. { int result;
  38. debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
  39. for (size_t i = aa.length; i != 0; )
  40. { dchar d;
  41. i--;
  42. d = aa[i];
  43. if (d & 0x80)
  44. { char c = cast(char)d;
  45. uint j;
  46. uint m = 0x3F;
  47. d = 0;
  48. while ((c & 0xC0) != 0xC0)
  49. { if (i == 0)
  50. throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
  51. i--;
  52. d |= (c & 0x3F) << j;
  53. j += 6;
  54. m >>= 1;
  55. c = aa[i];
  56. }
  57. d |= (c & m) << j;
  58. }
  59. result = dg(cast(void *)&d);
  60. if (result)
  61. break;
  62. }
  63. return result;
  64. }
  65. unittest
  66. {
  67. debug(apply) printf("_aApplyRcd1.unittest\n");
  68. char[] s = "hello";
  69. int i;
  70. foreach_reverse(dchar d; s)
  71. {
  72. switch (i)
  73. {
  74. case 0: assert(d == 'o'); break;
  75. case 1: assert(d == 'l'); break;
  76. case 2: assert(d == 'l'); break;
  77. case 3: assert(d == 'e'); break;
  78. case 4: assert(d == 'h'); break;
  79. default: assert(0);
  80. }
  81. i++;
  82. }
  83. assert(i == 5);
  84. s = "a\u1234\U00100456b";
  85. i = 0;
  86. foreach_reverse(dchar d; s)
  87. {
  88. //printf("i = %d, d = %x\n", i, d);
  89. switch (i)
  90. {
  91. case 0: assert(d == 'b'); break;
  92. case 1: assert(d == '\U00100456'); break;
  93. case 2: assert(d == '\u1234'); break;
  94. case 3: assert(d == 'a'); break;
  95. default: assert(0);
  96. }
  97. i++;
  98. }
  99. assert(i == 4);
  100. }
  101. /*****************************/
  102. extern (C) int _aApplyRwd1(wchar[] aa, dg_t dg)
  103. { int result;
  104. debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
  105. for (size_t i = aa.length; i != 0; )
  106. { dchar d;
  107. i--;
  108. d = aa[i];
  109. if (d >= 0xDC00 && d <= 0xDFFF)
  110. { if (i == 0)
  111. throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
  112. i--;
  113. d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
  114. }
  115. result = dg(cast(void *)&d);
  116. if (result)
  117. break;
  118. }
  119. return result;
  120. }
  121. unittest
  122. {
  123. debug(apply) printf("_aApplyRwd1.unittest\n");
  124. wchar[] s = "hello";
  125. int i;
  126. foreach_reverse(dchar d; s)
  127. {
  128. switch (i)
  129. {
  130. case 0: assert(d == 'o'); break;
  131. case 1: assert(d == 'l'); break;
  132. case 2: assert(d == 'l'); break;
  133. case 3: assert(d == 'e'); break;
  134. case 4: assert(d == 'h'); break;
  135. default: assert(0);
  136. }
  137. i++;
  138. }
  139. assert(i == 5);
  140. s = "a\u1234\U00100456b";
  141. i = 0;
  142. foreach_reverse(dchar d; s)
  143. {
  144. //printf("i = %d, d = %x\n", i, d);
  145. switch (i)
  146. {
  147. case 0: assert(d == 'b'); break;
  148. case 1: assert(d == '\U00100456'); break;
  149. case 2: assert(d == '\u1234'); break;
  150. case 3: assert(d == 'a'); break;
  151. default: assert(0);
  152. }
  153. i++;
  154. }
  155. assert(i == 4);
  156. }
  157. /*****************************/
  158. extern (C) int _aApplyRcw1(char[] aa, dg_t dg)
  159. { int result;
  160. debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
  161. for (size_t i = aa.length; i != 0; )
  162. { dchar d;
  163. wchar w;
  164. i--;
  165. w = aa[i];
  166. if (w & 0x80)
  167. { char c = cast(char)w;
  168. uint j;
  169. uint m = 0x3F;
  170. d = 0;
  171. while ((c & 0xC0) != 0xC0)
  172. { if (i == 0)
  173. throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
  174. i--;
  175. d |= (c & 0x3F) << j;
  176. j += 6;
  177. m >>= 1;
  178. c = aa[i];
  179. }
  180. d |= (c & m) << j;
  181. if (d <= 0xFFFF)
  182. w = cast(wchar) d;
  183. else
  184. {
  185. w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
  186. result = dg(cast(void *)&w);
  187. if (result)
  188. break;
  189. w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
  190. }
  191. }
  192. result = dg(cast(void *)&w);
  193. if (result)
  194. break;
  195. }
  196. return result;
  197. }
  198. unittest
  199. {
  200. debug(apply) printf("_aApplyRcw1.unittest\n");
  201. char[] s = "hello";
  202. int i;
  203. foreach_reverse(wchar d; s)
  204. {
  205. switch (i)
  206. {
  207. case 0: assert(d == 'o'); break;
  208. case 1: assert(d == 'l'); break;
  209. case 2: assert(d == 'l'); break;
  210. case 3: assert(d == 'e'); break;
  211. case 4: assert(d == 'h'); break;
  212. default: assert(0);
  213. }
  214. i++;
  215. }
  216. assert(i == 5);
  217. s = "a\u1234\U00100456b";
  218. i = 0;
  219. foreach_reverse(wchar d; s)
  220. {
  221. //printf("i = %d, d = %x\n", i, d);
  222. switch (i)
  223. {
  224. case 0: assert(d == 'b'); break;
  225. case 1: assert(d == 0xDBC1); break;
  226. case 2: assert(d == 0xDC56); break;
  227. case 3: assert(d == 0x1234); break;
  228. case 4: assert(d == 'a'); break;
  229. default: assert(0);
  230. }
  231. i++;
  232. }
  233. assert(i == 5);
  234. }
  235. /*****************************/
  236. extern (C) int _aApplyRwc1(wchar[] aa, dg_t dg)
  237. { int result;
  238. debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
  239. for (size_t i = aa.length; i != 0; )
  240. { dchar d;
  241. char c;
  242. i--;
  243. d = aa[i];
  244. if (d >= 0xDC00 && d <= 0xDFFF)
  245. { if (i == 0)
  246. throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
  247. i--;
  248. d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
  249. }
  250. if (d & ~0x7F)
  251. {
  252. char[4] buf;
  253. char[] b;
  254. b = std.utf.toUTF8(buf, d);
  255. foreach (char c2; b)
  256. {
  257. result = dg(cast(void *)&c2);
  258. if (result)
  259. return result;
  260. }
  261. continue;
  262. }
  263. c = cast(char)d;
  264. result = dg(cast(void *)&c);
  265. if (result)
  266. break;
  267. }
  268. return result;
  269. }
  270. unittest
  271. {
  272. debug(apply) printf("_aApplyRwc1.unittest\n");
  273. wchar[] s = "hello";
  274. int i;
  275. foreach_reverse(char d; s)
  276. {
  277. switch (i)
  278. {
  279. case 0: assert(d == 'o'); break;
  280. case 1: assert(d == 'l'); break;
  281. case 2: assert(d == 'l'); break;
  282. case 3: assert(d == 'e'); break;
  283. case 4: assert(d == 'h'); break;
  284. default: assert(0);
  285. }
  286. i++;
  287. }
  288. assert(i == 5);
  289. s = "a\u1234\U00100456b";
  290. i = 0;
  291. foreach_reverse(char d; s)
  292. {
  293. //printf("i = %d, d = %x\n", i, d);
  294. switch (i)
  295. {
  296. case 0: assert(d == 'b'); break;
  297. case 1: assert(d == 0xF4); break;
  298. case 2: assert(d == 0x80); break;
  299. case 3: assert(d == 0x91); break;
  300. case 4: assert(d == 0x96); break;
  301. case 5: assert(d == 0xE1); break;
  302. case 6: assert(d == 0x88); break;
  303. case 7: assert(d == 0xB4); break;
  304. case 8: assert(d == 'a'); break;
  305. default: assert(0);
  306. }
  307. i++;
  308. }
  309. assert(i == 9);
  310. }
  311. /*****************************/
  312. extern (C) int _aApplyRdc1(dchar[] aa, dg_t dg)
  313. { int result;
  314. debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
  315. for (size_t i = aa.length; i != 0;)
  316. { dchar d = aa[--i];
  317. char c;
  318. if (d & ~0x7F)
  319. {
  320. char[4] buf;
  321. char[] b;
  322. b = std.utf.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";
  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(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";
  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(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. throw new std.utf.UtfException("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";
  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(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. throw new std.utf.UtfException("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";
  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(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. throw new std.utf.UtfException("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";
  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(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. throw new std.utf.UtfException("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. char[] b;
  671. b = std.utf.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. wchar[] s = "hello";
  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(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. char[] b;
  741. b = std.utf.toUTF8(buf, d);
  742. foreach (char c2; b)
  743. {
  744. result = dg(&i, cast(void *)&c2);
  745. if (result)
  746. return result;
  747. }
  748. continue;
  749. }
  750. else
  751. { c = cast(char)d;
  752. }
  753. result = dg(&i, cast(void *)&c);
  754. if (result)
  755. break;
  756. }
  757. return result;
  758. }
  759. unittest
  760. {
  761. debug(apply) printf("_aApplyRdc2.unittest\n");
  762. dchar[] s = "hello";
  763. int i;
  764. foreach_reverse(k, char d; s)
  765. {
  766. //printf("i = %d, k = %d, d = %x\n", i, k, d);
  767. assert(k == 4 - i);
  768. switch (i)
  769. {
  770. case 0: assert(d == 'o'); break;
  771. case 1: assert(d == 'l'); break;
  772. case 2: assert(d == 'l'); break;
  773. case 3: assert(d == 'e'); break;
  774. case 4: assert(d == 'h'); break;
  775. default: assert(0);
  776. }
  777. i++;
  778. }
  779. assert(i == 5);
  780. s = "a\u1234\U00100456b";
  781. i = 0;
  782. foreach_reverse(k, char d; s)
  783. {
  784. //printf("i = %d, k = %d, d = %x\n", i, k, d);
  785. switch (i)
  786. {
  787. case 0: assert(k == 3); assert(d == 'b'); break;
  788. case 1: assert(k == 2); assert(d == 0xF4); break;
  789. case 2: assert(k == 2); assert(d == 0x80); break;
  790. case 3: assert(k == 2); assert(d == 0x91); break;
  791. case 4: assert(k == 2); assert(d == 0x96); break;
  792. case 5: assert(k == 1); assert(d == 0xE1); break;
  793. case 6: assert(k == 1); assert(d == 0x88); break;
  794. case 7: assert(k == 1); assert(d == 0xB4); break;
  795. case 8: assert(k == 0); assert(d == 'a'); break;
  796. default: assert(0);
  797. }
  798. i++;
  799. }
  800. assert(i == 9);
  801. }
  802. /*****************************/
  803. extern (C) int _aApplyRdw2(dchar[] aa, dg2_t dg)
  804. { int result;
  805. debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
  806. for (size_t i = aa.length; i != 0; )
  807. { dchar d = aa[--i];
  808. wchar w;
  809. if (d <= 0xFFFF)
  810. w = cast(wchar) d;
  811. else
  812. {
  813. w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
  814. result = dg(&i, cast(void *)&w);
  815. if (result)
  816. break;
  817. w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
  818. }
  819. result = dg(&i, cast(void *)&w);
  820. if (result)
  821. break;
  822. }
  823. return result;
  824. }
  825. unittest
  826. {
  827. debug(apply) printf("_aApplyRdw2.unittest\n");
  828. dchar[] s = "hello";
  829. int i;
  830. foreach_reverse(k, wchar d; s)
  831. {
  832. //printf("i = %d, k = %d, d = %x\n", i, k, d);
  833. assert(k == 4 - i);
  834. switch (i)
  835. {
  836. case 0: assert(d == 'o'); break;
  837. case 1: assert(d == 'l'); break;
  838. case 2: assert(d == 'l'); break;
  839. case 3: assert(d == 'e'); break;
  840. case 4: assert(d == 'h'); break;
  841. default: assert(0);
  842. }
  843. i++;
  844. }
  845. assert(i == 5);
  846. s = "a\u1234\U00100456b";
  847. i = 0;
  848. foreach_reverse(k, wchar d; s)
  849. {
  850. //printf("i = %d, k = %d, d = %x\n", i, k, d);
  851. switch (i)
  852. {
  853. case 0: assert(k == 3); assert(d == 'b'); break;
  854. case 1: assert(k == 2); assert(d == 0xDBC1); break;
  855. case 2: assert(k == 2); assert(d == 0xDC56); break;
  856. case 3: assert(k == 1); assert(d == 0x1234); break;
  857. case 4: assert(k == 0); assert(d == 'a'); break;
  858. default: assert(0);
  859. }
  860. i++;
  861. }
  862. assert(i == 5);
  863. }