1 module symbols;
2 
3 class SymbolTable
4 {
5     private size_t[string] table = null;
6 
7     private string[] pool = null;
8 
9     invariant (table.length == pool.length);
10 
11     size_t intern(const(char)[] value) nothrow pure @safe
12     {
13         if (auto id = value in table)
14             return *id;
15 
16         size_t id = pool.length;
17 
18         pool ~= value.idup;
19         table[pool[id]] = id;
20         return id;
21     }
22 
23     @("intern equal strings")
24     unittest
25     {
26         with (new SymbolTable)
27         {
28             assert(intern("foo") == intern("foo"));
29         }
30     }
31 
32     @("intern different strings")
33     unittest
34     {
35         with (new SymbolTable)
36         {
37             assert(intern("foo") != intern("bar"));
38         }
39     }
40 
41     string symbol(size_t id) @nogc nothrow pure @safe
42     in (id < pool.length)
43     {
44         return pool[id];
45     }
46 
47     @("get interned symbol")
48     unittest
49     {
50         with (new SymbolTable)
51         {
52             assert(symbol(intern("foo")) == "foo");
53         }
54     }
55 }