D - String switch bug and wide string switching
- Burton Radons (120/120) Jun 16 2002 switch ((char []) "c")
- Walter (1/1) Jun 17 2002 Thanks, Burton! -Walter
switch ((char []) "c") { case "coo": default: break; } Throws an assertion failure during runtime in switch.d(54). The reason is that the out contract assertion check is wrong - it's checking that the switch failed correctly, but in doing so it's only comparing the first bytes of the match, not the lengths, so it thinks it's buggy when in fact the contract is. Simply adding a length check should fix the problem. The out check for success is also wrong - it could give a false positive for a broken implementation, so it should have a length check too. Also, "Symbol Undefined __d_switch_ustring" if the "(char [])" cast is removed - wchar[] switching isn't implemented. Here's the function converted over, I think, with the length fixes applied: /****************************************************** * Support for switch statements switching on wide strings. * Input: * table[] sorted array of strings generated by compiler * ca string to look up in table * Output: * result index of match in table[] * -1 if not in table */ extern (C): int _d_switch_ustring(wchar[][] table, wchar[] ca) in { //printf("in _d_switch_string()\n"); assert(table.length >= 0); assert(ca.length >= 0); // Make sure table[] is sorted correctly int i; for (i = 1; i < table.length; i++) { int len1 = table[i - 1].length; int len2 = table[i].length; assert(len1 <= len2); if (len1 == len2) { int c; c = memcmp(table[i - 1], table[i], len1 * wchar.size); assert(c < 0); // c==0 means a duplicate } } } out (result) { int i; int c; //printf("out _d_switch_string()\n"); if (result == -1) { // Not found for (i = 0; i < table.length; i++) { if (table[i].length != c = memcmp(table[i], ca, ca.length * wchar.size); assert(c != 0); } } else { assert(0 <= result && result < table.length); for (i = 0; 1; i++) { assert(i < table.length); if (table[i].length != ca.length) continue; c = memcmp(table[i], ca, ca.length * wchar.size); if (c == 0) { assert(i == result); break; } } } } body { //printf("body _d_switch_string()\n"); int low; int high; int mid; int c; wchar[] pca; low = 0; high = table.length; // Do binary search while (low < high) { mid = (low + high) >> 1; pca = table[mid]; c = ca.length - pca.length; if (c == 0) { c = memcmp(ca, pca, ca.length * wchar.size); if (c == 0) { //printf("found %d\n", mid); return mid; } } if (c < 0) { high = mid; } else { low = mid + 1; } } //printf("not found\n"); return -1; // not found }
Jun 16 2002