97 lines
2.4 KiB
D
97 lines
2.4 KiB
D
|
|
// Copyright Ferdinand Majerech 2011.
|
|
// 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 dyaml.fastcharsearch;
|
|
|
|
|
|
import std.algorithm;
|
|
import std.conv;
|
|
|
|
|
|
package:
|
|
|
|
/**
|
|
* Mixin used for fast searching for a character in string.
|
|
*
|
|
* Creates a lookup table to quickly determine if a character
|
|
* is present in the string. Size of the lookup table is limited;
|
|
* any characters not represented in the table will be checked
|
|
* by ordinary equality comparison.
|
|
*
|
|
* Params: chars = String to search in.
|
|
* tableSize = Maximum number of bytes used by the table.
|
|
*
|
|
* Generated method:
|
|
* bool canFind(dchar c)
|
|
*
|
|
* Determines if a character is in the string.
|
|
*/
|
|
template FastCharSearch(dstring chars, uint tableSize = 256)
|
|
{
|
|
private mixin(searchCode!(chars, tableSize)());
|
|
}
|
|
|
|
///Generate the search table and the canFind method.
|
|
string searchCode(dstring chars, uint tableSize)() @safe pure nothrow
|
|
{
|
|
const tableSizeStr = to!string(tableSize);
|
|
ubyte[tableSize] table;
|
|
table[] = 0;
|
|
|
|
//Characters that don't fit in the table.
|
|
dchar[] specialChars;
|
|
|
|
foreach(c; chars)
|
|
{
|
|
if(c < tableSize){table[c] = 1;}
|
|
else {specialChars ~= c;}
|
|
}
|
|
|
|
string tableCode()
|
|
{
|
|
string code = "static immutable ubyte table_[" ~ tableSizeStr ~ "] = [\n";
|
|
foreach(c; table[0 .. $ - 1])
|
|
{
|
|
code ~= c ? "true,\n" : "false,\n";
|
|
}
|
|
code ~= table[$ - 1] ? "true\n" : "false\n";
|
|
code ~= "];\n\n";
|
|
return code;
|
|
}
|
|
|
|
string specialCharsCode()
|
|
{
|
|
string code;
|
|
foreach(c; specialChars[0 .. $ - 1])
|
|
{
|
|
code ~= "cast(uint)c == " ~ to!string(cast(uint)c) ~ " || ";
|
|
}
|
|
code ~= "cast(uint)c == " ~ to!string(cast(uint)specialChars[$ - 1]);
|
|
|
|
return code;
|
|
}
|
|
|
|
string code = tableSize ? tableCode() : "";
|
|
|
|
code ~= "bool canFind(in dchar c) pure @safe nothrow @nogc\n"
|
|
"{\n";
|
|
|
|
if(tableSize)
|
|
{
|
|
code ~= " if(c < " ~ tableSizeStr ~ ")\n"
|
|
" {\n"
|
|
" return cast(immutable(bool))table_[c];\n"
|
|
" }\n";
|
|
}
|
|
|
|
code ~= specialChars.length
|
|
? " return " ~ specialCharsCode() ~ ";\n"
|
|
: " return false;";
|
|
code ~= "}\n";
|
|
|
|
return code;
|
|
}
|