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