GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Flags::test()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 13
ccs 8
cts 8
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\ASN1\Util;
6
7
use Sop\ASN1\Type\Primitive\BitString;
8
9
/**
10
 * Class to handle a bit string as a field of flags.
11
 */
12
class Flags
13
{
14
    /**
15
     * Flag octets.
16
     *
17
     * @var string
18
     */
19
    protected $_flags;
20
21
    /**
22
     * Number of flags.
23
     *
24
     * @var int
25
     */
26
    protected $_width;
27
28
    /**
29
     * Constructor.
30
     *
31
     * @param int|string $flags Flags
32
     * @param int        $width The number of flags. If width is larger than
33
     *                          number of bits in $flags, zeroes are prepended
34
     *                          to flag field.
35
     */
36 62
    public function __construct($flags, int $width)
37
    {
38 62
        if (!$width) {
39 2
            $this->_flags = '';
40
        } else {
41
            // calculate number of unused bits in last octet
42 60
            $last_octet_bits = $width % 8;
43 60
            $unused_bits = $last_octet_bits ? 8 - $last_octet_bits : 0;
44 60
            $num = gmp_init($flags);
45
            // mask bits outside bitfield width
46 60
            $mask = gmp_sub(gmp_init(1) << $width, 1);
47 60
            $num &= $mask;
48
            // shift towards MSB if needed
49 60
            $data = gmp_export($num << $unused_bits, 1,
50 60
                GMP_MSW_FIRST | GMP_BIG_ENDIAN);
51 60
            $octets = unpack('C*', $data);
52 60
            assert(is_array($octets), new \RuntimeException('unpack() failed'));
53 60
            $bits = count($octets) * 8;
54
            // pad with zeroes
55 60
            while ($bits < $width) {
56 20
                array_unshift($octets, 0);
57 20
                $bits += 8;
58
            }
59 60
            $this->_flags = pack('C*', ...$octets);
60
        }
61 62
        $this->_width = $width;
62 62
    }
63
64
    /**
65
     * Initialize from `BitString`.
66
     */
67 8
    public static function fromBitString(BitString $bs, int $width): self
68
    {
69 8
        $num_bits = $bs->numBits();
70 8
        $num = gmp_import($bs->string(), 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN);
71 8
        $num >>= $bs->unusedBits();
72 8
        if ($num_bits < $width) {
73 5
            $num <<= ($width - $num_bits);
74
        }
75 8
        return new self(gmp_strval($num, 10), $width);
76
    }
77
78
    /**
79
     * Check whether a bit at given index is set.
80
     *
81
     * Index 0 is the leftmost bit.
82
     *
83
     * @throws \OutOfBoundsException
84
     */
85 15
    public function test(int $idx): bool
86
    {
87 15
        if ($idx >= $this->_width) {
88 1
            throw new \OutOfBoundsException('Index is out of bounds.');
89
        }
90
        // octet index
91 14
        $oi = (int) floor($idx / 8);
92 14
        $byte = $this->_flags[$oi];
93
        // bit index
94 14
        $bi = $idx % 8;
95
        // index 0 is the most significant bit in byte
96 14
        $mask = 0x01 << (7 - $bi);
97 14
        return (ord($byte) & $mask) > 0;
98
    }
99
100
    /**
101
     * Get flags as an octet string.
102
     *
103
     * Zeroes are appended to the last octet if width is not divisible by 8.
104
     */
105 23
    public function string(): string
106
    {
107 23
        return $this->_flags;
108
    }
109
110
    /**
111
     * Get flags as a base 10 integer.
112
     *
113
     * @return string Integer as a string
114
     */
115 15
    public function number(): string
116
    {
117 15
        $num = gmp_import($this->_flags, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN);
118 15
        $last_octet_bits = $this->_width % 8;
119 15
        $unused_bits = $last_octet_bits ? 8 - $last_octet_bits : 0;
120 15
        $num >>= $unused_bits;
121 15
        return gmp_strval($num, 10);
122
    }
123
124
    /**
125
     * Get flags as an integer.
126
     */
127 1
    public function intNumber(): int
128
    {
129 1
        $num = new BigInt($this->number());
130 1
        return $num->intVal();
131
    }
132
133
    /**
134
     * Get flags as a `BitString` object.
135
     *
136
     * Unused bits are set accordingly. Trailing zeroes are not stripped.
137
     */
138 9
    public function bitString(): BitString
139
    {
140 9
        $last_octet_bits = $this->_width % 8;
141 9
        $unused_bits = $last_octet_bits ? 8 - $last_octet_bits : 0;
142 9
        return new BitString($this->_flags, $unused_bits);
143
    }
144
}
145