Bit::read()   C
last analyzed

Complexity

Conditions 17
Paths 53

Size

Total Lines 63
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 40
CRAP Score 17

Importance

Changes 0
Metric Value
dl 0
loc 63
ccs 40
cts 40
cp 1
rs 6.0439
c 0
b 0
f 0
cc 17
eloc 42
nc 53
nop 2
crap 17

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpBinaryReader\Type;
4
5
use PhpBinaryReader\BinaryReader;
6
use PhpBinaryReader\BitMask;
7
use PhpBinaryReader\Exception\InvalidDataException;
8
9
class Bit implements TypeInterface
10
{
11
    /**
12
     * @var bool
13
     */
14
    private $signed = false;
15
16
    /**
17
     * Returns an unsigned integer from the bit level
18
     *
19
     * @param  \PhpBinaryReader\BinaryReader $br
20
     * @param  int                           $length
21
     * @throws \OutOfBoundsException
22
     * @throws InvalidDataException
23
     * @return int
24
     */
25 76
    public function read(BinaryReader &$br, $length)
26
    {
27 76
        if (!is_int($length)) {
28 4
            throw new InvalidDataException('The length parameter must be an integer');
29
        }
30
31 72
        $bitmask = new BitMask();
32 72
        $result = 0;
33 72
        $bits = $length;
34 72
        $shift = $br->getCurrentBit();
35
36 72
        if ($shift != 0) {
37 8
            $bitsLeft = 8 - $shift;
38
39 8
            if ($bitsLeft < $bits) {
40 4
                $bits -= $bitsLeft;
41 4
                $result = ($br->getNextByte() >> $shift) << $bits;
42 8
            } elseif ($bitsLeft > $bits) {
43 8
                $br->setCurrentBit($br->getCurrentBit() + $bits);
44
45 8
                return ($br->getNextByte() >> $shift) & $bitmask->getMask($bits, BitMask::MASK_LO);
46
            } else {
47 8
                $br->setCurrentBit(0);
48
49 8
                return $br->getNextByte() >> $shift;
50
            }
51
        }
52
53 72
        if (!$br->canReadBytes($length / 8)) {
54 8
            throw new \OutOfBoundsException('Cannot read bits, it exceeds the boundary of the file');
55
        }
56
57 68
        if ($bits >= 8) {
58 38
            $bytes = intval($bits / 8);
59
60 38
            if ($bytes == 1) {
61 4
                $bits -= 8;
62 4
                $result |= ($this->getSigned() ? $br->readInt8() : $br->readUInt8()) << $bits;
63 38
            } elseif ($bytes == 2) {
64 4
                $bits -= 16;
65 4
                $result |= ($this->getSigned() ? $br->readInt16() : $br->readUInt16()) << $bits;
66 38
            } elseif ($bytes == 4) {
67 6
                $bits -= 32;
68 6
                $result |= ($this->getSigned() ? $br->readInt32() : $br->readUInt32()) << $bits;
69
            } else {
70 36
                while ($bits > 8) {
71 36
                    $bits -= 8;
72 36
                    $result |= ($this->getSigned() ? $br->readInt8() : $br->readUInt8()) << 8;
73
                }
74
            }
75
        }
76
77 68
        if ($bits != 0) {
78 66
            $code = $this->getSigned() ? 'c' : 'C';
79 66
            $data = unpack($code, $br->readFromHandle(1));
80 66
            $br->setNextByte($data[1]);
81 66
            $result |= $br->getNextByte() & $bitmask->getMask($bits, BitMask::MASK_LO);
82
        }
83
84 68
        $br->setCurrentBit($bits);
85
86 68
        return $result;
87
    }
88
89
    /**
90
     * Returns a signed integer from the bit level
91
     *
92
     * @param  \PhpBinaryReader\BinaryReader $br
93
     * @param  int                           $length
94
     * @return int
95
     */
96 74
    public function readSigned(&$br, $length)
97
    {
98 74
        $this->setSigned(true);
99 74
        $value = $this->read($br, $length);
100 66
        $this->setSigned(false);
101
102 66
        return $value;
103
    }
104
105
    /**
106
     * @param boolean $signed
107
     */
108 74
    public function setSigned($signed)
109
    {
110 74
        $this->signed = $signed;
111 74
    }
112
113
    /**
114
     * @return boolean
115
     */
116 68
    public function getSigned()
117
    {
118 68
        return $this->signed;
119
    }
120
}
121