summaryrefslogtreecommitdiff
path: root/lib/src/main/kotlin/IPAddress.kt
diff options
context:
space:
mode:
Diffstat (limited to 'lib/src/main/kotlin/IPAddress.kt')
-rw-r--r--lib/src/main/kotlin/IPAddress.kt73
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