Passed
Push — 1.x ( 5dbfd8...9a028c )
by Ulises Jeremias
02:21
created

Sequenceable::setSize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php namespace Mbh\Collection\Traits;
2
3
use Mbh\Collection\Interfaces\Collection as CollectionInterface;
4
use Mbh\Collection\Interfaces\Sequenceable as SequenceableInterface;
5
use Mbh\Collection\FixedArray;
6
use Mbh\Collection\CallbackHeap;
7
use Mbh\Iterator\SliceIterator;
8
use Mbh\Iterator\ConcatIterator;
9
use SplFixedArray;
10
use SplHeap;
11
use SplStack;
12
use LimitIterator;
13
use Iterator;
14
use ArrayAccess;
15
use Countable;
16
use CallbackFilterIterator;
17
use JsonSerializable;
18
use RuntimeException;
19
use Traversable;
20
use ReflectionClass;
21
use UnderflowException;
22
use OutOfRangeException;
23
24
/**
25
 * MBHFramework
26
 *
27
 * @link      https://github.com/MBHFramework/mbh-framework
28
 * @copyright Copyright (c) 2017 Ulises Jeremias Cornejo Fandos
29
 * @license   https://github.com/MBHFramework/mbh-framework/blob/master/LICENSE (MIT License)
30
 */
