Integer::isInRange()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 4
nc 5
nop 1
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 4
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Vanderlee\Comprehend\Parser\Terminal;
4
5
use Exception;
6
use Vanderlee\Comprehend\Core\Context;
7
use Vanderlee\Comprehend\Match\Failure;
8
use Vanderlee\Comprehend\Match\Success;
9
use Vanderlee\Comprehend\Parser\Parser;
10
11
/**
12
 * Matches an integer within the specified range.
13
 *
14
 * @author Martijn
15
 */
16
class Integer extends Parser
17
{
18
    use CaseSensitiveTrait;
19
20
    /**
21
     * List of digits to use for the different bases (up to 36).
22
     *
23
     * @var string
24
     */
25
    private static $set = '0123456789abcdefghijklmnopqrstuvwxyz';
26
27
    /**
28
     * @var int|null
29
     */
30
    private $minimum;
31
32
    /**
33
     * @var int|null
34
     */
35
    private $maximum;
36
37
    /**
38
     * @var int
39
     */
40
    private $base;
41
42
    /**
43
     * @param int|null $minimum
44
     * @param int|null $maximum
45
     * @param int $base
46
     *
47
     * @throws Exception
48
     */
49 8
    public function __construct($minimum = 0, $maximum = null, $base = 10)
50
    {
51 8
        if ($minimum !== null
52 8
            && $maximum !== null
53 8
            && $minimum > $maximum) {
54 1
            throw new Exception('Maximum must be greater than minimum');
55
        }
56
57 7
        $this->setMinimum($minimum);
58 6
        $this->setMaximum($maximum);
59
60 5
        $this->base = intval($base);
61 5
        if ($base < 2
62 5
            || $base > strlen(self::$set)) {
63 2
            throw new Exception('Unsupported base');
64
        }
65 3
    }
66
67
    /**
68
     * @param int|null $minimum
69
     *
70
     * @throws Exception
71
     */
72 7
    private function setMinimum($minimum)
73
    {
74 7
        if ($minimum !== null
75 7
            && !is_int($minimum)) {
0 ignored issues
show
introduced by
The condition is_int($minimum) is always true.
Loading history...
76 1
            throw new Exception('Minimum must be integer or `null`');
77
        }
78
79 6
        $this->minimum = $minimum;
80 6
    }
81
82
    /**
83
     * @param int|null $maximum
84
     *
85
     * @throws Exception
86
     */
87 6
    private function setMaximum($maximum)
88
    {
89 6
        if ($maximum !== null
90 6
            && !is_int($maximum)) {
0 ignored issues
show
introduced by
The condition is_int($maximum) is always true.
Loading history...
91 1
            throw new Exception('Maximum must be integer or `null`');
92
        }
93
94 5
        $this->maximum = $maximum;
95 5
    }
96
97 51
    private function isInRange($integer)
98
    {
99 51
        return ($this->minimum === null
100 51
                || $integer >= $this->minimum)
101 49
            && ($this->maximum === null
102 51
                || $integer <= $this->maximum);
103
    }
104
105
    /**
106
     * @param string $input
107
     * @param int $offset
108
     * @param Context $context
109
     *
110
     * @return Failure|Success
111
     */
112 54
    protected function parse(&$input, $offset, Context $context)
113
    {
114 54
        $this->pushCaseSensitivityToContext($context);
115
116
        // Build pattern
117 54
        $set0 = substr(self::$set, 0, $this->base);
118 54
        $set1 = substr(self::$set, 1, $this->base - 1);
119 54
        $pattern = '/(?:0|-?[' . $set1 . '][' . $set0 . ']*)/A' . ($context->isCaseSensitive()
120 51
                ? ''
121 54
                : 'i');
122
123 54
        $this->popCaseSensitivityFromContext($context);
124
125 54
        if (preg_match($pattern, $input, $match, 0, $offset) === 1) {
126
            do {
127 51
                $integer = intval($match[0], $this->base);
128 51
                if ($this->isInRange($integer)
129 51
                    && $match[0] !== '-') {
130 40
                    return $this->success($input, $offset, mb_strlen($match[0]));
131
                }
132
133 18
                $match[0] = substr($match[0], 0, -1); // strip off last char
134 18
            } while ($match[0] !== '');
135
        }
136
137 14
        return $this->failure($input, $offset);
138
    }
139
140
    /**
141
     * @return string
142
     */
143 54
    public function __toString()
144
    {
145 54
        return ($this->minimum === null
146 7
                ? '<-INF'
147 54
                : ('[' . $this->minimum)) . ',' . ($this->maximum === null
148 14
                ? 'INF>'
149 54
                : ($this->maximum . ']'));
150
    }
151
}
152