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

JuliaLang / julia / #37525

pending completion
#37525

push

local

web-flow
NFC: some cleanup in gc.c (#49577)

71766 of 83435 relevant lines covered (86.01%)

34298284.82 hits per line

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

38.28
/stdlib/Sockets/src/IPAddr.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    IPAddr
5

6
Abstract supertype for IP addresses. [`IPv4`](@ref) and [`IPv6`](@ref) are subtypes of this.
7
"""
8
abstract type IPAddr end
9

10
Base.isless(a::T, b::T) where {T<:IPAddr} = isless(a.host, b.host)
×
11
(dt::Type{<:Integer})(ip::IPAddr) = dt(ip.host)::dt
×
12

13
# Allow IP addresses to broadcast as unwrapped scalars
14
Base.Broadcast.broadcastable(ip::IPAddr) = Ref(ip)
×
15

16
struct IPv4 <: IPAddr
17
    host::UInt32
18
    IPv4(host::UInt32) = new(host)
639✔
19
    IPv4(a::UInt8,b::UInt8,c::UInt8,d::UInt8) = new(UInt32(a)<<24|
×
20
                                                    UInt32(b)<<16|
21
                                                    UInt32(c)<<8|
22
                                                    d)
23
    function IPv4(a::Integer,b::Integer,c::Integer,d::Integer)
×
24
        if !(0<=a<=255 && 0<=b<=255 && 0<=c<=255 && 0<=d<=255)
×
25
            throw(ArgumentError("IPv4 field out of range (must be 0-255)"))
×
26
        end
27
        IPv4(UInt8(a),UInt8(b),UInt8(c),UInt8(d))
×
28
    end
29
end
30

31
"""
32
    IPv4(host::Integer) -> IPv4
33

34
Return an IPv4 object from ip address `host` formatted as an [`Integer`](@ref).
35

36
# Examples
37
```jldoctest
38
julia> IPv4(3223256218)
39
ip"192.30.252.154"
40
```
41
"""
42
function IPv4(host::Integer)
39✔
43
    if host < 0
424✔
44
        throw(ArgumentError("IPv4 address must be positive"))
×
45
    elseif typemax(typeof(host)) > typemax(UInt32) && host > typemax(UInt32)
424✔
46
        throw(ArgumentError("IPv4 address must fit within 32 bits"))
×
47
    else
48
        return IPv4(UInt32(host))
424✔
49
    end
50
end
51

52
# constructor: ("1.2.3.4")
53
IPv4(str::AbstractString) = parse(IPv4, str)
111✔
54

55
show(io::IO,ip::IPv4) = print(io,"ip\"",ip,"\"")
×
56
print(io::IO,ip::IPv4) = print(io,string((ip.host&(0xFF000000))>>24),".",
301✔
57
                                  string((ip.host&(0xFF0000))>>16),".",
58
                                  string((ip.host&(0xFF00))>>8),".",
59
                                  string(ip.host&0xFF))
60

61
struct IPv6 <: IPAddr
62
    host::UInt128
63
    IPv6(host::UInt128) = new(host)
41✔
64
    IPv6(a::UInt16,b::UInt16,c::UInt16,d::UInt16,
65
     e::UInt16,f::UInt16,g::UInt16,h::UInt16) = new(UInt128(a)<<(7*16)|
×
66
                            UInt128(b)<<(6*16)|
67
                            UInt128(c)<<(5*16)|
68
                            UInt128(d)<<(4*16)|
69
                            UInt128(e)<<(3*16)|
70
                            UInt128(f)<<(2*16)|
71
                            UInt128(g)<<(1*16)|
72
                            h)
73
    function IPv6(a::Integer,b::Integer,c::Integer,d::Integer,
×
74
          e::Integer,f::Integer,g::Integer,h::Integer)
75
        if !(0<=a<=0xFFFF && 0<=b<=0xFFFF && 0<=c<=0xFFFF && 0<=d<=0xFFFF &&
×
76
             0<=e<=0xFFFF && 0<=f<=0xFFFF && 0<=g<=0xFFFF && 0<=h<=0xFFFF)
77
            throw(ArgumentError("IPv6 field out of range (must be 0-65535)"))
×
78
        end
79
        IPv6(UInt16(a),UInt16(b),UInt16(c),UInt16(d),
×
80
             UInt16(e),UInt16(f),UInt16(g),UInt16(h))
81
    end
82
end
83

84
"""
85
    IPv6(host::Integer) -> IPv6
86

87
Return an IPv6 object from ip address `host` formatted as an [`Integer`](@ref).
88

89
# Examples
90
```jldoctest
91
julia> IPv6(3223256218)
92
ip"::c01e:fc9a"
93
```
94
"""
95
function IPv6(host::Integer)
×
96
    if host < 0
×
97
        throw(ArgumentError("IPv6 address must be positive"))
×
98
        # We allow passing bigger integer types, but need to be careful to avoid overflow
99
        # Let's hope promotion rules are sensible
100
    elseif typemax(typeof(host)) > typemax(UInt128) && host > typemax(UInt128)
×
101
        throw(ArgumentError("IPv6 address must fit within 128 bits"))
×
102
    else
103
        return IPv6(UInt128(host))
×
104
    end
105
end
106

107
IPv6(str::AbstractString) = parse(IPv6, str)
×
108

109
# Suppress leading '0's and "0x"
110
print_ipv6_field(io,field::UInt16) = print(io,string(field, base = 16))
×
111

112
print_ipv6_field(io,ip,i) = print_ipv6_field(io,ipv6_field(ip,i))
×
113
function ipv6_field(ip::IPv6,i)
×
114
    if i < 0 || i > 7
×
115
        throw(BoundsError())
×
116
    end
117
    UInt16((ip.host&(UInt128(0xFFFF)<<(i*16))) >> (i*16))
×
118
end
119

120
show(io::IO, ip::IPv6) = print(io,"ip\"",ip,"\"")
×
121
# RFC 5952 compliant show function
122
# http://tools.ietf.org/html/rfc5952
123
function print(io::IO,ip::IPv6)
×
124
    i = 8
×
125
    m = 0
×
126
    longest_sub_i = -1
×
127
    while i!=0
×
128
        i-=1
×
129
        field = ipv6_field(ip,i)
×
130
        if field == 0 && longest_sub_i == -1
×
131
            # Find longest subsequence of 0
132
            longest_sub_i,j,m,c = i,i,1,1
×
133
            while j != 0
×
134
                j-=1
×
135
                if ipv6_field(ip,j) == 0
×
136
                    c += 1
×
137
                else
138
                    c = 0
×
139
                end
140
                if c > m
×
141
                    if j+c != longest_sub_i+1
×
142
                        longest_sub_i = j+c-1
×
143
                    end
144
                    m = c
×
145
                end
146
            end
×
147
            # Prevent single 0 from contracting to :: as required
148
            if m == 1
×
149
                longest_sub_i = 9
×
150
            end
151
        end
152
        if i == longest_sub_i
×
153
            print(io,":")
×
154
            i -= m-1
×
155
            if i == 0
×
156
                print(io,":")
×
157
                break
×
158
            end
159
        else
160
            if i != 7
×
161
                print(io,":")
×
162
            end
163
            print_ipv6_field(io,field)
×
164
        end
165
    end
×
166
end
167

168
# Parsing
169

170
const ipv4_leading_zero_error = """
171
Leading zeros in IPv4 addresses are disallowed due to ambiguity.
172
If the address is in octal or hexadecimal, convert it to decimal, otherwise remove the leading zero.
173
"""
174

175
function parse(::Type{IPv4}, str::AbstractString)
385✔
176
    fields = split(str,'.')
385✔
177
    i = 1
×
178
    ret = 0
×
179
    for f in fields
385✔
180
        if isempty(f)
1,540✔
181
            throw(ArgumentError("empty field in IPv4 address"))
×
182
        end
183
        if length(f) > 1 && f[1] == '0'
1,540✔
184
            throw(ArgumentError(ipv4_leading_zero_error))
×
185
        else
186
            r = parse(Int, f, base = 10)
1,540✔
187
        end
188
        if i != length(fields)
1,540✔
189
            if r < 0 || r > 255
2,310✔
190
                throw(ArgumentError("IPv4 field out of range (must be 0-255)"))
×
191
            end
192
            ret |= UInt32(r) << ((4-i)*8)
1,155✔
193
        else
194
            if r > ((UInt64(1)<<((5-length(fields))*8))-1)
385✔
195
                throw(ArgumentError("IPv4 field too large"))
×
196
            end
197
            ret |= r
385✔
198
        end
199
        i+=1
1,540✔
200
    end
1,925✔
201
    IPv4(ret)
385✔
202
end
203

204
function parseipv6fields(fields,num_fields)
1✔
205
    if length(fields) > num_fields
1✔
206
        throw(ArgumentError("too many fields in IPv6 address"))
×
207
    end
208
    cf = 7
×
209
    ret = UInt128(0)
×
210
    for f in fields
1✔
211
        if isempty(f)
3✔
212
            # ::abc:... and ..:abc::
213
            if cf != 7 && cf != 0
2✔
214
                cf -= num_fields-length(fields)
1✔
215
            end
216
            cf -= 1
2✔
217
            continue
2✔
218
        end
219
        ret |= UInt128(parse(Int, f, base = 16))<<(cf*16)
1✔
220
        cf -= 1
1✔
221
    end
4✔
222
    ret
1✔
223
end
224
parseipv6fields(fields) = parseipv6fields(fields,8)
1✔
225

226
function parse(::Type{IPv6}, str::AbstractString)
1✔
227
    fields = split(str,':')
1✔
228
    if length(fields) > 8
1✔
229
        throw(ArgumentError("too many fields in IPv6 address"))
×
230
    elseif length(fields) == 8
1✔
231
        return IPv6(parseipv6fields(fields))
×
232
    elseif in('.',fields[end])
1✔
233
        return IPv6((parseipv6fields(fields[1:(end-1)],6))
×
234
            | parse(IPv4, fields[end]).host )
235
    else
236
        return IPv6(parseipv6fields(fields))
1✔
237
    end
238
end
239

240
#
241
# This supports IP addresses in the common dot (IPv4) or colon (IPv6)
242
# separated formats. Most other common formats use a standard integer encoding
243
# of the appropriate size and should use the appropriate constructor
244
#
245

246
function parse(::Type{IPAddr}, str::AbstractString)
288✔
247
    if ':' in str
288✔
248
        return parse(IPv6, str)
1✔
249
    else
250
        return parse(IPv4, str)
287✔
251
    end
252
end
253

254
"""
255
    @ip_str str -> IPAddr
256

257
Parse `str` as an IP address.
258

259
# Examples
260
```jldoctest
261
julia> ip"127.0.0.1"
262
ip"127.0.0.1"
263

264
julia> @ip_str "2001:db8:0:0:0:0:2:1"
265
ip"2001:db8::2:1"
266
```
267
"""
268
macro ip_str(str)
2✔
269
    return parse(IPAddr, str)
2✔
270
end
271

272
struct InetAddr{T<:IPAddr}
273
    host::T
540✔
274
    port::UInt16
275
end
276

277
"""
278
    InetAddr(ip::IPAddr, port) -> InetAddr
279

280
Return an `InetAddr` object from ip address `ip` and port number `port`.
281

282
# Examples
283
```jldoctest
284
julia> Sockets.InetAddr(ip"127.0.0.1", 8000)
285
Sockets.InetAddr{IPv4}(ip"127.0.0.1", 8000)
286
```
287
"""
288
InetAddr(ip::IPAddr, port) = InetAddr{typeof(ip)}(ip, port)
429✔
289

290
"""
291
    InetAddr(str::AbstractString, port) -> InetAddr
292

293
Return an `InetAddr` object from ip address `str` formatted as [`AbstractString`](@ref)
294
and port number `port`.
295

296
!!! compat "Julia 1.3"
297
    This constructor requires at least Julia 1.3.
298

299
# Examples
300
```jldoctest
301
julia> Sockets.InetAddr("127.0.0.1", 8000)
302
Sockets.InetAddr{IPv4}(ip"127.0.0.1", 8000)
303
```
304
"""
305
InetAddr(str::AbstractString, port) = InetAddr(parse(IPAddr, str), port)
×
306

307
function show(io::IO, addr::InetAddr)
×
308
    show(io, typeof(addr))
×
309
    print(io, "(")
×
310
    show(io, addr.host)
×
311
    print(io, ", ", Int(addr.port), ")")
×
312
end
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