blob: 58d0aaed21da83ee8d7bbada29bb79c448d9844d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
/**
* An IP address (v4 or v6).
*/
class IPAddress {
private var address: Array<Byte>
private var is4: Boolean
/**
* @throws NumberFormatException if the IP address follows neither the IPv4 syntax, nor the IPv6 syntax.
*/
constructor(address: String) {
if (isAddressV4(address)) {
this.is4 = true
} else if (isAddressV6(address)) {
this.is4 = false
} else {
throw NumberFormatException()
}
val split4 = address.split('.')
val split6 = address.split(':')
val bytes: List<Byte>
if (this.is4) {
bytes = split4.map { it.toByte(10) }
} else {
val shorts = split6.map { it.toShort(16) }
bytes = shorts.flatMap {
listOf(
it.toInt().shr(8).toByte(),
it.toInt().and(0x00FF).toByte()
)
}
}
this.address = bytes.toTypedArray()
}
private fun isAddressV4(address: String): Boolean {
val split4 = address.split('.')
var isOK = split4.size == 4
isOK = isOK && split4.size == split4.filter { it.matches(Regex("^[0-9]+$")) }.size
return isOK
}
private fun isAddressV6(address: String): Boolean {
val split6 = address.split(':')
var isOK = split6.size == 8
isOK = isOK && split6.size == split6.filter { it.contains(Regex("^[0-9][a-f]+$")) }.size
if (isOK) {
return true
}
// try with "::"
val split6Double = address.split("::")
if (split6Double.size != 2) {
return false
}
val omitted = 8 - split6Double[0].split(':').size - split6Double[1].split(':').size
if (omitted < 0) {
return false
}
return true
}
override fun toString(): String {
val str: String
if (this.is4) {
str = this.address.joinToString(separator = ".") { it.toString() }
} else {
str = this.address.joinToString(separator = ":") { it.toString() }
}
return str
}
}
|