31
32
trait Sequenceable
33
{
34
    use Sequenceable\Countable;
35
    use Sequenceable\ArrayAccess;
36
    use Sequenceable\Iterator;
37
38
    protected $sfa = null;
39
40
    /**
41
     * Create an fixed array
42
     *
43
     * @param Traversable $array data
44
     */
45
    protected function __construct(Traversable $array)
46
    {
47
        $this->sfa = $array;
48
        $this->checkCapacity();
49
    }
50
51
    /**
52
     * @inheritDoc
53
     */
54
    public static function fromArray(array $array)
55
    {
56
        return new static(SplFixedArray::fromArray($array));
57
    }
58
59
    /**
60
     * @inheritDoc
61
     */
62
    public static function fromItems(Traversable $array)
63
    {
64
        if (!$array instanceof Countable) {
65
            return static::fromArray(iterator_to_array($array));
66
        }
67
68
        $sfa = new SplFixedArray(count($array));
69
70
        foreach ($array as $i => $elem) {
71
            $sfa[$i] = $elem;
72
        }
73
74
        return new static($sfa);
75
    }
76
77
    /**
78
     * @inheritDoc
79
     */
80
    public function contains(...$values): bool
81
    {
82
        foreach ($values as $value) {
83
            if ($this->search($value) !== null) {
84
                return false;
85
            }
86
        }
87
88
        return true;
89
    }
90
91
    /**
92
     * @inheritDoc
93
     */
94
    public function copy()
95
    {
96
        return static::fromArray($this->toArray());
97
    }
98
99
    /**
100
     * @inheritDoc
101
     */
102
    public function first()
103
    {
104
        if ($this->isEmpty()) {
105
            throw new UnderflowException();
106
        }
107
108
        return $this[0];
109
    }
110
111
    /**
112
     * @inheritDoc
113
     */
114
    public function get(int $index)
115
    {
116
        if (!$this->validIndex($index)) {
117
            throw new OutOfRangeException();
118
        }
119
120
        return $this[$index];
121
    }
122
123
    /**
124
     * @inheritDoc
125
     */
126
    public function insert(int $index, ...$values)
127
    {
128
        if (!$this->validIndex($index) && $index !== $this->count()) {
129
            throw new OutOfRangeException();
130
        }
131
132
        $slice = $this->slice($index, $this->count());
0 ignored issues
show
Bug introduced by
It seems like slice() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

132
        /** @scrutinizer ignore-call */ 
133
        $slice = $this->slice($index, $this->count());
Loading history...
133
        $this->setSize($index);
134
135
        $this->pushAll($values, $slice);
136
    }
137
138
    /**
139
     * @inheritDoc
140
     */
141
    public function last()
142
    {
143
        if ($this->isEmpty()) {
144
            throw new UnderflowException();
145
        }
146
147
        return $this[$this->count() - 1];
148
    }
149
150
    /**
151
     * Converts negative or large rotations into the minimum positive number
152
     * of rotations required to rotate the sequence by a given $r.
153
     */
154
    private function normalizeRotations(int $r)
155
    {
156
        $n = $this->count();
157
158
        if ($n < 2) {
159
            return 0;
160
        }
161
162
        if ($r < 0) {
163
            return $n - (abs($r) % $n);
164
        }
165
166
        return $r % $n;
167
    }
168
169
    /**
170
     * @inheritDoc
171
     */
172
    public function pop()
173
    {
174
        if ($this->isEmpty()) {
175
            throw new UnderflowException();
176
        }
177
178
        $value = $this->last();
179
        $count = $this->count();
180
        unset($this[--$count]);
181
        $this->setSize($count);
182
183
        $this->checkCapacity();
184
185
        return $value;
186
    }
187
188
    /**
189
     * Pushes all values of either an array or traversable object.
190
     */
191
    private function pushAll(...$args)
192
    {
193
        $size = $this->getSize();
194
195
        foreach ($args as &$values) {
196
            $this->setSize($size + count($values));
197
198
            foreach ($values as $value) {
199
                $this[$size++] = $value;
200
            }
201
        }
202
203
        $this->checkCapacity();
204
    }
205
206
    /**
207
     * @inheritDoc
208
     */
209
    public function push(...$values)
210
    {
211
        $this->pushAll($values);
212
    }
213
214
    /**
215
     * @inheritDoc
216
     */
217
    public function remove(int $index)
218
    {
219
        if (!$this->validIndex($index)) {
220
            throw new OutOfRangeException();
221
        }
222
223
        $value = $this[$index];
224
        $this->sfa->offsetUnset($index);
225
226
        $this->checkCapacity();
227
        return $value;
228
    }
229
230
    /**
231
     * @inheritDoc
232
     */
233
    public function set(int $index, $value)
234
    {
235
        if (!$this->validIndex($index)) {
236
            throw new OutOfRangeException();
237
        }
238
239
        $this->sfa->offsetSet($index, $value);
240
    }
241
242
    /**
243
     * @inheritDoc
244
     */
245
    public function shift()
246
    {
247
        if ($this->isEmpty()) {
248
            throw new UnderflowException();
249
        }
250
251
        $value = $this->first();
252
        unset($this[0]);
253
254
        $this->checkCapacity();
255
256
        return $value;
257
    }
258
259
    public function toArray(): array
260
    {
261
        return $this->sfa->toArray();
262
    }
263
264
    /**
265
     * @inheritDoc
266
     */
267
    public function unshift(...$values)
268
    {
269
        $this->insert(0, ...$values);
270
271
        return $this->count();
272
    }
273
274
    protected function validIndex(int $index)
275
    {
276
        return $index >= 0 && $index < $this->getSize();
277
    }
278
279
    public function clear()
280
    {
281
        $this->sfa->clear();
282
        $this->checkCapacity();
283
    }
284
285
    protected function getMainTraversable(): Traversable
286
    {
287
        return $this->sfa;
288
    }
289
290
    protected function setTraversable(Traversable $traversable)
291
    {
292
        $this->sfa = $traversable;
293
    }
294
295
    /**
296
     * Gets the size of the array.
297
     *
298
     * @return int
299
     */
300
    protected function getSize(): int
301
    {
302
        return $this->sfa->getSize();
303
    }
304
305
    /**
306
     * Change the size of an array to the new size of size.
307
     * If size is less than the current array size, any values after the
308
     * new size will be discarded. If size is greater than the current
309
     * array size, the array will be padded with NULL values.
310
     *
311
     * @param int $size The new array size. This should be a value between 0
312
     * and PHP_INT_MAX.
313
     * @return bool Returns TRUE on success or FALSE on failure.
314
     */
315
    protected function setSize(int $size): bool
316
    {
317
        return $this->sfa->setSize($size);
318
    }
319
320
    abstract protected function checkCapacity();
321
322
    abstract public function isEmpty(): bool;
323
324
    abstract public function search($value);
325
}
326