Mercurial > projects > ldc
annotate tango/lib/compiler/llvmdc/switch.d @ 341:1bb99290e03a trunk
[svn r362] Started merging the old 'test' dir as well as the newer 'tangotests' dir into 'tests/mini' and 'tests/minicomplex'.
author | lindquist |
---|---|
date | Sun, 13 Jul 2008 02:51:19 +0200 |
parents | 1e6e2b5d5bfe |
children |
rev | line source |
---|---|
132 | 1 /* |
2 * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com | |
3 * Written by Walter Bright | |
4 * | |
5 * This software is provided 'as-is', without any express or implied | |
6 * warranty. In no event will the authors be held liable for any damages | |
7 * arising from the use of this software. | |
8 * | |
9 * Permission is granted to anyone to use this software for any purpose, | |
10 * including commercial applications, and to alter it and redistribute it | |
11 * freely, in both source and binary form, subject to the following | |
12 * restrictions: | |
13 * | |
14 * o The origin of this software must not be misrepresented; you must not | |
15 * claim that you wrote the original software. If you use this software | |
16 * in a product, an acknowledgment in the product documentation would be | |
17 * appreciated but is not required. | |
18 * o Altered source versions must be plainly marked as such, and must not | |
19 * be misrepresented as being the original software. | |
20 * o This notice may not be removed or altered from any source | |
21 * distribution. | |
22 */ | |
23 | |
24 /* | |
25 * Modified by Sean Kelly <sean@f4.ca> for use with Tango. | |
26 */ | |
27 | |
28 private import tango.stdc.string; | |
271
1e6e2b5d5bfe
[svn r292] Fixed: string switch was broken in several ways.
lindquist
parents:
132
diff
changeset
|
29 //private import tango.stdc.stdio; |
132 | 30 |
31 /****************************************************** | |
32 * Support for switch statements switching on strings. | |
33 * Input: | |
34 * table[] sorted array of strings generated by compiler | |
35 * ca string to look up in table | |
36 * Output: | |
37 * result index of match in table[] | |
38 * -1 if not in table | |
39 */ | |
40 | |
41 extern (C): | |
42 | |
43 int _d_switch_string(char[][] table, char[] ca) | |
44 in | |
45 { | |
46 //printf("in _d_switch_string()\n"); | |
47 assert(table.length >= 0); | |
48 assert(ca.length >= 0); | |
49 | |
50 // Make sure table[] is sorted correctly | |
51 int j; | |
52 | |
53 for (j = 1; j < table.length; j++) | |
54 { | |
55 size_t len1 = table[j - 1].length; | |
56 size_t len2 = table[j].length; | |
57 | |
58 assert(len1 <= len2); | |
59 if (len1 == len2) | |
60 { | |
61 int ci; | |
62 | |
63 ci = memcmp(table[j - 1].ptr, table[j].ptr, len1); | |
64 assert(ci < 0); // ci==0 means a duplicate | |
65 } | |
66 } | |
67 } | |
68 out (result) | |
69 { | |
70 int i; | |
71 int cj; | |
72 | |
73 //printf("out _d_switch_string()\n"); | |
74 if (result == -1) | |
75 { | |
76 // Not found | |
77 for (i = 0; i < table.length; i++) | |
78 { | |
79 if (table[i].length == ca.length) | |
80 { cj = memcmp(table[i].ptr, ca.ptr, ca.length); | |
81 assert(cj != 0); | |
82 } | |
83 } | |
84 } | |
85 else | |
86 { | |
87 assert(0 <= result && result < table.length); | |
88 for (i = 0; 1; i++) | |
89 { | |
90 assert(i < table.length); | |
91 if (table[i].length == ca.length) | |
92 { | |
93 cj = memcmp(table[i].ptr, ca.ptr, ca.length); | |
94 if (cj == 0) | |
95 { | |
96 assert(i == result); | |
97 break; | |
98 } | |
99 } | |
100 } | |
101 } | |
102 } | |
103 body | |
104 { | |
271
1e6e2b5d5bfe
[svn r292] Fixed: string switch was broken in several ways.
lindquist
parents:
132
diff
changeset
|
105 //printf("body _d_switch_string(%.*s)\n", ca.length, ca.ptr); |
132 | 106 size_t low; |
107 size_t high; | |
108 size_t mid; | |
271
1e6e2b5d5bfe
[svn r292] Fixed: string switch was broken in several ways.
lindquist
parents:
132
diff
changeset
|
109 ptrdiff_t c; |
132 | 110 char[] pca; |
111 | |
112 low = 0; | |
113 high = table.length; | |
114 | |
115 version (none) | |
116 { | |
117 // Print table | |
118 printf("ca[] = '%s'\n", cast(char *)ca); | |
119 for (mid = 0; mid < high; mid++) | |
120 { | |
121 pca = table[mid]; | |
122 printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); | |
123 } | |
124 } | |
125 if (high && | |
126 ca.length >= table[0].length && | |
127 ca.length <= table[high - 1].length) | |
128 { | |
129 // Looking for 0 length string, which would only be at the beginning | |
130 if (ca.length == 0) | |
131 return 0; | |
132 | |
133 char c1 = ca[0]; | |
134 | |
135 // Do binary search | |
136 while (low < high) | |
137 { | |
138 mid = (low + high) >> 1; | |
139 pca = table[mid]; | |
271
1e6e2b5d5bfe
[svn r292] Fixed: string switch was broken in several ways.
lindquist
parents:
132
diff
changeset
|
140 c = cast(ptrdiff_t)(ca.length - pca.length); |
132 | 141 if (c == 0) |
142 { | |
143 c = cast(ubyte)c1 - cast(ubyte)pca[0]; | |
144 if (c == 0) | |
145 { | |
146 c = memcmp(ca.ptr, pca.ptr, ca.length); | |
147 if (c == 0) | |
148 { //printf("found %d\n", mid); | |
149 return cast(int)mid; | |
150 } | |
151 } | |
152 } | |
153 if (c < 0) | |
154 { | |
155 high = mid; | |
156 } | |
157 else | |
158 { | |
159 low = mid + 1; | |
160 } | |
161 } | |
162 } | |
163 | |
164 //printf("not found\n"); | |
165 return -1; // not found | |
166 } | |
167 | |
168 unittest | |
169 { | |
170 switch (cast(char []) "c") | |
171 { | |
172 case "coo": | |
173 default: | |
174 break; | |
175 } | |
176 } | |
177 | |
178 /********************************** | |
179 * Same thing, but for wide chars. | |
180 */ | |
181 | |
182 int _d_switch_ustring(wchar[][] table, wchar[] ca) | |
183 in | |
184 { | |
185 //printf("in _d_switch_ustring()\n"); | |
186 assert(table.length >= 0); | |
187 assert(ca.length >= 0); | |
188 | |
189 // Make sure table[] is sorted correctly | |
190 int j; | |
191 | |
192 for (j = 1; j < table.length; j++) | |
193 { | |
194 size_t len1 = table[j - 1].length; | |
195 size_t len2 = table[j].length; | |
196 | |
197 assert(len1 <= len2); | |
198 if (len1 == len2) | |
199 { | |
200 int c; | |
201 | |
202 c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof); | |
203 assert(c < 0); // c==0 means a duplicate | |
204 } | |
205 } | |
206 } | |
207 out (result) | |
208 { | |
209 int i; | |
210 int c; | |
211 | |
212 //printf("out _d_switch_string()\n"); | |
213 if (result == -1) | |
214 { | |
215 // Not found | |
216 for (i = 0; i < table.length; i++) | |
217 { | |
218 if (table[i].length == ca.length) | |
219 { c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); | |
220 assert(c != 0); | |
221 } | |
222 } | |
223 } | |
224 else | |
225 { | |
226 assert(0 <= result && result < table.length); | |
227 for (i = 0; 1; i++) | |
228 { | |
229 assert(i < table.length); | |
230 if (table[i].length == ca.length) | |
231 { | |
232 c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); | |
233 if (c == 0) | |
234 { | |
235 assert(i == result); | |
236 break; | |
237 } | |
238 } | |
239 } | |
240 } | |
241 } | |
242 body | |
243 { | |
244 //printf("body _d_switch_ustring()\n"); | |
245 size_t low; | |
246 size_t high; | |
247 size_t mid; | |
271
1e6e2b5d5bfe
[svn r292] Fixed: string switch was broken in several ways.
lindquist
parents:
132
diff
changeset
|
248 ptrdiff_t c; |
132 | 249 wchar[] pca; |
250 | |
251 low = 0; | |
252 high = table.length; | |
253 | |
254 /* | |
255 // Print table | |
256 wprintf("ca[] = '%.*s'\n", ca); | |
257 for (mid = 0; mid < high; mid++) | |
258 { | |
259 pca = table[mid]; | |
260 wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); | |
261 } | |
262 */ | |
263 | |
264 // Do binary search | |
265 while (low < high) | |
266 { | |
267 mid = (low + high) >> 1; | |
268 pca = table[mid]; | |
271
1e6e2b5d5bfe
[svn r292] Fixed: string switch was broken in several ways.
lindquist
parents:
132
diff
changeset
|
269 c = cast(ptrdiff_t)(ca.length - pca.length); |
132 | 270 if (c == 0) |
271 { | |
272 c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof); | |
273 if (c == 0) | |
274 { //printf("found %d\n", mid); | |
275 return cast(int)mid; | |
276 } | |
277 } | |
278 if (c < 0) | |
279 { | |
280 high = mid; | |
281 } | |
282 else | |
283 { | |
284 low = mid + 1; | |
285 } | |
286 } | |
287 //printf("not found\n"); | |
288 return -1; // not found | |
289 } | |
290 | |
291 | |
292 unittest | |
293 { | |
294 switch (cast(wchar []) "c") | |
295 { | |
296 case "coo": | |
297 default: | |
298 break; | |
299 } | |
300 } | |
301 | |
302 | |
303 /********************************** | |
304 * Same thing, but for wide chars. | |
305 */ | |
306 | |
307 int _d_switch_dstring(dchar[][] table, dchar[] ca) | |
308 in | |
309 { | |
310 //printf("in _d_switch_dstring()\n"); | |
311 assert(table.length >= 0); | |
312 assert(ca.length >= 0); | |
313 | |
314 // Make sure table[] is sorted correctly | |
315 int j; | |
316 | |
317 for (j = 1; j < table.length; j++) | |
318 { | |
319 size_t len1 = table[j - 1].length; | |
320 size_t len2 = table[j].length; | |
321 | |
322 assert(len1 <= len2); | |
323 if (len1 == len2) | |
324 { | |
325 int c; | |
326 | |
327 c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof); | |
328 assert(c < 0); // c==0 means a duplicate | |
329 } | |
330 } | |
331 } | |
332 out (result) | |
333 { | |
334 int i; | |
335 int c; | |
336 | |
337 //printf("out _d_switch_string()\n"); | |
338 if (result == -1) | |
339 { | |
340 // Not found | |
341 for (i = 0; i < table.length; i++) | |
342 { | |
343 if (table[i].length == ca.length) | |
344 { c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof); | |
345 assert(c != 0); | |
346 } | |
347 } | |
348 } | |
349 else | |
350 { | |
351 assert(0 <= result && result < table.length); | |
352 for (i = 0; 1; i++) | |
353 { | |
354 assert(i < table.length); | |
355 if (table[i].length == ca.length) | |
356 { | |
357 c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof); | |
358 if (c == 0) | |
359 { | |
360 assert(i == result); | |
361 break; | |
362 } | |
363 } | |
364 } | |
365 } | |
366 } | |
367 body | |
368 { | |
369 //printf("body _d_switch_ustring()\n"); | |
370 size_t low; | |
371 size_t high; | |
372 size_t mid; | |
271
1e6e2b5d5bfe
[svn r292] Fixed: string switch was broken in several ways.
lindquist
parents:
132
diff
changeset
|
373 ptrdiff_t c; |
132 | 374 dchar[] pca; |
375 | |
376 low = 0; | |
377 high = table.length; | |
378 | |
379 /* | |
380 // Print table | |
381 wprintf("ca[] = '%.*s'\n", ca); | |
382 for (mid = 0; mid < high; mid++) | |
383 { | |
384 pca = table[mid]; | |
385 wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); | |
386 } | |
387 */ | |
388 | |
389 // Do binary search | |
390 while (low < high) | |
391 { | |
392 mid = (low + high) >> 1; | |
393 pca = table[mid]; | |
271
1e6e2b5d5bfe
[svn r292] Fixed: string switch was broken in several ways.
lindquist
parents:
132
diff
changeset
|
394 c = cast(ptrdiff_t)(ca.length - pca.length); |
132 | 395 if (c == 0) |
396 { | |
397 c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof); | |
398 if (c == 0) | |
399 { //printf("found %d\n", mid); | |
400 return cast(int)mid; | |
401 } | |
402 } | |
403 if (c < 0) | |
404 { | |
405 high = mid; | |
406 } | |
407 else | |
408 { | |
409 low = mid + 1; | |
410 } | |
411 } | |
412 //printf("not found\n"); | |
413 return -1; // not found | |
414 } | |
415 | |
416 | |
417 unittest | |
418 { | |
419 switch (cast(dchar []) "c") | |
420 { | |
421 case "coo": | |
422 default: | |
423 break; | |
424 } | |
425 } |