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