1 2 // Copyright Ferdinand Majerech 2011. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 module dyaml.fastcharsearch; 8 9 10 import std.algorithm; 11 import std.conv; 12 13 14 package: 15 16 /** 17 * Mixin used for fast searching for a character in string. 18 * 19 * Creates a lookup table to quickly determine if a character 20 * is present in the string. Size of the lookup table is limited; 21 * any characters not represented in the table will be checked 22 * by ordinary equality comparison. 23 * 24 * Params: chars = String to search in. 25 * tableSize = Maximum number of bytes used by the table. 26 * 27 * Generated method: 28 * bool canFind(dchar c) 29 * 30 * Determines if a character is in the string. 31 */ 32 template FastCharSearch(dstring chars, uint tableSize = 256) 33 { 34 private mixin(searchCode!(chars, tableSize)()); 35 } 36 37 /// Generate the search table and the canFind method. 38 string searchCode(dstring chars, uint tableSize)() @safe pure //nothrow 39 { 40 import std.string; 41 42 const tableSizeStr = tableSize.to!string; 43 ubyte[tableSize] table; 44 table[] = 0; 45 46 //Characters that don't fit in the table. 47 dchar[] specialChars; 48 49 foreach(c; chars) 50 { 51 if(c < tableSize) { table[c] = 1; } 52 else { specialChars ~= c; } 53 } 54 55 string specialCharsCode() 56 { 57 return specialChars.map!(c => q{cast(uint)c == %s}.format(cast(uint)c)).join(q{ || }); 58 } 59 60 const caseInTable = 61 q{ 62 if(c < %s) 63 { 64 return cast(immutable(bool))table_[c]; 65 } 66 }.format(tableSize); 67 68 string code; 69 if(tableSize) 70 { 71 code ~= 72 q{ 73 static immutable ubyte[%s] table_ = [ 74 %s]; 75 }.format(tableSize, table[].map!(c => c ? q{true} : q{false}).join(q{, })); 76 } 77 code ~= 78 q{ 79 bool canFind(const dchar c) @safe pure nothrow @nogc 80 { 81 %s 82 83 return %s; 84 } 85 }.format(tableSize ? caseInTable : "", 86 specialChars.length ? specialCharsCode() : q{false}); 87 88 return code; 89 }