diff --git a/binding/java/src/main/java/org/lionsoul/ip2region/DbSearcher.java b/binding/java/src/main/java/org/lionsoul/ip2region/DbSearcher.java index 5bc8e8f..b7721ef 100644 --- a/binding/java/src/main/java/org/lionsoul/ip2region/DbSearcher.java +++ b/binding/java/src/main/java/org/lionsoul/ip2region/DbSearcher.java @@ -82,7 +82,7 @@ public class DbSearcher int l = 0, h = totalIndexBlocks; long sip, eip, dataptr = 0; while ( l <= h ) { - int m = (l + h) >> 1; + int m = Util.mean(l, h); int p = (int)(firstIndexPtr + m * blen); sip = Util.getIntLong(dbBinStr, p); @@ -194,7 +194,7 @@ public class DbSearcher int l = 0, h = headerLength, sptr = 0, eptr = 0; while ( l <= h ) { - int m = (l + h) >> 1; + int m = Util.mean(l, h); //perfetc matched, just return it if ( ip == HeaderSip[m] ) { @@ -247,7 +247,7 @@ public class DbSearcher l = 0; h = blockLen / blen; long sip, eip, dataptr = 0; while ( l <= h ) { - int m = (l + h) >> 1; + int m = Util.mean(l, h); int p = m * blen; sip = Util.getIntLong(iBuffer, p); if ( ip < sip ) { @@ -316,7 +316,7 @@ public class DbSearcher byte[] buffer = new byte[blen]; long sip, eip, dataptr = 0; while ( l <= h ) { - int m = (l + h) >> 1; + int m = Util.mean(l, h); raf.seek(firstIndexPtr + m * blen); //set the file pointer raf.readFully(buffer, 0, buffer.length); sip = Util.getIntLong(buffer, 0); diff --git a/binding/java/src/main/java/org/lionsoul/ip2region/Util.java b/binding/java/src/main/java/org/lionsoul/ip2region/Util.java index f94d3ee..0044e18 100644 --- a/binding/java/src/main/java/org/lionsoul/ip2region/Util.java +++ b/binding/java/src/main/java/org/lionsoul/ip2region/Util.java @@ -140,4 +140,19 @@ public class Util return true; } + + /** + * Returns the arithmetic mean of {@code x} and {@code y}, rounded towards + * negative infinity. This method is overflow resilient. + * + * code from guava 14.0 + * com.google.common.math.IntMath.mean(int x, int y) + * + */ + public static int mean(int x, int y) { + // Efficient method for computing the arithmetic mean. + // The alternative (x + y) / 2 fails for large values. + // The alternative (x + y) >>> 1 fails for negative values. + return (x & y) + ((x ^ y) >> 1); + } }