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








"Walter" <walter digitalmars.com>