diff options
author | Edoardo La Greca | 2025-08-18 21:09:11 +0200 |
---|---|---|
committer | Edoardo La Greca | 2025-08-18 21:09:11 +0200 |
commit | 7341ead2aade10ea1b833e94275277658741883a (patch) | |
tree | 46495f24c54278d50aa0da5046822fbe502f3f14 /lib/src/main/kotlin/IPAddress.kt | |
parent | 1e50cf9c224d03896f176f3718ff80ef1659e9c2 (diff) |
switch to multi-module project structure
Diffstat (limited to 'lib/src/main/kotlin/IPAddress.kt')
-rw-r--r-- | lib/src/main/kotlin/IPAddress.kt | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/lib/src/main/kotlin/IPAddress.kt b/lib/src/main/kotlin/IPAddress.kt new file mode 100644 index 0000000..8eb7414 --- /dev/null +++ b/lib/src/main/kotlin/IPAddress.kt @@ -0,0 +1,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 + } +}
\ No newline at end of file |