/lib/kruntime/src/rt/switch_.d

https://github.com/SDX2000/helios · D · 430 lines · 341 code · 37 blank · 52 comment · 80 complexity · cf9a6a6c4a3203ca283dad89b0d76ad2 MD5 · raw file

  1. /**
  2. * Contains support code for switch blocks using string constants.
  3. *
  4. * Copyright: Copyright Digital Mars 2004 - 2010.
  5. * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
  6. * Authors: Walter Bright, Sean Kelly
  7. */
  8. /* Copyright Digital Mars 2004 - 2010.
  9. * Distributed under the Boost Software License, Version 1.0.
  10. * (See accompanying file LICENSE_1_0.txt or copy at
  11. * http://www.boost.org/LICENSE_1_0.txt)
  12. */
  13. module rt.switch_;
  14. private import core.stdc.string;
  15. /******************************************************
  16. * Support for switch statements switching on strings.
  17. * Input:
  18. * table[] sorted array of strings generated by compiler
  19. * ca string to look up in table
  20. * Output:
  21. * result index of match in table[]
  22. * -1 if not in table
  23. */
  24. extern (C):
  25. int _d_switch_string(char[][] table, char[] ca)
  26. in
  27. {
  28. //printf("in _d_switch_string()\n");
  29. assert(table.length >= 0);
  30. assert(ca.length >= 0);
  31. // Make sure table[] is sorted correctly
  32. int j;
  33. for (j = 1; j < table.length; j++)
  34. {
  35. auto len1 = table[j - 1].length;
  36. auto len2 = table[j].length;
  37. assert(len1 <= len2);
  38. if (len1 == len2)
  39. {
  40. int ci;
  41. ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
  42. assert(ci < 0); // ci==0 means a duplicate
  43. }
  44. }
  45. }
  46. out (result)
  47. {
  48. int i;
  49. int cj;
  50. //printf("out _d_switch_string()\n");
  51. if (result == -1)
  52. {
  53. // Not found
  54. for (i = 0; i < table.length; i++)
  55. {
  56. if (table[i].length == ca.length)
  57. { cj = memcmp(table[i].ptr, ca.ptr, ca.length);
  58. assert(cj != 0);
  59. }
  60. }
  61. }
  62. else
  63. {
  64. assert(0 <= result && result < table.length);
  65. for (i = 0; 1; i++)
  66. {
  67. assert(i < table.length);
  68. if (table[i].length == ca.length)
  69. {
  70. cj = memcmp(table[i].ptr, ca.ptr, ca.length);
  71. if (cj == 0)
  72. {
  73. assert(i == result);
  74. break;
  75. }
  76. }
  77. }
  78. }
  79. }
  80. body
  81. {
  82. //printf("body _d_switch_string(%.*s)\n", ca.length, ca.ptr);
  83. size_t low = 0;
  84. size_t high = table.length;
  85. version (none)
  86. {
  87. // Print table
  88. printf("ca[] = '%s'\n", ca.length, ca.ptr);
  89. for (auto i = 0; i < high; i++)
  90. {
  91. auto pca = table[i];
  92. printf("table[%d] = %d, '%.*s'\n", i, pca.length, pca.length, pca.ptr);
  93. }
  94. }
  95. if (high &&
  96. ca.length >= table[0].length &&
  97. ca.length <= table[high - 1].length)
  98. {
  99. // Looking for 0 length string, which would only be at the beginning
  100. if (ca.length == 0)
  101. return 0;
  102. char c1 = ca[0];
  103. // Do binary search
  104. while (low < high)
  105. {
  106. auto mid = (low + high) >> 1;
  107. auto pca = table[mid];
  108. auto c = cast(sizediff_t)(ca.length - pca.length);
  109. if (c == 0)
  110. {
  111. c = cast(ubyte)c1 - cast(ubyte)pca[0];
  112. if (c == 0)
  113. {
  114. c = memcmp(ca.ptr, pca.ptr, ca.length);
  115. if (c == 0)
  116. { //printf("found %d\n", mid);
  117. return cast(int)mid;
  118. }
  119. }
  120. }
  121. if (c < 0)
  122. {
  123. high = mid;
  124. }
  125. else
  126. {
  127. low = mid + 1;
  128. }
  129. }
  130. }
  131. //printf("not found\n");
  132. return -1; // not found
  133. }
  134. unittest
  135. {
  136. switch (cast(char []) "c")
  137. {
  138. case "coo":
  139. default:
  140. break;
  141. }
  142. int bug5381(string s)
  143. {
  144. switch(s)
  145. {
  146. case "unittest": return 1;
  147. case "D_Version2": return 2;
  148. case "none": return 3;
  149. case "all": return 4;
  150. default: return 5;
  151. }
  152. }
  153. int rc = bug5381("none");
  154. assert(rc == 3);
  155. }
  156. /**********************************
  157. * Same thing, but for wide chars.
  158. */
  159. int _d_switch_ustring(wchar[][] table, wchar[] ca)
  160. in
  161. {
  162. //printf("in _d_switch_ustring()\n");
  163. assert(table.length >= 0);
  164. assert(ca.length >= 0);
  165. // Make sure table[] is sorted correctly
  166. int j;
  167. for (j = 1; j < table.length; j++)
  168. {
  169. auto len1 = table[j - 1].length;
  170. auto len2 = table[j].length;
  171. assert(len1 <= len2);
  172. if (len1 == len2)
  173. {
  174. int c;
  175. c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
  176. assert(c < 0); // c==0 means a duplicate
  177. }
  178. }
  179. }
  180. out (result)
  181. {
  182. int i;
  183. int c;
  184. //printf("out _d_switch_ustring()\n");
  185. if (result == -1)
  186. {
  187. // Not found
  188. for (i = 0; i < table.length; i++)
  189. {
  190. if (table[i].length == ca.length)
  191. { c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
  192. assert(c != 0);
  193. }
  194. }
  195. }
  196. else
  197. {
  198. assert(0 <= result && result < table.length);
  199. for (i = 0; 1; i++)
  200. {
  201. assert(i < table.length);
  202. if (table[i].length == ca.length)
  203. {
  204. c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
  205. if (c == 0)
  206. {
  207. assert(i == result);
  208. break;
  209. }
  210. }
  211. }
  212. }
  213. }
  214. body
  215. {
  216. //printf("body _d_switch_ustring()\n");
  217. size_t low = 0;
  218. auto high = table.length;
  219. version(none)
  220. {
  221. // Print table
  222. wprintf("ca[] = '%.*s'\n", ca.length, ca.ptr);
  223. for (auto i = 0; i < high; i++)
  224. {
  225. auto pca = table[i];
  226. wprintf("table[%d] = %d, '%.*s'\n", i, pca.length, pca.length, pca.ptr);
  227. }
  228. }
  229. // Do binary search
  230. while (low < high)
  231. {
  232. auto mid = (low + high) >> 1;
  233. auto pca = table[mid];
  234. auto c = cast(sizediff_t)(ca.length - pca.length);
  235. if (c == 0)
  236. {
  237. c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
  238. if (c == 0)
  239. { //printf("found %d\n", mid);
  240. return cast(int)mid;
  241. }
  242. }
  243. if (c < 0)
  244. {
  245. high = mid;
  246. }
  247. else
  248. {
  249. low = mid + 1;
  250. }
  251. }
  252. //printf("not found\n");
  253. return -1; // not found
  254. }
  255. unittest
  256. {
  257. switch (cast(wchar []) "c")
  258. {
  259. case "coo":
  260. default:
  261. break;
  262. }
  263. int bug5381(wstring ws)
  264. {
  265. switch(ws)
  266. {
  267. case "unittest": return 1;
  268. case "D_Version2": return 2;
  269. case "none": return 3;
  270. case "all": return 4;
  271. default: return 5;
  272. }
  273. }
  274. int rc = bug5381("none"w);
  275. assert(rc == 3);
  276. }
  277. /**********************************
  278. * Same thing, but for wide chars.
  279. */
  280. int _d_switch_dstring(dchar[][] table, dchar[] ca)
  281. in
  282. {
  283. //printf("in _d_switch_dstring()\n");
  284. assert(table.length >= 0);
  285. assert(ca.length >= 0);
  286. // Make sure table[] is sorted correctly
  287. for (auto j = 1; j < table.length; j++)
  288. {
  289. auto len1 = table[j - 1].length;
  290. auto len2 = table[j].length;
  291. assert(len1 <= len2);
  292. if (len1 == len2)
  293. {
  294. auto c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
  295. assert(c < 0); // c==0 means a duplicate
  296. }
  297. }
  298. }
  299. out (result)
  300. {
  301. //printf("out _d_switch_dstring()\n");
  302. if (result == -1)
  303. {
  304. // Not found
  305. for (auto i = 0; i < table.length; i++)
  306. {
  307. if (table[i].length == ca.length)
  308. { auto c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
  309. assert(c != 0);
  310. }
  311. }
  312. }
  313. else
  314. {
  315. assert(0 <= result && result < table.length);
  316. for (auto i = 0; 1; i++)
  317. {
  318. assert(i < table.length);
  319. if (table[i].length == ca.length)
  320. {
  321. auto c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
  322. if (c == 0)
  323. {
  324. assert(i == result);
  325. break;
  326. }
  327. }
  328. }
  329. }
  330. }
  331. body
  332. {
  333. //printf("body _d_switch_dstring()\n");
  334. size_t low = 0;
  335. auto high = table.length;
  336. version(none)
  337. {
  338. // Print table
  339. wprintf("ca[] = '%.*s'\n", ca.length, ca.ptr);
  340. for (auto i = 0; i < high; i++)
  341. {
  342. auto pca = table[i];
  343. wprintf("table[%d] = %d, '%.*s'\n", i, pca.length, pca.length, pca.ptr);
  344. }
  345. }
  346. // Do binary search
  347. while (low < high)
  348. {
  349. auto mid = (low + high) >> 1;
  350. auto pca = table[mid];
  351. auto c = cast(sizediff_t)(ca.length - pca.length);
  352. if (c == 0)
  353. {
  354. c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
  355. if (c == 0)
  356. { //printf("found %d\n", mid);
  357. return cast(int)mid;
  358. }
  359. }
  360. if (c < 0)
  361. {
  362. high = mid;
  363. }
  364. else
  365. {
  366. low = mid + 1;
  367. }
  368. }
  369. //printf("not found\n");
  370. return -1; // not found
  371. }
  372. unittest
  373. {
  374. switch (cast(dchar []) "c")
  375. {
  376. case "coo":
  377. default:
  378. break;
  379. }
  380. int bug5381(dstring ds)
  381. {
  382. switch(ds)
  383. {
  384. case "unittest": return 1;
  385. case "D_Version2": return 2;
  386. case "none": return 3;
  387. case "all": return 4;
  388. default: return 5;
  389. }
  390. }
  391. int rc = bug5381("none"d);
  392. assert(rc == 3);
  393. }