Skip to content

Commit 6227f02

Browse files
committed
EnumMap: added seek(), getKeys() and getValues() + null aware contains()
1 parent 8b1e418 commit 6227f02

File tree

3 files changed

+209
-49
lines changed

3 files changed

+209
-49
lines changed

bench/EnumMapBench.php

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,41 @@ public function init()
4848

4949
$this->emptyMap = new EnumMap(Enum66::class);
5050
$this->fullMap = new EnumMap(Enum66::class);
51-
foreach ($this->enumerators as $enumerator) {
52-
$this->fullMap->offsetSet($enumerator);
51+
foreach ($this->enumerators as $i => $enumerator) {
52+
$this->fullMap->offsetSet($enumerator, $i);
5353
}
5454
}
5555

56+
public function benchGetKeysEmpty()
57+
{
58+
$this->emptyMap->getKeys();
59+
}
60+
61+
public function benchGetKeysFull()
62+
{
63+
$this->fullMap->getKeys();
64+
}
65+
66+
public function benchGetValuesEmpty()
67+
{
68+
$this->emptyMap->getValues();
69+
}
70+
71+
public function benchGetValuesFull()
72+
{
73+
$this->fullMap->getValues();
74+
}
75+
76+
public function benchSearchTypeJuggling()
77+
{
78+
$this->fullMap->search('31');
79+
}
80+
81+
public function benchSearchStrict()
82+
{
83+
$this->fullMap->search(31, true);
84+
}
85+
5686
public function benchOffsetSetEnumerator()
5787
{
5888
foreach ($this->enumerators as $enumerator) {
@@ -81,31 +111,31 @@ public function benchOffsetUnsetValue()
81111
}
82112
}
83113

84-
public function benchOffsetExistsEnumeratorTrue()
114+
public function benchOffsetExistsEnumerator()
85115
{
86116
foreach ($this->enumerators as $enumerator) {
87117
$this->fullMap->offsetExists($enumerator);
88118
}
89119
}
90120

