1
|
|
|
<?php namespace Mbh\Collection; |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* MBHFramework |
5
|
|
|
* |
6
|
|
|
* @link https://github.com/MBHFramework/mbh-framework |
7
|
|
|
* @copyright Copyright (c) 2017 Ulises Jeremias Cornejo Fandos |
8
|
|
|
* @license https://github.com/MBHFramework/mbh-framework/blob/master/LICENSE (MIT License) |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
use Mbh\Collection\Interfaces\Collection as CollectionInterface; |
12
|
|
|
use Traversable; |
13
|
|
|
use ArrayAccess; |
14
|
|
|
use IteratorAggregate; |
15
|
|
|
use Error; |
16
|
|
|
use OutOfBoundsException; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* A “last in, first out” or “LIFO” collection that only allows access to the |
20
|
|
|
* value at the top of the structure and iterates in that order, destructively. |
21
|
|
|
* |
22
|
|
|
* @package structures |
23
|
|
|
* @author Ulises Jeremias Cornejo Fandos <[email protected]> |
24
|
|
|
*/ |
25
|
|
|
|
26
|
|
View Code Duplication |
class Stack implements ArrayAccess, CollectionInterface, IteratorAggregate |
|
|
|
|
27
|
|
|
{ |
28
|
|
|
use Traits\Collection; |
29
|
|
|
|
30
|
|
|
const MIN_CAPACITY = 8; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var FixedArray internal sfa to store values of the stack. |
34
|
|
|
*/ |
35
|
|
|
private $sfa; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Creates an instance using the values of an array or Traversable object. |
39
|
|
|
* |
40
|
|
|
* @param array|Traversable $values |
41
|
|
|
*/ |
42
|
|
|
public function __construct($values = []) |
43
|
|
|
{ |
44
|
|
|
$this->sfa = FixedArray::fromArray([]); |
45
|
|
|
|
46
|
|
|
$this->pushAll($values); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Clear all elements in the Stack |
51
|
|
|
*/ |
52
|
|
|
public function clear() |
53
|
|
|
{ |
54
|
|
|
$this->sfa->clear(); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @inheritdoc |
59
|
|
|
*/ |
60
|
|
|
public function copy() |
61
|
|
|
{ |
62
|
|
|
return new self($this->sfa); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Returns the number of elements in the Stack |
67
|
|
|
* |
68
|
|
|
* @return int |
69
|
|
|
*/ |
70
|
|
|
public function count(): int |
71
|
|
|
{ |
72
|
|
|
return count($this->sfa); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Ensures that enough memory is allocated for a specified capacity. This |
77
|
|
|
* potentially reduces the number of reallocations as the size increases. |
78
|
|
|
* |
79
|
|
|
* @param int $capacity The number of values for which capacity should be |
80
|
|
|
* allocated. Capacity will stay the same if this value |
81
|
|
|
* is less than or equal to the current capacity. |
82
|
|
|
*/ |
83
|
|
|
public function allocate(int $capacity) |
84
|
|
|
{ |
85
|
|
|
$this->sfa->allocate($capacity); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Returns the current capacity of the stack. |
90
|
|
|
* |
91
|
|
|
* @return int |
92
|
|
|
*/ |
93
|
|
|
public function capacity(): int |
94
|
|
|
{ |
95
|
|
|
return $this->sfa->capacity(); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Returns the value at the top of the stack without removing it. |
100
|
|
|
* |
101
|
|
|
* @return mixed |
102
|
|
|
* |
103
|
|
|
* @throws UnderflowException if the stack is empty. |
104
|
|
|
*/ |
105
|
|
|
public function peek() |
106
|
|
|
{ |
107
|
|
|
return $this->sfa->last(); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Returns and removes the value at the top of the stack. |
112
|
|
|
* |
113
|
|
|
* @return mixed |
114
|
|
|
* |
115
|
|
|
* @throws UnderflowException if the stack is empty. |
116
|
|
|
*/ |
117
|
|
|
public function pop() |
118
|
|
|
{ |
119
|
|
|
return $this->sfa->pop(); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Pushes zero or more values onto the top of the stack. |
124
|
|
|
* |
125
|
|
|
* @param mixed ...$values |
126
|
|
|
*/ |
127
|
|
|
public function push(...$values) |
128
|
|
|
{ |
129
|
|
|
$this->sfa->push(...$values); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Creates associations for all keys and corresponding values of either an |
134
|
|
|
* array or iterable object. |
135
|
|
|
* |
136
|
|
|
* @param Traversable|array $values |
137
|
|
|
*/ |
138
|
|
|
private function pushAll($values) |
139
|
|
|
{ |
140
|
|
|
foreach ($values as &$value) { |
141
|
|
|
$this[] = $value; |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* @inheritDoc |
147
|
|
|
*/ |
148
|
|
|
public function toArray(): array |
149
|
|
|
{ |
150
|
|
|
return array_reverse($this->sfa->toArray()); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* @inheritDoc |
155
|
|
|
*/ |
156
|
|
|
public function unserialize($values) |
157
|
|
|
{ |
158
|
|
|
$values = unserialize($values); |
159
|
|
|
$this->sfa = FixedArray::fromArray($values); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* |
164
|
|
|
*/ |
165
|
|
|
public function getIterator() |
166
|
|
|
{ |
167
|
|
|
while (!$this->isEmpty()) { |
168
|
|
|
yield $this->pop(); |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* @inheritdoc |
174
|
|
|
* |
175
|
|
|
* @throws OutOfBoundsException |
176
|
|
|
*/ |
177
|
|
|
public function offsetSet($offset, $value) |
178
|
|
|
{ |
179
|
|
|
if ($offset === null) { |
180
|
|
|
$this->push($value); |
181
|
|
|
} else { |
182
|
|
|
throw new OutOfBoundsException(); |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* @inheritdoc |
188
|
|
|
* |
189
|
|
|
* @throws Error |
190
|
|
|
*/ |
191
|
|
|
public function offsetGet($offset) |
192
|
|
|
{ |
193
|
|
|
throw new Error(); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* @inheritdoc |
198
|
|
|
* |
199
|
|
|
* @throws Error |
200
|
|
|
*/ |
201
|
|
|
public function offsetUnset($offset) |
202
|
|
|
{ |
203
|
|
|
throw new Error(); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* @inheritdoc |
208
|
|
|
* |
209
|
|
|
* @throws Error |
210
|
|
|
*/ |
211
|
|
|
public function offsetExists($offset) |
212
|
|
|
{ |
213
|
|
|
throw new Error(); |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.