1 
2 module hunt.sql.parser.SymbolTable;
3 
4 import std.concurrency:initOnce;
5 
6 /**
7  */
8 public class SymbolTable {
9     // private  enum UTF8 = "UTF-8";
10     // private static  bool JVM_16;
11     // static this()
12     // {
13     //     global = new SymbolTable(32768);
14     // }
15 
16     static SymbolTable global() {
17         __gshared SymbolTable inst;
18         return initOnce!inst(new SymbolTable(32768));
19     }
20 
21     private  Entry[] entries;
22     private  int      indexMask;
23 
24     public this(int tableSize){
25         this.indexMask = tableSize - 1;
26         this.entries = new Entry[tableSize];
27     }
28 
29     public string addSymbol(string buffer, int offset, int len, long hash) {
30          int bucket = (cast(int) hash) & indexMask;
31 
32         Entry entry = entries[bucket];
33         if (entry !is null) {
34             if (hash == entry.hash) {
35                 return entry.value;
36             }
37 
38             string str = buffer[offset .. offset + len];
39 
40             return str;
41         }
42 
43         string str = buffer[offset .. offset + len];
44         entry = new Entry(hash, len, str);
45         entries[bucket] = entry;
46         return str;
47     }
48 
49     public string addSymbol(byte[] buffer, int offset, int len, long hash) {
50          int bucket = (cast(int) hash) & indexMask;
51 
52         Entry entry = entries[bucket];
53         if (entry !is null) {
54             if (hash == entry.hash) {
55                 return entry.value;
56             }
57 
58             string str = subString(buffer, offset, len);
59 
60             return str;
61         }
62 
63         string str = subString(buffer, offset, len);
64         entry = new Entry(hash, len, str);
65         entries[bucket] = entry;
66         return str;
67     }
68 
69     public string addSymbol(string symbol, long hash) {
70          int bucket = (cast(int) hash) & indexMask;
71 
72         Entry entry = entries[bucket];
73         if (entry !is null) {
74             if (hash == entry.hash) {
75                 return entry.value;
76             }
77 
78             return symbol;
79         }
80 
81         entry = new Entry(hash, cast(int)symbol.length, symbol);
82         entries[bucket] = entry;
83         return symbol;
84     }
85 
86     public string findSymbol(long hash) {
87          int bucket = (cast(int) hash) & indexMask;
88         Entry entry = entries[bucket];
89         if (entry !is null && entry.hash == hash) {
90             return entry.value;
91         }
92         return null;
93     }
94 
95     private static string subString(string src, int offset, int len) {
96         //char[] chars = new char[len];
97         // src.getChars(offset, offset + len, chars, 0);
98         return src[offset..offset+len];
99     }
100 
101     private static string subString(byte[] bytes, int from, int len) {
102         // byte[] strBytes = new byte[len];
103         byte[] strBytes = bytes[from..from+len].dup;
104         return cast(string)strBytes;
105         // System.arraycopy(bytes, from, strBytes, 0, len);
106         // return new string(strBytes, UTF8);
107     }
108 
109     private static class Entry {
110         public  long hash;
111         public  int len;
112         public  string value;
113 
114         public this(long hash, int len, string value) {
115             this.hash = hash;
116             this.len = len;
117             this.value = value;
118         }
119     }
120 }