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