1 /* 2 * Copyright (c) 2012-2019 The ANTLR Project. All rights reserved. 3 * Use of this file is governed by the BSD 3-clause license that 4 * can be found in the LICENSE.txt file in the project root. 5 */ 6 7 module antlr.v4.runtime.misc.DoubleKeyMap; 8 9 import std.typecons; 10 11 /** 12 * Sometimes we need to map a key to a value but key is two pieces of data. 13 * This nested hash table saves creating a single key each time we access 14 * map; avoids mem creation. 15 */ 16 class DoubleKeyMap(K1, K2, V) 17 { 18 19 public V[K1][K2] data; 20 21 public V put(K1 k1, K2 k2, V v) 22 { 23 data[k1][k2] = v; 24 return v; 25 } 26 27 public Nullable!V get(K1 k1, K2 k2) 28 { 29 Nullable!V v; 30 if (k1 !in data || k2 !in data[k1]) { 31 return v; // null 32 } 33 v = data[k1][k2]; 34 return v; 35 } 36 37 public V[K2] get(K1 k1) 38 { 39 if (k1 !in data) { 40 V[K2] v; 41 return v; 42 } 43 return data[k1]; 44 } 45 46 /** 47 * Get all values associated with a primary key. 48 */ 49 public V[] values(K1 k1) 50 { 51 V[] va; 52 if (k1 !in data) { 53 return va; // [] 54 } 55 V[K2] data2 = data[k1]; 56 return data2.values; 57 } 58 59 /** 60 * get all primary keys 61 */ 62 public K1[] keySet() 63 { 64 return data.keys; 65 } 66 67 /** 68 * Get all secondary keys associated with a primary key. 69 */ 70 public K2[] keySet(K1 k1) 71 { 72 if (k1 !in data) { 73 K2[] v; 74 return v; 75 } 76 V[K2] data2 = data[k1]; 77 return data2.keys; 78 } 79 80 } 81 82 version(unittest) { 83 import dshould : be, equal, not, should; 84 import unit_threaded; 85 86 class Test { 87 88 @Tags("DoubleKeyMap") 89 @("construction DoubleKeyMap") 90 unittest { 91 auto t1 = new DoubleKeyMap!(int, int, int); 92 t1.put(7,1,12); 93 t1.put(7,1,13); 94 auto x = t1.get(7,1); 95 x.get.should.equal(13); 96 x = t1.get(7,2); 97 x.isNull.should.equal(true); 98 } 99 100 @Tags("DoubleKeyMap") 101 @("comparing DoubleKeyMaps") 102 unittest { 103 auto t1 = new DoubleKeyMap!(int, int, int); 104 t1.put(7,1,13); 105 auto y = t1.get(7); 106 int[int] c; 107 c[1] = 13; 108 c.should.equal(y); 109 y = t1.get(6); 110 y.length.should.equal(0); 111 t1.put(7,4,71); 112 c[4] = 71; 113 y = t1.get(7); 114 c.should.equal(y); 115 116 auto v1 = t1.values(7); 117 v1.should.equal([71, 13]); 118 v1 = t1.values(0); 119 v1.should.equal([]); 120 121 auto kx = t1.keySet; 122 auto kk = [7]; 123 kk.should.equal(kx); 124 125 auto tx = t1.keySet(8); 126 tx.should.equal([]); 127 tx = t1.keySet(7); 128 tx.should.equal([4, 1]); 129 } 130 131 } 132 133 }