Passed
Push — 1.x ( f1b002...306f92 )
by Ulises Jeremias
02:31
created

Arrayed::__clone()   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
    }
51
52
    /**
53
     * @inheritDoc
54
     */
55
    public function first()
56
    {
57
        $this->emptyGuard(__METHOD__);
58
        return $this[0];
59
    }
60
61
    /**
62
     * @inheritDoc
63
     */
64
    public function get(int $index)
65
    {
66
        if (!$this->validIndex($index)) {
67
            throw new OutOfRangeException();
68
        }
69
70
        return $this[$index];
71
    }
72
73
    /**
74
     * @inheritDoc
75
     */
76
    public function insert(int $index, ...$values)
77
    {
78
        if (!$this->validIndex($index) && $index !== $this->count()) {
79
            throw new OutOfRangeException();
80
        }
81
82
        $splice = $this->splice($index, 0, $values);
83
        $this->clear();
84
85
        $this->pushAll($splice);
86
    }
87
88
    /**
89
     * @inheritDoc
90
     */
91
    public function last()
92
    {
93
        $this->emptyGuard(__METHOD__);
94
        return $this[$this->count() - 1];
95
    }
96
97
    /**
98
     * Converts negative or large rotations into the minimum positive number
99
     * of rotations required to rotate the sequence by a given $r.
100
     */
101
    private function normalizeRotations(int $r)
102
    {
103
        $n = $this->count();
104
105
        if ($n < 2) {
106
            return 0;
107
        }
108
109
        if ($r < 0) {
110
            return $n - (abs($r) % $n);
111
        }
112
113
        return $r % $n;
114
    }
115
116
    /**
117
     * @inheritDoc
118
     */
119
    public function pop()
120
    {
121
        $this->emptyGuard(__METHOD__);
122
        $value = $this->last();
123
        $count = $this->count();
124
        unset($this[--$count]);
125
        $this->setSize($count);
126
127
        $this->checkCapacity();
128
129
        return $value;
130
    }
131
132
    /**
133
     * Pushes all values of either an array or traversable object.
134
     */
135
    private function pushAll(...$args)
136
    {
137
        $size = $this->getSize();
138
139
        foreach ($args as &$values) {
140
            $this->setSize($size + count($values));
141
142
            foreach ($values as $value) {
143
                $this[$size++] = $value;
144
            }
145
        }
146
147
        $this->checkCapacity();
148
    }
149
150
    /**
151
     * @inheritDoc
152
     */
153
    public function push(...$values)
154
    {
155
        $this->pushAll($values);
156
    }
157
158
    /**
159
     * @inheritDoc
160
     */
161
    public function remove(int $index)
162
    {
163
        if (!$this->validIndex($index)) {
164
            throw new OutOfRangeException();
165
        }
166
167
        $value = $this[$index];
168
        $splice = $this->splice($index + 1, 1, null);
169
        $this->clear();
170
171
        $this->pushAll($splice);
172
        return $value;
173
    }
174
175
    /**
176
     * @inheritDoc
177
     */
178
    public function set(int $index, $value)
179
    {
180
        if (!$this->validIndex($index)) {
181
            throw new OutOfRangeException();
182
        }
183
184
        $this->sfa->offsetSet($index, $value);
185
    }
186
187
    /**
188
     * @inheritDoc
189
     */
190
    public function shift()
191
    {
192
        $this->emptyGuard(__METHOD__);
193
        $value = $this->first();
194
        unset($this[0]);
195
196
        $this->checkCapacity();
197
198
        return $value;
199
    }
200
201
    /**
202
     * @inheritDoc
203
     */
204
    public function toArray(): array
205
    {
206
        return $this->sfa->toArray();
207
    }
208
209
    /**
210
     * @inheritDoc
211
     */
212
    public function unshift(...$values)
213
    {
214
        $this->insert(0, ...$values);
215
        
216
        return $this->count();
217
    }
218
219
    /**
220
     * @inheritDoc
221
     */
222
    protected function validIndex(int $index)
223
    {
224
        return $index >= 0 && $index < $this->count();
225
    }
226
227
    /**
228
     * @inheritDoc
229
     */
230
    public function clear()
231
    {
232
        $this->sfa->setSize(0);
233
        $this->checkCapacity();
234
    }
235
236
    protected function getValues(): Traversable
237
    {
238
        return $this->sfa;
239
    }
240
241
    protected function setValues(Traversable $traversable)
242
    {
243
        $this->clear();
244
        $this->pushAll($traversable);
245
    }
246
247
    /**
248
     * Gets the size of the array.
249
     *
250
     * @return int
251
     */
252
    protected function getSize(): int
253
    {
254
        return $this->sfa->getSize();
255
    }
256
257
    /**
258
     * Change the size of an array to the new size of size.
259
     * If size is less than the current array size, any values after the
260
     * new size will be discarded. If size is greater than the current
261
     * array size, the array will be padded with NULL values.
262
     *
263
     * @param int $size The new array size. This should be a value between 0
264
     * and PHP_INT_MAX.
265
     * @return bool Returns TRUE on success or FALSE on failure.
266
     */
267
    protected function setSize(int $size): bool
268
    {
269
        return $this->sfa->setSize($size);
270
    }
271
272
    public function __clone()
273
    {
274
        return $this->copy();
0 ignored issues
show
Bug introduced by
It seems like copy() 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

274
        return $this->/** @scrutinizer ignore-call */ copy();
Loading history...
275
    }
276
277
    abstract protected function checkCapacity();
278
279
    abstract protected function emptyGuard($method);
280
281
    abstract public function isEmpty(): bool;
282
283
    abstract public function splice(int $begin = 0, int $length = null, $replacement = []);
284
}
285