ICU-20901 VersionInfo.compareTo() compare signed version int as unsigned
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/VersionInfo.java b/icu4j/main/classes/core/src/com/ibm/icu/util/VersionInfo.java
index 7e11f45..72fd079 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/VersionInfo.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/VersionInfo.java
@@ -471,7 +471,15 @@
@Override
public int compareTo(VersionInfo other)
{
- return m_version_ - other.m_version_;
+ // m_version_ is an int, a signed 32-bit integer.
+ // When the major version is >=128, then the version int is negative.
+ // Compare it in two steps to simulate an unsigned-int comparison.
+ // (Alternatively we could turn each int into a long and reset the upper 32 bits.)
+ // Compare the upper bits first, using logical shift right (unsigned).
+ int diff = (m_version_ >>> 1) - (other.m_version_ >>> 1);
+ if (diff != 0) { return diff; }
+ // Compare the remaining bits.
+ return (m_version_ & 1) - (other.m_version_ & 1);
}
// private data members ----------------------------------------------
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/VersionInfoTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/VersionInfoTest.java
index dcfe199..1577793 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/VersionInfoTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/VersionInfoTest.java
@@ -138,6 +138,18 @@
}
}
+ @Test
+ public void TestCompareLarge() {
+ // One version with major<128, one >=128.
+ VersionInfo small = VersionInfo.getInstance(13);
+ VersionInfo large = VersionInfo.getInstance(222); // >=128
+ assertTrue(small + " < " + large, small.compareTo(large) < 0);
+ // Difference only in the last bit.
+ small = VersionInfo.getInstance(222, 0, 1, 2);
+ large = VersionInfo.getInstance(222, 0, 1, 3);
+ assertTrue(small + " < " + large, small.compareTo(large) < 0);
+ }
+
/**
* Test that the getter function works
*/