|
|
|
@ -12,6 +12,7 @@ import org.session.libsignal.utilities.ThreadUtils
|
|
|
|
|
import java.io.DataInputStream
|
|
|
|
|
import java.io.InputStream
|
|
|
|
|
import java.io.InputStreamReader
|
|
|
|
|
import kotlin.math.absoluteValue
|
|
|
|
|
|
|
|
|
|
private fun ipv4Int(ip: String): UInt =
|
|
|
|
|
ip.split(".", "/", ",").take(4).fold(0U) { acc, s -> acc shl 8 or s.toUInt() }
|
|
|
|
@ -91,8 +92,8 @@ class IP2Country internal constructor(
|
|
|
|
|
countryNamesCache[ip]?.let { return it }
|
|
|
|
|
|
|
|
|
|
val ipInt = ipv4Int(ip)
|
|
|
|
|
val index = ips.fuzzyBinarySearch(ipInt)
|
|
|
|
|
val code = index?.let { codes[it] }
|
|
|
|
|
val index = ips.binarySearch(ipInt).let { it.takeIf { it >= 0 } ?: (it.absoluteValue - 2) }
|
|
|
|
|
val code = codes.getOrNull(index)
|
|
|
|
|
val bestMatchCountry = countryToNames[code]
|
|
|
|
|
|
|
|
|
|
if (bestMatchCountry != null) countryNamesCache[ip] = bestMatchCountry
|
|
|
|
@ -115,25 +116,3 @@ class IP2Country internal constructor(
|
|
|
|
|
}
|
|
|
|
|
// endregion
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@OptIn(ExperimentalUnsignedTypes::class)
|
|
|
|
|
private fun UIntArray.fuzzyBinarySearch(target: UInt): Int? {
|
|
|
|
|
if (isEmpty()) return null
|
|
|
|
|
|
|
|
|
|
var low = 0
|
|
|
|
|
var high = size - 1
|
|
|
|
|
|
|
|
|
|
while (low <= high) {
|
|
|
|
|
val mid = (low + high) / 2
|
|
|
|
|
val midValue = this[mid]
|
|
|
|
|
|
|
|
|
|
when {
|
|
|
|
|
midValue == target -> return mid // Exact match found
|
|
|
|
|
midValue < target -> low = mid + 1 // Search in the right half
|
|
|
|
|
else -> high = mid - 1 // Search in the left half
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If no exact match, return the largest index with value <= target
|
|
|
|
|
return if (high >= 0) high else null
|
|
|
|
|
}
|
|
|
|
|