122
|
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
|