dyaml/source/dyaml/fastcharsearch.d
2014-07-23 00:38:51 +02:00

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;
}