www.digitalmars.com         C & C++   DMDScript  

D - String switch bug and wide string switching

reply Burton Radons <loth users.sourceforge.net> writes:
     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
parent "Walter" <walter digitalmars.com> writes:
Thanks, Burton! -Walter
Jun 17 2002