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