comparison lphobos/internal/switch.d @ 122:36ab367572df trunk

[svn r126] String switch is now implemented. A few other fixes.
author lindquist
date Tue, 27 Nov 2007 09:19:07 +0100
parents
children 373489eeaf90
comparison
equal deleted inserted replaced
121:9c79b61fb638 122:36ab367572df
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 import std.c.stdio;
26 import std.c.string;
27 import std.string;
28
29 /******************************************************
30 * Support for switch statements switching on strings.
31 * Input:
32 * table[] sorted array of strings generated by compiler
33 * ca string to look up in table
34 * Output:
35 * result index of match in table[]
36 * -1 if not in table
37 */
38
39 extern (C):
40
41 int _d_switch_string(char[][] table, char[] ca)
42 in
43 {
44 //printf("in _d_switch_string()\n");
45 assert(table.length >= 0);
46 assert(ca.length >= 0);
47
48 // Make sure table[] is sorted correctly
49 int j;
50
51 for (j = 1; j < table.length; j++)
52 {
53 int len1 = table[j - 1].length;
54 int len2 = table[j].length;
55
56 assert(len1 <= len2);
57 if (len1 == len2)
58 {
59 int ci;
60
61 ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
62 assert(ci < 0); // ci==0 means a duplicate
63 }
64 }
65 }
66 out (result)
67 {
68 int i;
69 int cj;
70
71 //printf("out _d_switch_string()\n");
72 if (result == -1)
73 {
74 // Not found
75 for (i = 0; i < table.length; i++)
76 {
77 if (table[i].length == ca.length)
78 { cj = memcmp(table[i].ptr, ca.ptr, ca.length);
79 assert(cj != 0);
80 }
81 }
82 }
83 else
84 {
85 assert(0 <= result && result < table.length);
86 for (i = 0; 1; i++)
87 {
88 assert(i < table.length);
89 if (table[i].length == ca.length)
90 {
91 cj = memcmp(table[i].ptr, ca.ptr, ca.length);
92 if (cj == 0)
93 {
94 assert(i == result);
95 break;
96 }
97 }
98 }
99 }
100 }
101 body
102 {
103 //printf("body _d_switch_string(%.*s)\n", ca);
104 int low;
105 int high;
106 int mid;
107 int c;
108 char[] pca;
109
110 low = 0;
111 high = table.length;
112
113 version (none)
114 {
115 // Print table
116 printf("ca[] = '%s'\n", cast(char *)ca);
117 for (mid = 0; mid < high; mid++)
118 {
119 pca = table[mid];
120 printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
121 }
122 }
123 if (high &&
124 ca.length >= table[0].length &&
125 ca.length <= table[high - 1].length)
126 {
127 // Looking for 0 length string, which would only be at the beginning
128 if (ca.length == 0)
129 return 0;
130
131 char c1 = ca[0];
132
133 // Do binary search
134 while (low < high)
135 {
136 mid = (low + high) >> 1;
137 pca = table[mid];
138 c = ca.length - pca.length;
139 if (c == 0)
140 {
141 c = cast(ubyte)c1 - cast(ubyte)pca[0];
142 if (c == 0)
143 {
144 c = memcmp(ca.ptr, pca.ptr, ca.length);
145 if (c == 0)
146 { //printf("found %d\n", mid);
147 return mid;
148 }
149 }
150 }
151 if (c < 0)
152 {
153 high = mid;
154 }
155 else
156 {
157 low = mid + 1;
158 }
159 }
160 }
161
162 //printf("not found\n");
163 return -1; // not found
164 }
165
166 unittest
167 {
168 switch (cast(char []) "c")
169 {
170 case "coo":
171 default:
172 break;
173 }
174 }
175
176 /**********************************
177 * Same thing, but for wide chars.
178 */
179
180 int _d_switch_ustring(wchar[][] table, wchar[] ca)
181 in
182 {
183 //printf("in _d_switch_ustring()\n");
184 assert(table.length >= 0);
185 assert(ca.length >= 0);
186
187 // Make sure table[] is sorted correctly
188 int j;
189
190 for (j = 1; j < table.length; j++)
191 {
192 int len1 = table[j - 1].length;
193 int len2 = table[j].length;
194
195 assert(len1 <= len2);
196 if (len1 == len2)
197 {
198 int c;
199
200 c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
201 assert(c < 0); // c==0 means a duplicate
202 }
203 }
204 }
205 out (result)
206 {
207 int i;
208 int c;
209
210 //printf("out _d_switch_string()\n");
211 if (result == -1)
212 {
213 // Not found
214 for (i = 0; i < table.length; i++)
215 {
216 if (table[i].length == ca.length)
217 { c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
218 assert(c != 0);
219 }
220 }
221 }
222 else
223 {
224 assert(0 <= result && result < table.length);
225 for (i = 0; 1; i++)
226 {
227 assert(i < table.length);
228 if (table[i].length == ca.length)
229 {
230 c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
231 if (c == 0)
232 {
233 assert(i == result);
234 break;
235 }
236 }
237 }
238 }
239 }
240 body
241 {
242 //printf("body _d_switch_ustring()\n");
243 int low;
244 int high;
245 int mid;
246 int c;
247 wchar[] pca;
248
249 low = 0;
250 high = table.length;
251
252 /*
253 // Print table
254 wprintf("ca[] = '%.*s'\n", ca);
255 for (mid = 0; mid < high; mid++)
256 {
257 pca = table[mid];
258 wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
259 }
260 */
261
262 // Do binary search
263 while (low < high)
264 {
265 mid = (low + high) >> 1;
266 pca = table[mid];
267 c = ca.length - pca.length;
268 if (c == 0)
269 {
270 c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
271 if (c == 0)
272 { //printf("found %d\n", mid);
273 return mid;
274 }
275 }
276 if (c < 0)
277 {
278 high = mid;
279 }
280 else
281 {
282 low = mid + 1;
283 }
284 }
285 //printf("not found\n");
286 return -1; // not found
287 }
288
289
290 unittest
291 {
292 switch (cast(wchar []) "c")
293 {
294 case "coo":
295 default:
296 break;
297 }
298 }
299
300
301 /**********************************
302 * Same thing, but for wide chars.
303 */
304
305 int _d_switch_dstring(dchar[][] table, dchar[] ca)
306 in
307 {
308 //printf("in _d_switch_dstring()\n");
309 assert(table.length >= 0);
310 assert(ca.length >= 0);
311
312 // Make sure table[] is sorted correctly
313 int j;
314
315 for (j = 1; j < table.length; j++)
316 {
317 int len1 = table[j - 1].length;
318 int len2 = table[j].length;
319
320 assert(len1 <= len2);
321 if (len1 == len2)
322 {
323 int c;
324
325 c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
326 assert(c < 0); // c==0 means a duplicate
327 }
328 }
329 }
330 out (result)
331 {
332 int i;
333 int c;
334
335 //printf("out _d_switch_string()\n");
336 if (result == -1)
337 {
338 // Not found
339 for (i = 0; i < table.length; i++)
340 {
341 if (table[i].length == ca.length)
342 { c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
343 assert(c != 0);
344 }
345 }
346 }
347 else
348 {
349 assert(0 <= result && result < table.length);
350 for (i = 0; 1; i++)
351 {
352 assert(i < table.length);
353 if (table[i].length == ca.length)
354 {
355 c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
356 if (c == 0)
357 {
358 assert(i == result);
359 break;
360 }
361 }
362 }
363 }
364 }
365 body
366 {
367 //printf("body _d_switch_ustring()\n");
368 int low;
369 int high;
370 int mid;
371 int c;
372 dchar[] pca;
373
374 low = 0;
375 high = table.length;
376
377 /*
378 // Print table
379 wprintf("ca[] = '%.*s'\n", ca);
380 for (mid = 0; mid < high; mid++)
381 {
382 pca = table[mid];
383 wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
384 }
385 */
386
387 // Do binary search
388 while (low < high)
389 {
390 mid = (low + high) >> 1;
391 pca = table[mid];
392 c = ca.length - pca.length;
393 if (c == 0)
394 {
395 c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
396 if (c == 0)
397 { //printf("found %d\n", mid);
398 return mid;
399 }
400 }
401 if (c < 0)
402 {
403 high = mid;
404 }
405 else
406 {
407 low = mid + 1;
408 }
409 }
410 //printf("not found\n");
411 return -1; // not found
412 }
413
414
415 unittest
416 {
417 switch (cast(dchar []) "c")
418 {
419 case "coo":
420 default:
421 break;
422 }
423 }
424
425
426