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.BitSet;
8 
9 import std.bitmanip;
10 import std.conv;
11 import std.algorithm;
12 
13 /**
14  * This struct implements a vector of bits that grows as needed. Each component
15  * of the bit set has a bool value. The bits of a BitSet are indexed by nonnegative integers.
16  * Individual indexed bits can be examined, set, or cleared. One BitSet may be used to modify
17  * the contents of another BitSet through logical AND, logical inclusive OR,
18  * and logical exclusive OR operations.
19  *
20  * By default, all bits in the set initially have the value false.
21  */
22 struct BitSet
23 {
24 
25     private BitArray bitSet;
26 
27     public this(BitArray bitArray)
28     {
29         this.bitSet = bitArray;
30     }
31 
32     public this(size_t initialSize)
33     {
34         this.bitSet.length = initialSize;
35     }
36 
37     public size_t length()
38     {
39         return bitSet.length;
40     }
41 
42     public auto cardinality()
43     {
44         int res;
45         bitSet.each!(v => res += to!int(v));
46         return res;
47     }
48 
49     public int nextSetBit(int fromIndex)
50     {
51         foreach (i, el; bitSet) {
52             if (i > fromIndex && el == true)
53                 return to!int(i);
54         }
55         return -1;
56     }
57 
58     public void set(int bitIndex, bool value)
59     {
60         if (bitSet.length <= bitIndex)
61             bitSet.length = bitIndex + 16; // dynamic array need more space
62         bitSet[bitIndex] = value;
63     }
64 
65     /**
66      * @uml
67      * @nothrow
68      */
69     public bool get(int bitIndex) nothrow
70     in
71     {
72         assert(bitSet.length > bitIndex);
73     }
74     do
75     {
76         return bitSet[bitIndex];
77     }
78 
79     public bool isEmpty()
80     {
81         return cardinality == 0;
82     }
83 
84     public string toString()
85     {
86         import std.format : format;
87         return format("%b", bitSet);
88     }
89 
90     /**
91      * @uml
92      * @trusted
93      */
94     public size_t toHash() @trusted
95     {
96         size_t hash;
97         foreach (el; bitSet)
98             hash = (hash * 9) + el;
99         return hash;
100     }
101 
102     /**
103      * @uml
104      * @const
105      * @pure
106      * @nothrow
107      */
108     public bool opEquals(ref const BitSet bitSet) const pure nothrow
109     {
110         return this.bitSet == bitSet.bitSet;
111     }
112 
113     public void clear()
114     {
115         bitSet.length(0);
116     }
117 
118     public BitSet or(BitSet bits)
119     {
120         BitSet result;
121         auto maxLenght = max(this.bitSet.length, bits.bitSet.length);
122         if (this.bitSet.length < maxLenght)
123             this.bitSet.length = maxLenght;
124         else
125             if (bits.values.length < maxLenght)
126                 bits.values.length = maxLenght;
127         result.bitSet = this.bitSet | bits.bitSet;
128         return result;
129     }
130 
131     public string toIndexString()
132     {
133         import std.conv;
134         import std.array : join;
135         string[] res;
136         int index;
137         foreach(i, el; bitSet)
138         {
139             if(el)
140                 res ~= to!string(i);
141         }
142         return "{" ~ join(res, ",") ~ "}";
143     }
144 
145     public BitArray values()
146     {
147         return bitSet;
148     }
149 
150     public void dup(BitSet old)
151     {
152         this.bitSet = old.bitSet.dup;
153     }
154 
155 }