• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlocati / ip-lib / 13077233848

31 Jan 2025 04:58PM UTC coverage: 98.543% (-0.08%) from 98.622%
13077233848

Pull #93

github

web-flow
Merge e087e6636 into 67ce14c6f
Pull Request #93: Add `split` Method to Subnet for Dividing Network Ranges into Smaller Subnets

20 of 21 new or added lines in 1 file covered. (95.24%)

1 existing line in 1 file now uncovered.

879 of 892 relevant lines covered (98.54%)

220.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.55
/src/Range/AbstractRange.php
1
<?php
2

3
namespace IPLib\Range;
4

5
use IPLib\Address\AddressInterface;
6
use IPLib\Address\IPv4;
7
use IPLib\Address\IPv6;
8
use IPLib\Address\Type as AddressType;
9
use IPLib\Factory;
10
use OutOfBoundsException;
11
use OverflowException;
12

13
/**
14
 * Base class for range classes.
15
 */
16
abstract class AbstractRange implements RangeInterface
17
{
18
    /**
19
     * {@inheritdoc}
20
     *
21
     * @see \IPLib\Range\RangeInterface::getRangeType()
22
     */
23
    public function getRangeType()
24
    {
25
        if ($this->rangeType === null) {
242✔
26
            $addressType = $this->getAddressType();
242✔
27
            if ($addressType === AddressType::T_IPv6 && Subnet::get6to4()->containsRange($this)) {
242✔
28
                $this->rangeType = Factory::getRangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType();
9✔
29
            } else {
30
                switch ($addressType) {
233✔
31
                    case AddressType::T_IPv4:
32
                        $defaultType = IPv4::getDefaultReservedRangeType();
170✔
33
                        $reservedRanges = IPv4::getReservedRanges();
170✔
34
                        break;
170✔
35
                    case AddressType::T_IPv6:
36
                        $defaultType = IPv6::getDefaultReservedRangeType();
63✔
37
                        $reservedRanges = IPv6::getReservedRanges();
63✔
38
                        break;
63✔
39
                    default:
40
                        throw new \Exception('@todo'); // @codeCoverageIgnore
41
                }
42
                $rangeType = null;
233✔
43
                foreach ($reservedRanges as $reservedRange) {
233✔
44
                    $rangeType = $reservedRange->getRangeType($this);
233✔
45
                    if ($rangeType !== null) {
233✔
46
                        break;
198✔
47
                    }
48
                }
49
                $this->rangeType = $rangeType === null ? $defaultType : $rangeType;
233✔
50
            }
51
        }
52

53
        return $this->rangeType === false ? null : $this->rangeType;
242✔
54
    }
55

56
    /**
57
     * {@inheritdoc}
58
     *
59
     * @see \IPLib\Range\RangeInterface::getAddressAtOffset()
60
     */
61
    public function getAddressAtOffset($n)
62
    {
63
        if (!is_int($n)) {
15✔
64
            return null;
2✔
65
        }
66

67
        $address = null;
13✔
68
        if ($n >= 0) {
13✔
69
            $start = Factory::parseAddressString($this->getComparableStartString());
8✔
70
            $address = $start->getAddressAtOffset($n);
8✔
71
        } else {
72
            $end = Factory::parseAddressString($this->getComparableEndString());
5✔
73
            $address = $end->getAddressAtOffset($n + 1);
5✔
74
        }
75

76
        if ($address === null) {
13✔
77
            return null;
1✔
78
        }
79

80
        return $this->contains($address) ? $address : null;
12✔
81
    }
82

83
    /**
84
     * {@inheritdoc}
85
     *
86
     * @see \IPLib\Range\RangeInterface::contains()
87
     */
88
    public function contains(AddressInterface $address)
89
    {
90
        $result = false;
253✔
91
        if ($address->getAddressType() === $this->getAddressType()) {
253✔
92
            $cmp = $address->getComparableString();
253✔
93
            $from = $this->getComparableStartString();
253✔
94
            if ($cmp >= $from) {
253✔
95
                $to = $this->getComparableEndString();
248✔
96
                if ($cmp <= $to) {
248✔
97
                    $result = true;
204✔
98
                }
99
            }
100
        }
101

102
        return $result;
253✔
103
    }
104

105
    /**
106
     * {@inheritdoc}
107
     *
108
     * @see \IPLib\Range\RangeInterface::containsRange()
109
     */
110
    public function containsRange(RangeInterface $range)
111
    {
112
        $result = false;
89✔
113
        if ($range->getAddressType() === $this->getAddressType()) {
89✔
114
            $myStart = $this->getComparableStartString();
89✔
115
            $itsStart = $range->getComparableStartString();
89✔
116
            if ($itsStart >= $myStart) {
89✔
117
                $myEnd = $this->getComparableEndString();
51✔
118
                $itsEnd = $range->getComparableEndString();
51✔
119
                if ($itsEnd <= $myEnd) {
51✔
120
                    $result = true;
21✔
121
                }
122
            }
123
        }
124

125
        return $result;
89✔
126
    }
127

128
    /**
129
     * {@inheritdoc}
130
     *
131
     * @see \IPLib\Range\RangeInterface::split()
132
     */
133
    public function split($networkPrefix)
134
    {
135
        $networkPrefix = (int) $networkPrefix;
42✔
136
        $myNetworkPrefix = $this->getNetworkPrefix();
42✔
137
        if ($networkPrefix === $myNetworkPrefix) {
42✔
138
            return array(
139
                new Subnet($this->getStartAddress(), $this->getEndAddress(), $networkPrefix),
10✔
140
            );
141
        }
142
        if ($networkPrefix < $myNetworkPrefix) {
32✔
143
            throw new OutOfBoundsException("The value of the \$networkPrefix parameter can't be smaller than the network prefix of the range ({$myNetworkPrefix})");
10✔
144
        }
145
        $startIp = $this->getStartAddress();
22✔
146
        $maxPrefix = $startIp::getNumberOfBits();
22✔
147
        if ($networkPrefix > $maxPrefix) {
22✔
148
            throw new OutOfBoundsException("The value of the \$networkPrefix parameter can't be larger than the maximum network prefix of the range ({$maxPrefix})");
11✔
149
        }
150

151
        $systemBitness = PHP_INT_SIZE * 8;
11✔
152
        $minPrefixByBitness = $maxPrefix - $systemBitness + 2;
11✔
153
        if ($minPrefixByBitness > $networkPrefix) {
11✔
NEW
154
            throw new OverflowException("The value of \$networkPrefix leads to too large ranges for the current machine bitness (you can use a value of at least {$minPrefixByBitness})");
×
155
        }
156

157
        $chunkSize = pow(2, $maxPrefix - $networkPrefix);
11✔
158
        $maxIndex = $this->getSize() / $chunkSize;
11✔
159
        $data = array();
11✔
160
        for ($i = 0; $i < $maxIndex; $i++) {
11✔
161
            $data[] = Subnet::parseString(sprintf('%s/%d', $startIp, $networkPrefix));
11✔
162

163
            $startIp = $startIp->getAddressAtOffset($chunkSize);
11✔
164
        }
165

166
        return $data;
11✔
167
    }
168
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc