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 }