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 “first in, first out” or “FIFO” collection that only allows access to the |
20
|
|
|
* value at the front of the queue 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 Queue implements ArrayAccess, CollectionInterface, IteratorAggregate |
|
|
|
|
27
|
|
|
{ |
28
|
|
|
use Traits\Collection; |
29
|
|
|
|
30
|
|
|
const MIN_CAPACITY = 8; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var Deque internal deque to store values. |
34
|
|
|
*/ |
35
|
|
|
protected $deque; |
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->deque = Deque::fromArray([]); |
45
|
|
|
|
46
|
|
|
$this->pushAll($values); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Ensures that enough memory is allocated for a specified capacity. This |
51
|
|
|
* potentially reduces the number of reallocations as the size increases. |
52
|
|
|
* |
53
|
|
|
* @param int $capacity The number of values for which capacity should be |
54
|
|
|
* allocated. Capacity will stay the same if this value |
55
|
|
|
* is less than or equal to the current capacity. |
56
|
|
|
*/ |
57
|
|
|
public function allocate(int $capacity) |
58
|
|
|
{ |
59
|
|
|
$this->deque->allocate($capacity); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Returns the current capacity of the queue. |
64
|
|
|
* |
65
|
|
|
* @return int |
66
|
|
|
*/ |
67
|
|
|
public function capacity(): int |
68
|
|
|
{ |
69
|
|
|
return $this->deque->capacity(); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @inheritDoc |
74
|
|
|
*/ |
75
|
|
|
public function clear() |
76
|
|
|
{ |
77
|
|
|
$this->deque->clear(); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* @inheritDoc |
82
|
|
|
*/ |
83
|
|
|
public function copy() |
84
|
|
|
{ |
85
|
|
|
return new self($this->deque); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @inheritDoc |
90
|
|
|
*/ |
91
|
|
|
public function count(): int |
92
|
|
|
{ |
93
|
|
|
return count($this->deque); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Returns the value at the front of the queue without removing it. |
98
|
|
|
* |
99
|
|
|
* @return |
100
|
|
|
*/ |
101
|
|
|
public function peek() |
102
|
|
|
{ |
103
|
|
|
return $this->deque->first(); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Returns and removes the value at the front of the Queue. |
108
|
|
|
* |
109
|
|
|
* @return mixed |
110
|
|
|
*/ |
111
|
|
|
public function pop() |
112
|
|
|
{ |
113
|
|
|
return $this->deque->shift(); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Pushes zero or more values into the front of the queue. |
118
|
|
|
* |
119
|
|
|
* @param mixed ...$values |
120
|
|
|
*/ |
121
|
|
|
public function push(...$values) |
122
|
|
|
{ |
123
|
|
|
$this->deque->push(...$values); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Creates associations for all keys and corresponding values of either an |
128
|
|
|
* array or iterable object. |
129
|
|
|
* |
130
|
|
|
* @param Traversable|array $values |
131
|
|
|
*/ |
132
|
|
|
protected function pushAll($values) |
133
|
|
|
{ |
134
|
|
|
foreach ($values as &$value) { |
135
|
|
|
$this[] = $value; |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @inheritDoc |
141
|
|
|
*/ |
142
|
|
|
public function toArray(): array |
143
|
|
|
{ |
144
|
|
|
return $this->deque->toArray(); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* @inheritDoc |
149
|
|
|
*/ |
150
|
|
|
public function unserialize($values) |
151
|
|
|
{ |
152
|
|
|
$values = unserialize($values); |
153
|
|
|
$this->deque = Deque::fromArray($values); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* |
158
|
|
|
*/ |
159
|
|
|
public function getIterator() |
160
|
|
|
{ |
161
|
|
|
while (!$this->isEmpty()) { |
162
|
|
|
yield $this->pop(); |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @inheritdoc |
168
|
|
|
* |
169
|
|
|
* @throws OutOfBoundsException |
170
|
|
|
*/ |
171
|
|
|
public function offsetSet($offset, $value) |
172
|
|
|
{ |
173
|
|
|
if ($offset === null) { |
174
|
|
|
$this->push($value); |
175
|
|
|
} else { |
176
|
|
|
throw new OutOfBoundsException(); |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* @inheritdoc |
182
|
|
|
* |
183
|
|
|
* @throws Error |
184
|
|
|
*/ |
185
|
|
|
public function offsetGet($offset) |
186
|
|
|
{ |
187
|
|
|
throw new Error(); |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* @inheritdoc |
192
|
|
|
* |
193
|
|
|
* @throws Error |
194
|
|
|
*/ |
195
|
|
|
public function offsetUnset($offset) |
196
|
|
|
{ |
197
|
|
|
throw new Error(); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* @inheritdoc |
202
|
|
|
* |
203
|
|
|
* @throws Error |
204
|
|
|
*/ |
205
|
|
|
public function offsetExists($offset) |
206
|
|
|
{ |
207
|
|
|
throw new Error(); |
208
|
|
|
} |
209
|
|
|
} |
210
|
|
|
|
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.