Completed
Push — master ( 556fe8...ce0086 )
by Christophe
19:13
created

BitArray::restrict()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
rs 9.4285
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
3
/**
4
 * chdemko\BitArray\BitArray class
5
 *
6
 * @author     Christophe Demko <[email protected]>
7
 * @copyright  Copyright (C) 2012-2018 Christophe Demko. All rights reserved.
8
 *
9
 * @license    BSD 3-Clause License
10
 *
11
 * This file is part of the php-bitarray package https://github.com/chdemko/php-bitarray
12
 */
13
14
// Declare chdemko\BitArray namespace
15
namespace chdemko\BitArray;
16
17
/**
18
 * Array of bits
19
 *
20
 * @package  BitArray
21
 *
22
 * @property-read  integer  $count  The number of bits set to true
23
 * @property-read  integer  $size   The number of bits
24
 *
25
 * @since    1.0.0
26
 */
27
class BitArray implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
28
{
29
	/**
30
	 * @var  BitArray  Empty bit array
31
	 */
32
	private static $empty;
0 ignored issues
show
Unused Code introduced by
The property $empty is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
33
34
	/**
35
	 * @var  integer[]  Number of bits for each value between 0 and 255
36
	 */
37
	private static $count = array(
38
		0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
39
		1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
40
		1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
41
		2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
42
		1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
43
		2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
44
		2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
45
		3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
46
		1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
47
		2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
48
		2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
49
		3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
50
		2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
51
		3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
52
		3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
53
		4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
54
	);
55
56
	/**
57
	 * @var  integer[]  Mask for restricting complements
58
	 */
59
	private static $restrict = array(255, 1, 3, 7, 15, 31, 63, 127);
60
61
	/**
62
	 * @var     string  Underlying data
63
	 *
64
	 * @since   1.0.0
65
	 */
66
	private $data;
67
68
	/**
69
	 * @var     integer  Size of the bit array
70
	 *
71
	 * @since   1.0.0
72
	 */
73
	private $size;
74
75
	/**
76
	 * Create a new bit array of the given size
77
	 *
78
	 * @param   integer  $size     The BitArray size
79
	 * @param   boolean  $default  The default value for bits
80
	 *
81
	 * @since   1.0.0
82
	 */
83
	protected function __construct($size = 0, $default = false)
84
	{
85
		$this->size = (int) $size;
86
87
		if ($default)
88
		{
89
			$this->data = str_repeat(chr(255), ceil($this->size / 8));
90
			$this->restrict();
91
		}
92
		else
93
		{
94
			$this->data = str_repeat(chr(0), ceil($this->size / 8));
95
		}
96
	}
97
98
	/**
99
	 * Remove useless bits for simplifying count operation.
100
	 *
101
	 * @return  BitArray  $this for chaining
102
	 *
103
	 * @since   1.2.0
104
	 */
105
	protected function restrict()
106
	{
107
		$length = strlen($this->data);
108
109
		if ($length > 0)
110
		{
111
			$this->data[$length - 1] = chr(ord($this->data[$length - 1]) & self::$restrict[$this->size % 8]);
112
		}
113
114
		return $this;
115
	}
116
117
	/**
118
	 * Clone a BitArray
119
	 *
120
	 * @return  void
121
	 *
122
	 * @since   1.0.0
123
	 */
124
	public function __clone()
125
	{
126
		$this->data = str_repeat($this->data, 1);
127
	}
128
129
	/**
130
	 * Convert the object to a string
131
	 *
132
	 * @return  string  String representation of this object
133
	 *
134
	 * @since   1.0.0
135
	 */
136
	public function __toString()
137
	{
138
		$string = str_repeat('0', $this->size);
139
140
		for ($offset = 0; $offset < $this->size; $offset++)
141
		{
142
			if (ord($this->data[(int) ($offset / 8)]) & (1 << $offset % 8))
143
			{
144
				$string[$offset] = '1';
145
			}
146
		}
147
148
		return $string;
149
	}
150
151
	/**
152
	 * Magic get method
153
	 *
154
	 * @param   string  $property  The property
155
	 *
156
	 * @throws  \RuntimeException  If the property does not exist
157
	 *
158
	 * @return  mixed  The value associated to the property
159
	 *
160
	 * @since   1.0.0
161
	 */
162
	public function __get($property)
163
	{
164
		switch ($property)
165
		{
166
			case 'size':
167
				return $this->size;
168
			case 'count':
169
				return $this->count();
170
			default:
171
				throw new \RuntimeException('Undefined property');
172
		}
173
	}
174
175
	/**
176
	 * Test the existence of an index
177
	 *
178
	 * @param   integer  $offset  The offset
179
	 *
180
	 * @return  boolean  The truth value
181
	 *
182
	 * @since   1.0.0
183
	 */
184
	public function offsetExists($offset)
185
	{
186
		return is_int($offset) && $offset >= 0 && $offset < $this->size;
187
	}
188
189
	/**
190
	 * Get the truth value for an index
191
	 *
192
	 * @param   integer  $offset  The offset
193
	 *
194
	 * @return  boolean  The truth value
195
	 *
196
	 * @throw   \OutOfRangeException  Argument index must be an positive integer lesser than the size
197
	 *
198
	 * @since   1.0.0
199
	 */
200
	public function offsetGet($offset)
201
	{
202
		if ($this->offsetExists($offset))
203
		{
204
			return (bool) (ord($this->data[(int) ($offset / 8)]) & (1 << $offset % 8));
205
		}
206
		else
207
		{
208
			throw new \OutOfRangeException('Argument offset must be a positive integer lesser than the size');
209
		}
210
	}
211
212
	/**
213
	 * Set the truth value for an index
214
	 *
215
	 * @param   integer  $offset  The offset
216
	 * @param   boolean  $value   The truth value
217
	 *
218
	 * @return  void
219
	 *
220
	 * @throw   \OutOfRangeException  Argument index must be an positive integer lesser than the size
221
	 *
222
	 * @since   1.0.0
223
	 */
224
	public function offsetSet($offset, $value)
225
	{
226
		if ($this->offsetExists($offset))
227
		{
228
			$index = (int) ($offset / 8);
229
230
			if ($value)
231
			{
232
				$this->data[$index] = chr(ord($this->data[$index]) | (1 << $offset % 8));
233
			}
234
			else
235
			{
236
				$this->data[$index] = chr(ord($this->data[$index]) & ~(1 << $offset % 8));
237
			}
238
		}
239
		else
240
		{
241
			throw new \OutOfRangeException('Argument index must be a positive integer lesser than the size');
242
		}
243
	}
244
245
	/**
246
	 * Unset the existence of an index
247
	 *
248
	 * @param   integer  $offset  The index
249
	 *
250
	 * @return  void
251
	 *
252
	 * @throw   \RuntimeException  Values cannot be unset
253
	 *
254
	 * @since   1.0.0
255
	 */
256
	public function offsetUnset($offset)
257
	{
258
		throw new \RuntimeException('Values cannot be unset');
259
	}
260
261
	/**
262
	 * Return the number of true bits
263
	 *
264
	 * @return  integer  The number of true bits
265
	 *
266
	 * @since   1.0.0
267
	 */
268
	public function count()
269
	{
270
		$count = 0;
271
272
		for ($index = 0, $length = strlen($this->data); $index < $length; $index++)
273
		{
274
			$count += self::$count[ord($this->data[$index])];
275
		}
276
277
		return $count;
278
	}
279
280
	/**
281
	 * Transform the object to an array
282
	 *
283
	 * @return  array  Array of values
284
	 *
285
	 * @since   1.1.0
286
	 */
287
	public function toArray()
288
	{
289
		$array = array();
290
291
		for ($index = 0; $index < $this->size; $index++)
292
		{
293
			$array[] = (bool) (ord($this->data[(int) ($index / 8)]) & (1 << $index % 8));
294
		}
295
296
		return $array;
297
	}
298
299
	/**
300
	 * Serialize the object
301
	 *
302
	 * @return  array  Array of values
303
	 *
304
	 * @since   1.0.0
305
	 */
306
	public function jsonSerialize()
307
	{
308
		return $this->toArray();
309
	}
310
311
	/**
312
	 * Get an iterator
313
	 *
314
	 * @return  Iterator  Iterator
315
	 *
316
	 * @since   1.0.0
317
	 */
318
	public function getIterator()
319
	{
320
		return new Iterator($this);
321
	}
322
323
	/**
324
	 * Return the size
325
	 *
326
	 * @return  integer  The size
327
	 *
328
	 * @since   1.0.0
329
	 */
330
	public function size()
331
	{
332
		return $this->size;
333
	}
334
335
	/**
336
	 * Copy bits directly from a BitArray
337
	 *
338
	 * @param   BitArray  $bits    A BitArray to copy
339
	 * @param   int       $index   Starting index for destination
340
	 * @param   int       $offset  Starting index for copying
341
	 * @param   int       $size    Copy size
342
	 *
343
	 * @return  BitArray  This object for chaining
344
	 *
345
	 * @throw   \OutOfRangeException  Argument index must be an positive integer lesser than the size
346
	 *
347
	 * @since   1.1.0
348
	 */
349
	public function directCopy(BitArray $bits, $index = 0, $offset = 0, $size = 0)
350
	{
351
		if ($offset > $index)
352
		{
353 View Code Duplication
			for ($i = 0; $i < $size; $i++)
354
			{
355
				$this[$i + $index] = $bits[$i + $offset];
356
			}
357
		}
358
		else
359
		{
360 View Code Duplication
			for ($i = $size - 1; $i >= 0; $i--)
361
			{
362
				$this[$i + $index] = $bits[$i + $offset];
363
			}
364
		}
365
366
		return $this;
367
	}
368
369
	/**
370
	 * Copy bits from a BitArray
371
	 *
372
	 * @param   BitArray  $bits    A BitArray to copy
373
	 * @param   int       $index   Starting index for destination.
374
	 *                             If index is non-negative, the index parameter is used as it is, keeping its real value between 0 and size-1.
375
	 *                             If index is negative, the index parameter starts from the end, keeping its real value between 0 and size-1.
376
	 * @param   int       $offset  Starting index for copying.
377
	 *                             If offset is non-negative, the offset parameter is used as it is, keeping its positive value between 0 and size-1.
378
	 *                             If offset is negative, the offset parameter starts from the end, keeping its real value between 0 and size-1.
379
	 * @param   mixed     $size    Copy size.
380
	 *                             If size is given and is positive, then the copy will copy size elements.
381
	 *                             If the bits argument is shorter than the size, then only the available elements will be copied.
382
	 *                             If size is given and is negative then the copy starts from the end.
383
	 *                             If it is omitted, then the copy will have everything from offset up until the end of the bits argument.
384
	 *
385
	 * @return  BitArray  This object for chaining
386
	 *
387
	 * @since   1.1.0
388
	 */
389
	public function copy(BitArray $bits, $index = 0, $offset = 0, $size = null)
390
	{
391
		$index = $this->getRealOffset($index);
392
		$offset = $bits->getRealOffset($offset);
393
		$size = $bits->getRealSize($offset, $size);
394
395
		if ($size > $this->size - $index)
396
		{
397
			$size = $this->size - $index;
398
		}
399
400
		return $this->directCopy($bits, $index, $offset, $size);
401
	}
402
403
	/**
404
	 * Get the real offset using a positive or negative offset
405
	 *
406
	 * @param   int  $offset  If offset is non-negative, the offset parameter is used as it is, keeping its real value between 0 and size-1.
407
	 *                        If offset is negative, the offset parameter starts from the end, keeping its real value between 0 and size-1.
408
	 *
409
	 * @return  integer  The real offset
410
	 *
411
	 * @since   1.1.0
412
	 */
413
	protected function getRealOffset($offset)
414
	{
415
		$offset = (int) $offset;
416
417
		if ($offset < 0)
418
		{
419
			// Start from the end
420
			$offset = $this->size + $offset;
421
422
			if ($offset < 0)
423
			{
424
				$offset = 0;
425
			}
426
		}
427
		elseif ($offset > $this->size)
428
		{
429
			$offset = $this->size;
430
		}
431
432
		return $offset;
433
	}
434
435
	/**
436
	 * Get the real offset using a positive or negative offset
437
	 *
438
	 * @param   int    $offset  The real offset.
439
	 * @param   mixed  $size    If size is given and is positive, then the real size will be between 0 and the current size-1.
440
	 *                          If size is given and is negative then the real size starts from the end.
441
	 *                          If it is omitted, then the size goes until the end of the BitArray.
442
	 *
443
	 * @return  integer  The real size
444
	 *
445
	 * @since   1.1.0
446
	 */
447
	protected function getRealSize($offset, $size)
448
	{
449
		if ($size === null)
450
		{
451
			$size = $this->size - $offset;
452
		}
453
		else
454
		{
455
			$size = (int) $size;
456
457
			if ($size < 0)
458
			{
459
				$size = $this->size + $size - $offset;
460
461
				if ($size < 0)
462
				{
463
					$size = 0;
464
				}
465
			}
466
			elseif ($size > $this->size - $offset)
467
			{
468
				$size = $this->size - $offset;
469
			}
470
		}
471
472
		return $size;
473
	}
474
475
	/**
476
	 * Create a new BitArray from an integer
477
	 *
478
	 * @param   integer  $size     Size of the BitArray
479
	 * @param   boolean  $default  The default value for bits
480
	 *
481
	 * @return  BitArray  A new BitArray
482
	 *
483
	 * @since   1.0.0
484
	 */
485
	public static function fromInteger($size, $default = false)
486
	{
487
		return new BitArray($size, (bool) $default);
488
	}
489
490
	/**
491
	 * Create a new BitArray from a sequence of bits.
492
	 *
493
	 * @param   integer  $size    Size of the BitArray
494
	 * @param   integer  $values  The values for the bits
495
	 *
496
	 * @return  BitArray  A new BitArray
497
	 *
498
	 * @since   1.2.0
499
	 */
500
	public static function fromDecimal($size, $values = 0)
501
	{
502
		$size = min((int) $size, PHP_INT_SIZE);
503
		$values <<= PHP_INT_SIZE - $size;
504
		$bits = new BitArray($size);
505
506
		for ($i = 0; $i < PHP_INT_SIZE; $i++)
507
		{
508
			$bits->data[$i] = chr(($values & (0xff << (PHP_INT_SIZE - 8))) >> (PHP_INT_SIZE - 8));
509
			$values <<= 8;
510
		}
511
512
		return $bits;
513
	}
514
515
	/**
516
	 * Create a new BitArray from a traversable
517
	 *
518
	 * @param   \Traversable  $traversable  A traversable and countable
519
	 *
520
	 * @return  BitArray  A new BitArray
521
	 *
522
	 * @since   1.0.0
523
	 */
524 View Code Duplication
	public static function fromTraversable($traversable)
525
	{
526
		$bits = new BitArray(count($traversable));
527
		$offset = 0;
528
		$ord = 0;
529
530
		foreach ($traversable as $value)
531
		{
532
			if ($value)
533
			{
534
				$ord |= 1 << $offset % 8;
535
			}
536
537
			if ($offset % 8 === 7)
538
			{
539
				$bits->data[(int) ($offset / 8)] = chr($ord);
540
				$ord = 0;
541
			}
542
543
			$offset++;
544
		}
545
546
		if ($offset % 8 !== 0)
547
		{
548
			$bits->data[(int) ($offset / 8)] = chr($ord);
549
		}
550
551
		return $bits;
552
	}
553
554
	/**
555
	 * Create a new BitArray from a bit string
556
	 *
557
	 * @param   string  $string  A bit string
558
	 *
559
	 * @return  BitArray  A new BitArray
560
	 *
561
	 * @since   1.0.0
562
	 */
563 View Code Duplication
	public static function fromString($string)
564
	{
565
		$bits = new BitArray(strlen($string));
566
		$ord = 0;
567
568
		for ($offset = 0; $offset < $bits->size; $offset++)
569
		{
570
			if ($string[$offset] !== '0')
571
			{
572
				$ord |= 1 << $offset % 8;
573
			}
574
575
			if ($offset % 8 === 7)
576
			{
577
				$bits->data[(int) ($offset / 8)] = chr($ord);
578
				$ord = 0;
579
			}
580
		}
581
582
		if ($offset % 8 !== 0)
583
		{
584
			$bits->data[(int) ($offset / 8)] = chr($ord);
585
		}
586
587
		return $bits;
588
	}
589
590
	/**
591
	 * Create a new BitArray from json
592
	 *
593
	 * @param   string  $json  A json encoded value
594
	 *
595
	 * @return  BitArray  A new BitArray
596
	 *
597
	 * @since   1.0.0
598
	 */
599
	public static function fromJson($json)
600
	{
601
		return self::fromTraversable(json_decode($json));
602
	}
603
604
	/**
605
	 * Create a new BitArray using a slice
606
	 *
607
	 * @param   BitArray  $bits    A BitArray to get the slice
608
	 * @param   int       $offset  If offset is non-negative, the slice will start at that offset in the bits argument.
609
	 *                             If offset is negative, the slice will start from the end of the bits argument.
610
	 * @param   mixed     $size    If size is given and is positive, then the slice will have up to that many elements in it.
611
	 *                             If the bits argument is shorter than the size, then only the available elements will be present.
612
	 *                             If size is given and is negative then the slice will stop that many elements from the end of the bits argument.
613
	 *                             If it is omitted, then the slice will have everything from offset up until the end of the bits argument.
614
	 *
615
	 * @return  BitArray  A new BitArray
616
	 *
617
	 * @since   1.1.0
618
	 */
619
	public static function fromSlice(BitArray $bits, $offset = 0, $size = null)
620
	{
621
		$offset = $bits->getRealOffset($offset);
622
		$size = $bits->getRealSize($offset, $size);
623
		$slice = new BitArray($size);
624
625
		return $slice->directCopy($bits, 0, $offset, $size);
626
	}
627
628
	/**
629
	 * Create a new BitArray using the concat operation
630
	 *
631
	 * @param   BitArray  $bits1  A BitArray
632
	 * @param   BitArray  $bits2  A BitArray
633
	 *
634
	 * @return  BitArray  A new BitArray
635
	 *
636
	 * @since   1.1.0
637
	 */
638
	public static function fromConcat(BitArray $bits1, BitArray $bits2)
639
	{
640
		$size = $bits1->size + $bits2->size;
641
		$concat = new BitArray($size);
642
		$concat->directCopy($bits1, 0, 0, $bits1->size);
643
		$concat->directCopy($bits2, $bits1->size, 0, $bits2->size);
644
645
		return $concat;
646
	}
647
648
	/**
649
	 * Complement the bit array
650
	 *
651
	 * @return  BitArray  This object for chaining
652
	 *
653
	 * @since   1.0.0
654
	 */
655
	public function applyComplement()
656
	{
657
		$length = strlen($this->data);
658
659
		for ($index = 0; $index < $length; $index++)
660
		{
661
			$this->data[$index] = chr(~ ord($this->data[$index]));
662
		}
663
664
		return $this->restrict();
665
	}
666
667
	/**
668
	 * Or with an another bit array
669
	 *
670
	 * @param   BitArray  $bits  A bit array
671
	 *
672
	 * @return  BitArray  This object for chaining
673
	 *
674
	 * @throw   \InvalidArgumentException  Argument must be of equal size
675
	 *
676
	 * @since   1.0.0
677
	 */
678 View Code Duplication
	public function applyOr(BitArray $bits)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
679
	{
680
		if ($this->size == $bits->size)
681
		{
682
			$length = strlen($this->data);
683
684
			for ($index = 0; $index < $length; $index++)
685
			{
686
				$this->data[$index] = chr(ord($this->data[$index]) | ord($bits->data[$index]));
687
			}
688
689
			return $this;
690
		}
691
		else
692
		{
693
			throw new \InvalidArgumentException('Argument must be of equal size');
694
		}
695
	}
696
697
	/**
698
	 * And with an another bit array
699
	 *
700
	 * @param   BitArray  $bits  A bit array
701
	 *
702
	 * @return  BitArray  This object for chaining
703
	 *
704
	 * @throw   \InvalidArgumentException  Argument must be of equal size
705
	 *
706
	 * @since   1.0.0
707
	 */
708 View Code Duplication
	public function applyAnd(BitArray $bits)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
709
	{
710
		if ($this->size == $bits->size)
711
		{
712
			$length = strlen($this->data);
713
714
			for ($index = 0; $index < $length; $index++)
715
			{
716
				$this->data[$index] = chr(ord($this->data[$index]) & ord($bits->data[$index]));
717
			}
718
719
			return $this;
720
		}
721
		else
722
		{
723
			throw new \InvalidArgumentException('Argument must be of equal size');
724
		}
725
	}
726
727
	/**
728
	 * Xor with an another bit array
729
	 *
730
	 * @param   BitArray  $bits  A bit array
731
	 *
732
	 * @return  BitArray  This object for chaining
733
	 *
734
	 * @throw   \InvalidArgumentException  Argument must be of equal size
735
	 *
736
	 * @since   1.0.0
737
	 */
738 View Code Duplication
	public function applyXor(BitArray $bits)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
739
	{
740
		if ($this->size == $bits->size)
741
		{
742
			$length = strlen($this->data);
743
744
			for ($index = 0; $index < $length; $index++)
745
			{
746
				$this->data[$index] = chr(ord($this->data[$index]) ^ ord($bits->data[$index]));
747
			}
748
749
			return $this;
750
		}
751
		else
752
		{
753
			throw new \InvalidArgumentException('Argument must be of equal size');
754
		}
755
	}
756
757
	/**
758
	 * Shift a bit array.
759
	 *
760
	 * @param   int       $size   Size to shift.
761
	 *                            Negative value means the shifting is done right to left while
762
	 *                            positive value means the shifting is done left to right.
763
	 * @param   boolean   $value  Value to shift
764
	 *
765
	 * @return  BitArray  $this for chaining
766
	 *
767
	 * @since   1.2.0
768
	 */
769
	public function shift($size = 1, $value = false)
770
	{
771
		$size = (int) $size;
772
773
		if ($size > 0)
774
		{
775
			$min = min($this->size, $size);
776
777 View Code Duplication
			for ($i = $this->size - 1; $i >= $min; $i--)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
778
			{
779
				$this[$i] = $this[$i - $min];
780
			}
781
782
			for ($i = 0; $i < $min; $i++)
783
			{
784
				$this[$i] = $value;
785
			}
786
		}
787
		else
788
		{
789
			$min = min($this->size, -$size);
790
791 View Code Duplication
			for ($i = 0; $i < $this->size - $min; $i++)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
792
			{
793
				$this[$i] = $this[$i + $min];
794
			}
795
796
			for ($i = $this->size - $min; $i < $this->size; $i++)
797
			{
798
				$this[$i] = $value;
799
			}
800
		}
801
802
		return $this;
803
	}
804
}
805