Passed
Push — 1.x ( 650a57...b30111 )
by Ulises Jeremias
02:24
created

Arrayed::copy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php namespace Mbh\Collection\Traits\Sequenceable;
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 Mbh\Collection\Traits\Builder;
10
use SplFixedArray;
11
use SplHeap;
12
use SplStack;
13
use LimitIterator;
14
use Iterator;
15
use ArrayAccess;
16
use Countable;
17
use CallbackFilterIterator;
18
use JsonSerializable;
19
use RuntimeException;
20
use Traversable;
21
use ReflectionClass;
22
use UnderflowException;
23
use OutOfRangeException;
24
25
/**
26
 * MBHFramework
27
 *
28
 * @link      https://github.com/MBHFramework/mbh-framework
29
 * @copyright Copyright (c) 2017 Ulises Jeremias Cornejo Fandos
30
 * @license   https://github.com/MBHFramework/mbh-framework/blob/master/LICENSE (MIT License)
31
 */
32
33
trait Arrayed
34
{
35
    use Arrayed\Countable;
36
    use Arrayed\ArrayAccess;
37
    use Arrayed\Iterator;
38
    use Builder;
39
40
    protected $sfa = null;
41
42
    /**
43
     * Create an fixed array
44
     *
45
     * @param Traversable $array data
46
     */
47
    protected function __construct(Traversable $array)
48
    {
49
        $this->sfa = $array;
50
        $this->checkCapacity();
51
    }
52
53
    /**
54
     * @inheritDoc
55
     */
56
    public function contains(...$values): bool
57
    {
58
        foreach ($values as $value) {
59
            if ($this->search($value) !== null) {
60
                return false;
61
            }
62
        }
63
64
        return true;
65
    }
66
67
    /**
68
     * @inheritDoc
69
     */
70
    public function copy()
71
    {
72
        return static::fromArray($this->toArray());
73
    }
74
75
    /**
76
     * @inheritDoc
77
     */
78
    public function first()
79
    {
80
        $this->emptyGuard(__METHOD__);
81
        return $this[0];
82
    }
83
84
    /**
85
     * @inheritDoc
86
     */
87
    public function get(int $index)
88
    {
89
        if (!$this->validIndex($index)) {
90
            throw new OutOfRangeException();
91
        }
92
93
        return $this[$index];
94
    }
95
96
    /**
97
     * @inheritDoc
98
     */
99
    public function insert(int $index, ...$values)
100
    {
101
        if (!$this->validIndex($index) && $index !== $this->count()) {
102
            throw new OutOfRangeException();
103
        }
104
105
        $splice = $this->splice($index, 0, $values);
106
        $this->clear();
107
108
        $this->pushAll($splice);
109
    }
110
111
    /**
112
     * @inheritDoc
113
     */
114
    public function last()
115
    {
116
        $this->emptyGuard(__METHOD__);
117
        return $this[$this->count() - 1];
118
    }
119
120
    /**
121
     * Converts negative or large rotations into the minimum positive number
122
     * of rotations required to rotate the sequence by a given $r.
123
     */
124
    private function normalizeRotations(int $r)
125
    {
126
        $n = $this->count();
127
128
        if ($n < 2) {
129
            return 0;
130
        }
131
132
        if ($r < 0) {
133
            return $n - (abs($r) % $n);
134
        }
135
136
        return $r % $n;
137
    }
138
139
    /**
140
     * @inheritDoc
141
     */
142
    public function pop()
143
    {
144
        $this->emptyGuard(__METHOD__);
145
        $value = $this->last();
146
        $count = $this->count();
147
        unset($this[--$count]);
148
        $this->setSize($count);
149
150
        $this->checkCapacity();
151
152
        return $value;
153
    }
154
155
    /**
156
     * Pushes all values of either an array or traversable object.
157
     */
158
    private function pushAll(...$args)
159
    {
160
        $size = $this->getSize();
161
162
        foreach ($args as &$values) {
163
            $this->setSize($size + count($values));
164
165
            foreach ($values as $value) {
166
                $this[$size++] = $value;
167
            }
168
        }
169
170
        $this->checkCapacity();
171
    }
172
173
    /**
174
     * @inheritDoc
175
     */
176
    public function push(...$values)
177
    {
178
        $this->pushAll($values);
179
    }
180
181
    /**
182
     * @inheritDoc
183
     */
184
    public function remove(int $index)
185
    {
186
        if (!$this->validIndex($index)) {
187
            throw new OutOfRangeException();
188
        }
189
190
        $value = $this[$index];
191
        $splice = $this->splice($index + 1, 1, null);
192
        $this->clear();
193
194
        $this->pushAll($splice);
195
        return $value;
196
    }
197
198
    /**
199
     * @inheritDoc
200
     */
201
    public function set(int $index, $value)
202
    {
203
        if (!$this->validIndex($index)) {
204
            throw new OutOfRangeException();
205
        }
206
207
        $this->sfa->offsetSet($index, $value);
208
    }
209
210
    /**
211
     * @inheritDoc
212
     */
213
    public function shift()
214
    {
215
        $this->emptyGuard(__METHOD__);
216
        $value = $this->first();
217
        unset($this[0]);
218
219
        $this->checkCapacity();
220
221
        return $value;
222
    }
223
224
    /**
225
     * @inheritDoc
226
     */
227
    public function toArray(): array
228
    {
229
        return $this->sfa->toArray();
230
    }
231
232
    /**
233
     * @inheritDoc
234
     */
235
    public function unshift(...$values)
236
    {
237
        $this->insert(0, ...$values);
238
239
        return $this->count();
240
    }
241
242
    /**
243
     * @inheritDoc
244
     */
245
    public function unserialize($values)
246
    {
247
        $values = unserialize($values);
248
        $this->setValues(SplFixedArray::fromArray($values));
249
    }
250
251
    /**
252
     * @inheritDoc
253
     */
254
    protected function validIndex(int $index)
255
    {
256
        return $index >= 0 && $index < $this->getSize();
257
    }
258
259
    /**
260
     * @inheritDoc
261
     */
262
    public function clear()
263
    {
264
        $this->sfa->setSize(0);
265
        $this->checkCapacity();
266
    }
267
268
    protected function getValues(): Traversable
269
    {
270
        return $this->sfa;
271
    }
272
273
    protected function setValues(Traversable $traversable)
274
    {
275
        $this->clear();
276
        $this->pushAll($traversable);
277
    }
278
279
    /**
280
     * Gets the size of the array.
281
     *
282
     * @return int
283
     */
284
    protected function getSize(): int
285
    {
286
        return $this->sfa->getSize();
287
    }
288
289
    /**
290
     * Change the size of an array to the new size of size.
291
     * If size is less than the current array size, any values after the
292
     * new size will be discarded. If size is greater than the current
293
     * array size, the array will be padded with NULL values.
294
     *
295
     * @param int $size The new array size. This should be a value between 0
296
     * and PHP_INT_MAX.
297
     * @return bool Returns TRUE on success or FALSE on failure.
298
     */
299
    protected function setSize(int $size): bool
300
    {
301
        return $this->sfa->setSize($size);
302
    }
303
304
    public function __clone()
305
    {
306
        return $this->copy();
307
    }
308
309
    abstract protected function checkCapacity();
310
311
    abstract protected function emptyGuard($method);
312
313
    abstract public function isEmpty(): bool;
314
315
    abstract public function search($value);
316
317
    abstract public function splice(int $begin = 0, int $length = null, $replacement = []);
318
}
319