Netmask::__construct()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 21
ccs 11
cts 11
cp 1
crap 5
rs 9.6111
1
<?php
2
/**
3
 * Copyright (c) 2018 Mattheu Racine
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace mracine\IPTools\IPv4;
10
11
use DomainException;
12
use OutOfBoundsException;
13
use Countable;
14
15
use mracine\IPTools\IPv4\Address;
16
17
/**
18
 * Class Netmask represents an IPv4 netmask, wich is an address (32 bits integer) with special requirements
19
 *
20
 * @todo detail requirements
21
 *
22
 * @package IPTools
23
 */
24
25
26
class Netmask extends Address  implements Countable
27
{
28
    /**
29
     * Creates an instance of Netmask from an integer (0x00000000 to 0xffffffff)
30
     *
31
     * Must be a valid integer : lefts bits 1, lows bits 0
32
     *
33
     * @throws OutOfBoundsException when the value is negative or greater than 32 bits value
34
     * @throws DomainException when the value does not represents a netmask
35
     * @param int $netask 32 bits integer representing the address
36
     * @return self
37
     */
38 8
    public function __construct(int $netmask)
39
    {
40 8
        parent::__construct($netmask);
41 6
        if (0==$netmask)
42
        {
43 1
            return;
44
        }
45
        // Netamsk validation
46 5
        $mask = 0xffffffff;
47
        do {
48 5
            if ($mask == $netmask)
49
            {
50
                // valid netmask
51 3
                return;
52
            }
53 4
            $mask = ($mask << 1) & 0xffffffff;   
54 4
        } while ($mask>0);
55
56 2
        if ($netmask!=0)
57
        {
58 2
            throw new DomainException(sprintf("Cannot convert 0x%x (%s) to netmask", $netmask, (string)$this));
59
        }
60
    } // @codeCoverageIgnore
61
62
    /**
63
     * Creates an instance of Netmask from an integer between 0 and 32
64
     *
65
     * Usefull to create netmask notations :
66
     * A netmask is an adress (32 bits) with its left bits stes to 1 and rights to 0.
67
     * 1 => 10000000000000000000000000000000 => "128.0.0.0"
68
     * ...
69
     * 24 => 11111111111111111111111100000000 => "255.255.255.0"
70
     *
71
     * @param int $cidr CIDR notation of address
72
     * @throws OutOfBoundsException when param is negatve or greater than 32
73
     * @return self
74
     */
75 35
    public static function fromCidr(int $cidr)
76
    {
77 35
        if ($cidr<0 || $cidr>32 )
78
        {
79 2
            throw new OutOfBoundsException(sprintf("Invalid CIDR value %d", $cidr));
80
        }
81 33
        $netmask = (0xffffffff << (32 - $cidr)) & 0xffffffff;
82 33
        return new static($netmask);
83
    }    
84
85
    /**
86
     * Get a Netmask object from an Address if possible
87
     *
88
     * @throws DomainException when the Address cannot be converted to a Netmask
89
     * @return \mracine\IPTools\IPv4\Netmask
90
     */
91
92 3
    public static function fromAddress(Address $address)
93
    {
94 3
        return new static($address->int());
95
    }
96
97
    /**
98
     * Get the CIDR integer value (0-32) from the netmask
99
     *
100
     * @see Netmask::fromCidr()
101
     * @throws DomainException when the address cannot be converted to CIDR
102
     * @return integer A value beteween 0 to 32  
103
     */
104 2
    public function asCidr()
105
    {
106
        // Pas très élégant.... 
107 2
        for ($cidr=32 ; $cidr>=0 ; $cidr--)
108
        {
109 2
            $n = (0xffffffff << (32 - $cidr)) & 0xffffffff;
110 2
            if( $n == $this->int() )
111
            {
112 2
                return $cidr;
113
            }
114
        }
115
    } // @codeCoverageIgnore
116
117
    /**
118
     * Returns how many address are incuded in the netask
119
     *
120
     * @return int
121
     */ 
122 3
    public function count()
123
    {
124 3
        return (~($this->int()) & 0xffffffff)+1;
125
    }
126
127
    /**
128
     * Returns an netmask calculated from the current netmask, shifted by an amount of bits 
129
     *
130
     * NOTICE : A new instance of address is instanciated, does not shitf the instance used.
131
     *
132
     * @param int $offset in bits
133
     * @throws OutOfBoundsException when the resulting cidr is out of the bounds (negative or greater than 32)
134
     * @return self
135
     */
136 4
    public function shift(int $offset)
137
    {
138 4
        return static::fromCidr($this->asCidr() + $offset);
139
    }
140
}