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