Set::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Antlr\Antlr4\Runtime\Utils;
6
7
use Antlr\Antlr4\Runtime\Comparison\DefaultEquivalence;
8
use Antlr\Antlr4\Runtime\Comparison\Equatable;
9
use Antlr\Antlr4\Runtime\Comparison\Equivalence;
10
use Antlr\Antlr4\Runtime\Comparison\Hashable;
11
12
final class Set implements Equatable, \IteratorAggregate, \Countable
13
{
14
    /** @var array<int, array<mixed>> */
15
    private $table = [];
16
17
    /** @var int */
18
    private $size = 0;
19
20
    /** @var DefaultEquivalence|Equivalence */
21
    private $equivalence;
22
23 7
    public function __construct(?Equivalence $equivalence = null)
24
    {
25 7
        $this->equivalence = $equivalence ?? new DefaultEquivalence();
26 7
    }
27
28 3
    public function isEmpty() : bool
29
    {
30 3
        return $this->count() === 0;
31
    }
32
33 4
    public function count() : int
34
    {
35 4
        return $this->size;
36
    }
37
38
    public function contains($value) : bool
39
    {
40
        if (!$value instanceof Hashable) {
41
            return false;
42
        }
43
44
        $hash = $this->equivalence->hash($value);
45
46
        if (!isset($this->table[$hash])) {
47
            return false;
48
        }
49
50
        foreach ($this->table[$hash] as $entry) {
51
            if ($this->equivalence->equivalent($value, $entry)) {
52
                return true;
53
            }
54
        }
55
56
        return false;
57
    }
58
59 5
    public function getOrAdd(Hashable $value) : Hashable
60
    {
61 5
        $hash = $this->equivalence->hash($value);
62
63 5
        if (!isset($this->table[$hash])) {
64 5
            $this->table[$hash] = [];
65
        }
66
67 5
        foreach ($this->table[$hash] as $index => $entry) {
68 4
            if ($this->equivalence->equivalent($value, $entry)) {
69 4
                return $entry;
70
            }
71
        }
72
73 5
        $this->table[$hash][] = $value;
74
75 5
        $this->size++;
76
77 5
        return $value;
78
    }
79
80 4
    public function get(Hashable $value) : ?Hashable
81
    {
82 4
        $hash = $this->equivalence->hash($value);
83
84 4
        if (!isset($this->table[$hash])) {
85 4
            return null;
86
        }
87
88 2
        foreach ($this->table[$hash] as $index => $entry) {
89 2
            if ($this->equivalence->equivalent($value, $entry)) {
90 2
                return $entry;
91
            }
92
        }
93
94
        return null;
95
    }
96
97
    /**
98
     * @param iterable<Hashable> $values
99
     */
100
    public function addAll(iterable $values) : void
101
    {
102
        foreach ($values as $value) {
103
            $this->add($value);
104
        }
105
    }
106
107 5
    public function add(Hashable $value) : bool
108
    {
109 5
        $hash = $this->equivalence->hash($value);
110
111 5
        if (!isset($this->table[$hash])) {
112 5
            $this->table[$hash] = [];
113
        }
114
115 5
        foreach ($this->table[$hash] as $index => $entry) {
116 1
            if ($this->equivalence->equivalent($value, $entry)) {
117 1
                return false;
118
            }
119
        }
120
121 5
        $this->table[$hash][] = $value;
122
123 5
        $this->size++;
124
125 5
        return true;
126
    }
127
128
    public function remove(Hashable $value) : void
129
    {
130
        $hash = $this->equivalence->hash($value);
131
132
        if (!isset($this->table[$hash])) {
133
            return;
134
        }
135
136
        foreach ($this->table[$hash] as $index => $entry) {
137
            if ($this->equivalence->equivalent($value, $entry)) {
138
                continue;
139
            }
140
141
            unset($this->table[$hash][$index]);
142
143
            if (\count($this->table[$hash]) === 0) {
144
                unset($this->table[$hash]);
145
            }
146
147
            $this->size--;
148
149
            return;
150
        }
151
    }
152
153
    public function equals(object $other) : bool
154
    {
155
        if ($this === $other) {
156
            return true;
157
        }
158
159
        if (!$other instanceof self
160
            || $this->size !== $other->size
161
            || !$this->equivalence->equals($other)) {
162
            return false;
163
        }
164
165
        foreach ($this->table as $hash => $bucket) {
166
            if (!isset($other->table[$hash]) || \count($bucket) !== \count($other->table[$hash])) {
167
                return false;
168
            }
169
170
            $otherBucket = $other->table[$hash];
171
172
            foreach ($bucket as $index => $value) {
173
                if (!$value->equals($otherBucket[$index])) {
174
                    return false;
175
                }
176
            }
177
        }
178
179
        return true;
180
    }
181
182
    /**
183
     * @return array<mixed>
184
     */
185
    public function getValues() : array
186
    {
187
        $values = [];
188
        foreach ($this->table as $bucket) {
189
            foreach ($bucket as $value) {
190
                $values[] = $value;
191
            }
192
        }
193
194
        return $values;
195
    }
196
197
    public function getIterator() : \Iterator
198
    {
199
        foreach ($this->table as $bucket) {
200
            foreach ($bucket as $value) {
201
                yield $value;
202
            }
203
        }
204
    }
205
}
206