91-
public function benchOffsetExistsEnumeratorFalse()
121+
public function benchOffsetExistsValue()
92122
{
93-
foreach ($this->enumerators as $enumerator) {
94-
$this->fullMap->offsetExists($enumerator);
123+
foreach ($this->values as $value) {
124+
$this->fullMap->offsetExists($value);
95125
}
96126
}
97127

98-
public function benchOffsetExistsValueTrue()
128+
public function benchContainsEnumerator()
99129
{
100-
foreach ($this->values as $value) {
101-
$this->fullMap->offsetExists($value);
130+
foreach ($this->enumerators as $enumerator) {
131+
$this->fullMap->contains($enumerator);
102132
}
103133
}
104134

105-
public function benchOffsetExistsValueFalse()
135+
public function benchContainsValue()
106136
{
107137
foreach ($this->values as $value) {
108-
$this->fullMap->offsetExists($value);
138+
$this->fullMap->contains($value);
109139
}
110140
}
111141

src/EnumMap.php

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
use ArrayAccess;
66
use Countable;
77
use InvalidArgumentException;
8-
use Iterator;
8+
use OutOfBoundsException;
9+
use SeekableIterator;
910
use UnexpectedValueException;
1011

1112
/**
@@ -15,7 +16,7 @@
1516
* @copyright Copyright (c) 2017 Marc Bennewitz
1617
* @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
1718
*/
18-
class EnumMap implements ArrayAccess, Countable, Iterator
19+
class EnumMap implements ArrayAccess, Countable, SeekableIterator
1920
{
2021
/**
2122
* The classname of the enumeration type
@@ -67,43 +68,63 @@ public function getEnumeration()
6768
}
6869

6970
/**
70-
* Attach a new enumerator or overwrite an existing one
71-
* @param Enum|null|boolean|int|float|string $enumerator
72-
* @param mixed $data
73-
* @return void
74-
* @throws InvalidArgumentException On an invalid given enumerator
71+
* Get a list of map keys
72+
* @return Enum[]
7573
*/
76-
public function attach($enumerator, $data = null)
74+
public function getKeys()
7775
{
78-
return $this->offsetSet($enumerator, $data);
76+
return \array_map([$this->enumeration, 'byOrdinal'], $this->ordinals);
7977
}
8078

8179
/**
82-
* Test if the given enumerator exists
83-
* @param Enum|null|boolean|int|float|string $enumerator
84-
* @return boolean
80+
* Get a list of map values
81+
* @return mixed[]
8582
*/
86-
public function contains($enumerator)
83+
public function getValues()
8784
{
88-
return $this->offsetExists($enumerator);
85+
return \array_values($this->map);
8986
}
9087

9188
/**
92-
* Detach an enumerator
93-
* @param Enum|null|boolean|int|float|string $enumerator
94-
* @return void
95-
* @throws InvalidArgumentException On an invalid given enumerator
89+
* Search for the given value
90+
* @param mixed $value
91+
* @param bool $strict Use strict type comparison
92+
* @return Enum|null The found key or NULL
9693
*/
97-
public function detach($enumerator)
94+
public function search($value, $strict = false)
9895
{
99-
$this->offsetUnset($enumerator);
96+
$ord = \array_search($value, $this->map, $strict);
97+
if ($ord !== false) {
98+
$enumeration = $this->enumeration;
99+
return $enumeration::byOrdinal($ord);
100+
}
101+
102+
return null;
100103
}
101104

102105
/**
103106
* Test if the given enumerator exists
104107
* @param Enum|null|boolean|int|float|string $enumerator
105108
* @return boolean
106-
* @see contains()
109+
* @see offsetExists
110+
*/
111+
public function contains($enumerator)
112+
{
113+
try {
114+
$enumeration = $this->enumeration;
115+
$ord = $enumeration::get($enumerator)->getOrdinal();
116+
return array_key_exists($ord, $this->map);
117+
} catch (InvalidArgumentException $e) {
118+
// An invalid enumerator can't be contained in this map
119+
return false;
120+
}
121+
}
122+
123+
/**
124+
* Test if the given enumerator key exists and is not NULL
125+
* @param Enum|null|boolean|int|float|string $enumerator
126+
* @return boolean
127+
* @see contains
107128
*/
108129
public function offsetExists($enumerator)
109130
{
@@ -112,7 +133,7 @@ public function offsetExists($enumerator)
112133
$ord = $enumeration::get($enumerator)->getOrdinal();
113134
return isset($this->map[$ord]);
114135
} catch (InvalidArgumentException $e) {
115-
// An invalid enumerator can't be contained in this map
136+
// An invalid enumerator can't be an offset of this map
116137
return false;
117138
}
118139
}
@@ -145,15 +166,15 @@ public function offsetGet($enumerator)
145166
* @throws InvalidArgumentException On an invalid given enumerator
146167
* @see attach()
147168
*/
148-
public function offsetSet($enumerator, $data = null)
169+
public function offsetSet($enumerator, $value = null)
149170
{
150171
$enumeration = $this->enumeration;
151172
$ord = $enumeration::get($enumerator)->getOrdinal();
152173

153174
if (!isset($this->map[$ord])) {
154175
$this->ordinals[] = $ord;
155176
}
156-
$this->map[$ord] = $data;
177+
$this->map[$ord] = $value;
157178
}
158179

159180
/**
@@ -170,9 +191,24 @@ public function offsetUnset($enumerator)
170191

171192
if (($idx = \array_search($ord, $this->ordinals, true)) !== false) {
172193
unset($this->map[$ord], $this->ordinals[$idx]);
194+
$this->ordinals = \array_values($this->ordinals);
173195
}
174196
}
175197

198+
/**
199+
* Seeks to the given iterator position.
200+
* @param int $pos
201+
*/
202+
public function seek($pos)
203+
{
204+
$pos = (int)$pos;
205+
if (!isset($this->ordinals[$pos])) {
206+
throw new OutOfBoundsException("Position {$pos} not found");
207+
}
208+
209+
$this->pos = $pos;
210+
}
211+
176212
/**
177213
* Get the current value
178214
* @return mixed

0 commit comments

Comments
 (0)