blob: 8eb7414933a54eedf2797ba4f8408539076df10c (
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<UByte>
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<UByte>
if (this.is4) {
bytes = split4.map { it.toUByte(10) }
} else {
val shorts = split6.map { it.toShort(16) }
bytes = shorts.flatMap {
listOf(
it.toInt().and(0xFF00).shr(0x08).toUByte(),
it.toInt().and(0x00FF).toUByte()
)
}
}
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
}
}
|