Skip to content

Commit ca5fa52

Browse files
committed
Fix some edge cases and simplifly code
1 parent 431723a commit ca5fa52

File tree

4 files changed

+197
-494
lines changed

4 files changed

+197
-494
lines changed

src/main/kotlin/CdirAddress.kt

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import java.net.InetAddress
19+
import java.net.UnknownHostException
20+
import kotlin.math.floor
21+
import kotlin.math.ln
22+
import kotlin.math.pow
23+
24+
25+
inline class CdirAddress(val cdir: String) {
26+
override fun toString(): String {
27+
return "$cdir (${this.startAddress()?.hostAddress}...${this.endAddress()?.hostAddress})"
28+
}
29+
}
30+
31+
internal fun CdirAddress.addressCount(): Long {
32+
return inet2long(endAddress()) - inet2long(startAddress()) + 1
33+
}
34+
35+
private fun CdirAddress.inetAddress(): InetAddress {
36+
return InetAddress.getByName(cdir.substringBefore("/"))
37+
}
38+
39+
internal fun CdirAddress.prefix(): Int {
40+
return cdir.substringAfter("/").toInt()
41+
}
42+
43+
internal fun CdirAddress.startAddress(): InetAddress? {
44+
return long2inet(inet2long(this.inetAddress()) and prefix2mask(this.prefix()))
45+
}
46+
47+
internal fun CdirAddress.endAddress(): InetAddress? {
48+
return long2inet((inet2long(this.inetAddress()) and prefix2mask(this.prefix())) + (1L shl(32 - this.prefix())) - 1)
49+
}
50+
51+
internal fun CdirAddress.merge(other: CdirAddress): List<CdirAddress> {
52+
val end = this.endAddress()!!.toLong().coerceAtLeast(other.endAddress()!!.toLong()).toInetAddress()!!
53+
return toCdirAddresses(this.startAddress()!!, end)
54+
}
55+
56+
internal fun InetAddress.plus(value: Int): InetAddress? {
57+
return long2inet(inet2long(this) + value)
58+
}
59+
60+
internal fun InetAddress.minus(value: Int): InetAddress? {
61+
return long2inet(inet2long(this) - value)
62+
}
63+
64+
private fun prefix2mask(bits: Int): Long {
65+
return -0x100000000L shr bits and 0xFFFFFFFFL
66+
}
67+
68+
internal fun InetAddress.toLong(): Long {
69+
return inet2long(this)
70+
}
71+
72+
internal fun Long.toInetAddress(): InetAddress? {
73+
return long2inet(this)
74+
}
75+
76+
private fun inet2long(addr: InetAddress?): Long {
77+
var result: Long = 0
78+
if (addr != null) {
79+
for (b in addr.address) {
80+
result = (result shl 8) or (b.toLong() and 0xFF)
81+
}
82+
}
83+
return result
84+
}
85+
86+
87+
fun toCdirAddresses(start: InetAddress, end: InetAddress): List<CdirAddress> {
88+
val listResult: MutableList<CdirAddress> = ArrayList()
89+
// echo("toCdirAddress(" + start.hostAddress + "," + end.hostAddress + ")")
90+
91+
var from = inet2long(start)
92+
val to = inet2long(end)
93+
94+
while (to >= from) {
95+
var prefix: Byte = 32
96+
while (prefix > 0) {
97+
val mask = prefix2mask(prefix - 1)
98+
if (from and mask != from) break
99+
prefix--
100+
}
101+
val max = (32 - floor(ln((to - from + 1).toDouble()) / ln(2.0))).toByte()
102+
if (prefix < max) prefix = max
103+
listResult.add(CdirAddress("${long2inet(from)?.hostAddress}/$prefix"))
104+
from += 2.0.pow((32 - prefix).toDouble()).toLong()
105+
}
106+
107+
return listResult
108+
}
109+
110+
@Suppress("NAME_SHADOWING")
111+
private fun long2inet(addr: Long): InetAddress? {
112+
var addr = addr
113+
return try {
114+
val b = ByteArray(4)
115+
for (i in b.indices.reversed()) {
116+
b[i] = (addr and 0xFF).toByte()
117+
addr = addr shr 8
118+
}
119+
InetAddress.getByAddress(b)
120+
} catch (ignore: UnknownHostException) {
121+
null
122+
}
123+
}

0 commit comments

Comments
 (0)