/lib/kruntime/src/rt/switch_.d
https://github.com/SDX2000/helios · D · 430 lines · 341 code · 37 blank · 52 comment · 80 complexity · cf9a6a6c4a3203ca283dad89b0d76ad2 MD5 · raw file
- /**
- * Contains support code for switch blocks using string constants.
- *
- * Copyright: Copyright Digital Mars 2004 - 2010.
- * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Walter Bright, Sean Kelly
- */
- /* Copyright Digital Mars 2004 - 2010.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
- module rt.switch_;
- private import core.stdc.string;
- /******************************************************
- * Support for switch statements switching on 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_string(char[][] table, char[] ca)
- in
- {
- //printf("in _d_switch_string()\n");
- assert(table.length >= 0);
- assert(ca.length >= 0);
- // Make sure table[] is sorted correctly
- int j;
- for (j = 1; j < table.length; j++)
- {
- auto len1 = table[j - 1].length;
- auto len2 = table[j].length;
- assert(len1 <= len2);
- if (len1 == len2)
- {
- int ci;
- ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
- assert(ci < 0); // ci==0 means a duplicate
- }
- }
- }
- out (result)
- {
- int i;
- int cj;
- //printf("out _d_switch_string()\n");
- if (result == -1)
- {
- // Not found
- for (i = 0; i < table.length; i++)
- {
- if (table[i].length == ca.length)
- { cj = memcmp(table[i].ptr, ca.ptr, ca.length);
- assert(cj != 0);
- }
- }
- }
- else
- {
- assert(0 <= result && result < table.length);
- for (i = 0; 1; i++)
- {
- assert(i < table.length);
- if (table[i].length == ca.length)
- {
- cj = memcmp(table[i].ptr, ca.ptr, ca.length);
- if (cj == 0)
- {
- assert(i == result);
- break;
- }
- }
- }
- }
- }
- body
- {
- //printf("body _d_switch_string(%.*s)\n", ca.length, ca.ptr);
- size_t low = 0;
- size_t high = table.length;
- version (none)
- {
- // Print table
- printf("ca[] = '%s'\n", ca.length, ca.ptr);
- for (auto i = 0; i < high; i++)
- {
- auto pca = table[i];
- printf("table[%d] = %d, '%.*s'\n", i, pca.length, pca.length, pca.ptr);
- }
- }
- if (high &&
- ca.length >= table[0].length &&
- ca.length <= table[high - 1].length)
- {
- // Looking for 0 length string, which would only be at the beginning
- if (ca.length == 0)
- return 0;
- char c1 = ca[0];
- // Do binary search
- while (low < high)
- {
- auto mid = (low + high) >> 1;
- auto pca = table[mid];
- auto c = cast(sizediff_t)(ca.length - pca.length);
- if (c == 0)
- {
- c = cast(ubyte)c1 - cast(ubyte)pca[0];
- if (c == 0)
- {
- c = memcmp(ca.ptr, pca.ptr, ca.length);
- if (c == 0)
- { //printf("found %d\n", mid);
- return cast(int)mid;
- }
- }
- }
- if (c < 0)
- {
- high = mid;
- }
- else
- {
- low = mid + 1;
- }
- }
- }
- //printf("not found\n");
- return -1; // not found
- }
- unittest
- {
- switch (cast(char []) "c")
- {
- case "coo":
- default:
- break;
- }
- int bug5381(string s)
- {
- switch(s)
- {
- case "unittest": return 1;
- case "D_Version2": return 2;
- case "none": return 3;
- case "all": return 4;
- default: return 5;
- }
- }
- int rc = bug5381("none");
- assert(rc == 3);
- }
- /**********************************
- * Same thing, but for wide chars.
- */
- int _d_switch_ustring(wchar[][] table, wchar[] ca)
- in
- {
- //printf("in _d_switch_ustring()\n");
- assert(table.length >= 0);
- assert(ca.length >= 0);
- // Make sure table[] is sorted correctly
- int j;
- for (j = 1; j < table.length; j++)
- {
- auto len1 = table[j - 1].length;
- auto len2 = table[j].length;
- assert(len1 <= len2);
- if (len1 == len2)
- {
- int c;
- c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
- assert(c < 0); // c==0 means a duplicate
- }
- }
- }
- out (result)
- {
- int i;
- int c;
- //printf("out _d_switch_ustring()\n");
- if (result == -1)
- {
- // Not found
- for (i = 0; i < table.length; i++)
- {
- if (table[i].length == ca.length)
- { c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
- 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)
- {
- c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
- if (c == 0)
- {
- assert(i == result);
- break;
- }
- }
- }
- }
- }
- body
- {
- //printf("body _d_switch_ustring()\n");
- size_t low = 0;
- auto high = table.length;
- version(none)
- {
- // Print table
- wprintf("ca[] = '%.*s'\n", ca.length, ca.ptr);
- for (auto i = 0; i < high; i++)
- {
- auto pca = table[i];
- wprintf("table[%d] = %d, '%.*s'\n", i, pca.length, pca.length, pca.ptr);
- }
- }
- // Do binary search
- while (low < high)
- {
- auto mid = (low + high) >> 1;
- auto pca = table[mid];
- auto c = cast(sizediff_t)(ca.length - pca.length);
- if (c == 0)
- {
- c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
- if (c == 0)
- { //printf("found %d\n", mid);
- return cast(int)mid;
- }
- }
- if (c < 0)
- {
- high = mid;
- }
- else
- {
- low = mid + 1;
- }
- }
- //printf("not found\n");
- return -1; // not found
- }
- unittest
- {
- switch (cast(wchar []) "c")
- {
- case "coo":
- default:
- break;
- }
- int bug5381(wstring ws)
- {
- switch(ws)
- {
- case "unittest": return 1;
- case "D_Version2": return 2;
- case "none": return 3;
- case "all": return 4;
- default: return 5;
- }
- }
- int rc = bug5381("none"w);
- assert(rc == 3);
- }
- /**********************************
- * Same thing, but for wide chars.
- */
- int _d_switch_dstring(dchar[][] table, dchar[] ca)
- in
- {
- //printf("in _d_switch_dstring()\n");
- assert(table.length >= 0);
- assert(ca.length >= 0);
- // Make sure table[] is sorted correctly
- for (auto j = 1; j < table.length; j++)
- {
- auto len1 = table[j - 1].length;
- auto len2 = table[j].length;
- assert(len1 <= len2);
- if (len1 == len2)
- {
- auto c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
- assert(c < 0); // c==0 means a duplicate
- }
- }
- }
- out (result)
- {
- //printf("out _d_switch_dstring()\n");
- if (result == -1)
- {
- // Not found
- for (auto i = 0; i < table.length; i++)
- {
- if (table[i].length == ca.length)
- { auto c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
- assert(c != 0);
- }
- }
- }
- else
- {
- assert(0 <= result && result < table.length);
- for (auto i = 0; 1; i++)
- {
- assert(i < table.length);
- if (table[i].length == ca.length)
- {
- auto c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
- if (c == 0)
- {
- assert(i == result);
- break;
- }
- }
- }
- }
- }
- body
- {
- //printf("body _d_switch_dstring()\n");
- size_t low = 0;
- auto high = table.length;
- version(none)
- {
- // Print table
- wprintf("ca[] = '%.*s'\n", ca.length, ca.ptr);
- for (auto i = 0; i < high; i++)
- {
- auto pca = table[i];
- wprintf("table[%d] = %d, '%.*s'\n", i, pca.length, pca.length, pca.ptr);
- }
- }
- // Do binary search
- while (low < high)
- {
- auto mid = (low + high) >> 1;
- auto pca = table[mid];
- auto c = cast(sizediff_t)(ca.length - pca.length);
- if (c == 0)
- {
- c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
- if (c == 0)
- { //printf("found %d\n", mid);
- return cast(int)mid;
- }
- }
- if (c < 0)
- {
- high = mid;
- }
- else
- {
- low = mid + 1;
- }
- }
- //printf("not found\n");
- return -1; // not found
- }
- unittest
- {
- switch (cast(dchar []) "c")
- {
- case "coo":
- default:
- break;
- }
- int bug5381(dstring ds)
- {
- switch(ds)
- {
- case "unittest": return 1;
- case "D_Version2": return 2;
- case "none": return 3;
- case "all": return 4;
- default: return 5;
- }
- }
- int rc = bug5381("none"d);
- assert(rc == 3);
- }