From 953cafd908e3a306001043a6d043120fa18e7bd5 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 28 Sep 2020 18:57:15 +0200 Subject: [PATCH] Add Uint saturated converters There are a number of places where we need to perform a saturated conversion, i.e. when we have a 'long' count and need to put it into a Uint32 field. Add methods to deal with that. JIRA: YANGTOOLS-1135 Change-Id: Ia0bb2e9f0400d975ce1f4b150704dcf526d3bc82 Signed-off-by: Robert Varga (cherry picked from commit 254b2d0b480ae2ddec8b5db9b97cb5fef084d93c) --- .../yangtools/yang/common/Uint16.java | 60 ++++++++++++++++++ .../yangtools/yang/common/Uint32.java | 61 ++++++++++++++++++ .../yangtools/yang/common/Uint64.java | 60 ++++++++++++++++++ .../yangtools/yang/common/Uint8.java | 62 +++++++++++++++++++ .../yangtools/yang/common/Uint16Test.java | 20 ++++++ .../yangtools/yang/common/Uint32Test.java | 19 ++++++ .../yangtools/yang/common/Uint64Test.java | 21 +++++++ .../yangtools/yang/common/Uint8Test.java | 21 +++++++ 8 files changed, 324 insertions(+) diff --git a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint16.java b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint16.java index 491559859d..d9b6ad974b 100644 --- a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint16.java +++ b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint16.java @@ -234,6 +234,62 @@ public class Uint16 extends Number implements CanonicalValue { return valueOf(Integer.parseInt(requireNonNull(string), radix)); } + /** + * Returns an {@code Uint16} corresponding to a given {@code byteVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param byteVal byte value + * @return A Uint16 instance + */ + public static Uint16 saturatedOf(final byte byteVal) { + return byteVal < 0 ? Uint16.ZERO : instanceFor(byteVal); + } + + /** + * Returns an {@code Uint16} corresponding to a given {@code shortVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param shortVal short value + * @return A Uint16 instance + */ + public static Uint16 saturatedOf(final short shortVal) { + return shortVal < 0 ? Uint16.ZERO : instanceFor(shortVal); + } + + /** + * Returns an {@code Uint16} corresponding to a given {@code intVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. If the value is greater than 65535, {@link #MAX_VALUE} will be returned. + * + * @param intVal int value + * @return A Uint16 instance + */ + public static Uint16 saturatedOf(final int intVal) { + if (intVal < 0) { + return Uint16.ZERO; + } + if (intVal >= MAX_VALUE_INT) { + return Uint16.MAX_VALUE; + } + return instanceFor((short) intVal); + } + + /** + * Returns an {@code Uint16} corresponding to a given {@code longVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. If the value is greater than 65535, {@link #MAX_VALUE} will be returned. + * + * @param longVal long value + * @return A Uint16 instance + */ + public static Uint16 saturatedOf(final long longVal) { + if (longVal < 0) { + return Uint16.ZERO; + } + if (longVal >= MAX_VALUE_INT) { + return Uint16.MAX_VALUE; + } + return instanceFor((short) longVal); + } + /** * {@inheritDoc} * @@ -328,6 +384,10 @@ public class Uint16 extends Number implements CanonicalValue { return Uint64.fromLongBits(longValue()); } + public final Uint8 toSaturatedUint8() { + return Uint8.saturatedOf(toJava()); + } + @Override public final int hashCode() { return Short.hashCode(value); diff --git a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint32.java b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint32.java index 6b3b392914..5fa071378d 100644 --- a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint32.java +++ b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint32.java @@ -245,6 +245,57 @@ public class Uint32 extends Number implements CanonicalValue { return instanceFor(Integer.parseUnsignedInt(requireNonNull(string), radix)); } + /** + * Returns an {@code Uint32} corresponding to a given {@code byteVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param byteVal byte value + * @return A Uint32 instance + */ + public static Uint32 saturatedOf(final byte byteVal) { + return byteVal < 0 ? Uint32.ZERO : instanceFor(byteVal); + } + + /** + * Returns an {@code Uint32} corresponding to a given {@code shortVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param shortVal short value + * @return A Uint32 instance + */ + public static Uint32 saturatedOf(final short shortVal) { + return shortVal < 0 ? Uint32.ZERO : instanceFor(shortVal); + } + + /** + * Returns an {@code Uint32} corresponding to a given {@code intVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param intVal int value + * @return A Uint32 instance + */ + public static Uint32 saturatedOf(final int intVal) { + return intVal < 0 ? Uint32.ZERO : instanceFor(intVal); + } + + /** + * Returns an {@code Uint32} corresponding to a given {@code longVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. If the value is greater than 4294967295, {@link #MAX_VALUE} will be + * returned. + * + * @param longVal long value + * @return A Uint32 instance + */ + public static Uint32 saturatedOf(final long longVal) { + if (longVal < 0) { + return Uint32.ZERO; + } + if (longVal >= MAX_VALUE_LONG) { + return Uint32.MAX_VALUE; + } + return instanceFor((int) longVal); + } + /** * {@inheritDoc} * @@ -344,6 +395,16 @@ public class Uint32 extends Number implements CanonicalValue { return Uint64.fromLongBits(longValue()); } + public final Uint8 toSaturatedUint8() { + return Uint8.saturatedOf(toJava()); + } + + public final Uint16 toSaturatedUint16() { + return Uint16.saturatedOf(toJava()); + } + + // FIXME: more saturated conversions + @Override public final int hashCode() { return Integer.hashCode(value); diff --git a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint64.java b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint64.java index 6d537fd009..6ff71de790 100644 --- a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint64.java +++ b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint64.java @@ -260,6 +260,66 @@ public class Uint64 extends Number implements CanonicalValue { return instanceFor(Long.parseUnsignedLong(requireNonNull(string), radix)); } + /** + * Returns an {@code Uint64} corresponding to a given {@code byteVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param byteVal byte value + * @return A Uint64 instance + */ + public static Uint64 saturatedOf(final byte byteVal) { + return byteVal < 0 ? Uint64.ZERO : instanceFor(byteVal); + } + + /** + * Returns an {@code Uint32} corresponding to a given {@code shortVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param shortVal short value + * @return A Uint32 instance + */ + public static Uint64 saturatedOf(final short shortVal) { + return shortVal < 0 ? Uint64.ZERO : instanceFor(shortVal); + } + + /** + * Returns an {@code Uint64} corresponding to a given {@code intVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param intVal int value + * @return A Uint64 instance + */ + public static Uint64 saturatedOf(final int intVal) { + return intVal < 0 ? Uint64.ZERO : instanceFor(intVal); + } + + /** + * Returns an {@code Uint64} corresponding to a given {@code longVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param longVal long value + * @return A Uint64 instance + */ + public static Uint64 saturatedOf(final long longVal) { + return longVal < 0 ? Uint64.ZERO : instanceFor(longVal); + } + + /** + * Returns an {@code Uint64} corresponding to a given {@code longVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. If the value is greater than 18446744073709551615, {@link #MAX_VALUE} + * will be returned. + * + * @param bigInt BigInteger value + * @return A Uint64 instance + * @throws NullPointerException if bigInt is null + */ + public static Uint64 saturatedOf(final BigInteger bigInt) { + if (bigInt.signum() < 0) { + return Uint64.ZERO; + } + return bigInt.bitLength() > Long.SIZE ? Uint64.MAX_VALUE : instanceFor(bigInt.longValue()); + } + @Override public final int intValue() { return (int)value; diff --git a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint8.java b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint8.java index 99548c3327..7766d5e4cc 100644 --- a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint8.java +++ b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/Uint8.java @@ -217,6 +217,68 @@ public class Uint8 extends Number implements CanonicalValue { return valueOf(Short.parseShort(requireNonNull(string), radix)); } + /** + * Returns an {@code Uint8} corresponding to a given {@code byteVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. + * + * @param byteVal byte value + * @return A Uint8 instance + */ + public static Uint8 saturatedOf(final byte byteVal) { + return byteVal < 0 ? Uint8.ZERO : instanceFor(byteVal); + } + + /** + * Returns an {@code Uint8} corresponding to a given {@code shortVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. If the value is greater than 255, {@link #MAX_VALUE} will be returned. + * + * @param shortVal short value + * @return A Uint8 instance + */ + public static Uint8 saturatedOf(final short shortVal) { + if (shortVal < 0) { + return Uint8.ZERO; + } + if (shortVal >= MAX_VALUE_SHORT) { + return Uint8.MAX_VALUE; + } + return instanceFor((byte) shortVal); + } + + /** + * Returns an {@code Uint8} corresponding to a given {@code intVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. If the value is greater than 255, {@link #MAX_VALUE} will be returned. + * + * @param intVal int value + * @return A Uint8 instance + */ + public static Uint8 saturatedOf(final int intVal) { + if (intVal < 0) { + return Uint8.ZERO; + } + if (intVal >= MAX_VALUE_SHORT) { + return Uint8.MAX_VALUE; + } + return instanceFor((byte) intVal); + } + + /** + * Returns an {@code Uint8} corresponding to a given {@code longVal} if it is representable. If the value is + * negative {@link #ZERO} will be returned. If the value is greater than 255, {@link #MAX_VALUE} will be returned. + * + * @param longVal long value + * @return A Uint8 instance + */ + public static Uint8 saturatedOf(final long longVal) { + if (longVal < 0) { + return Uint8.ZERO; + } + if (longVal >= MAX_VALUE_SHORT) { + return Uint8.MAX_VALUE; + } + return instanceFor((byte) longVal); + } + /** * {@inheritDoc} * diff --git a/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint16Test.java b/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint16Test.java index 17f7ec2976..fc9f7a59fc 100644 --- a/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint16Test.java +++ b/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint16Test.java @@ -33,6 +33,18 @@ public class Uint16Test { assertEquals(0, Uint16.valueOf("0").intValue()); } + @Test + public void testSaturatedOf() { + assertEquals(127, Uint16.saturatedOf((byte) 127).byteValue()); + assertEquals(127, Uint16.saturatedOf((short) 127).byteValue()); + assertEquals(127, Uint16.saturatedOf(127).byteValue()); + assertEquals(127, Uint16.saturatedOf(127L).byteValue()); + + assertEquals(255, Uint16.saturatedOf((short) 255).intValue()); + assertEquals(255, Uint16.saturatedOf(255).intValue()); + assertEquals(255L, Uint16.saturatedOf(255L).longValue()); + } + @Test public void testCompareTo() { final Uint16 five = Uint16.valueOf(5); @@ -128,12 +140,20 @@ public class Uint16Test { assertThrows(IllegalArgumentException.class, () -> Uint16.valueOf((short)-1)); assertThrows(IllegalArgumentException.class, () -> Uint16.valueOf(-1)); assertThrows(IllegalArgumentException.class, () -> Uint16.valueOf(-1L)); + + assertEquals(Uint16.ZERO, Uint16.saturatedOf((byte)-1)); + assertEquals(Uint16.ZERO, Uint16.saturatedOf((short)-1)); + assertEquals(Uint16.ZERO, Uint16.saturatedOf(-1)); + assertEquals(Uint16.ZERO, Uint16.saturatedOf(-1L)); } @Test public void testLargeValues() { assertThrows(IllegalArgumentException.class, () -> Uint16.valueOf(65536)); assertThrows(IllegalArgumentException.class, () -> Uint16.valueOf(65536L)); + + assertEquals(Uint16.MAX_VALUE, Uint16.saturatedOf(65536)); + assertEquals(Uint16.MAX_VALUE, Uint16.saturatedOf(65536L)); } @Test diff --git a/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint32Test.java b/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint32Test.java index b1a122647a..1eb936886c 100644 --- a/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint32Test.java +++ b/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint32Test.java @@ -31,6 +31,18 @@ public class Uint32Test { assertEquals(0, Uint32.valueOf("0").intValue()); } + @Test + public void testSaturatedOf() { + assertEquals(127, Uint32.saturatedOf((byte) 127).byteValue()); + assertEquals(127, Uint32.saturatedOf((short) 127).byteValue()); + assertEquals(127, Uint32.saturatedOf(127).byteValue()); + assertEquals(127, Uint32.saturatedOf(127L).byteValue()); + + assertEquals(255, Uint32.saturatedOf((short) 255).intValue()); + assertEquals(255, Uint32.saturatedOf(255).intValue()); + assertEquals(255L, Uint32.saturatedOf(255L).longValue()); + } + @Test public void testCompareTo() { final Uint32 five = Uint32.valueOf(5); @@ -134,11 +146,18 @@ public class Uint32Test { assertThrows(IllegalArgumentException.class, () -> Uint32.valueOf((short)-1)); assertThrows(IllegalArgumentException.class, () -> Uint32.valueOf(-1)); assertThrows(IllegalArgumentException.class, () -> Uint32.valueOf(-1L)); + + assertEquals(Uint32.ZERO, Uint32.saturatedOf((byte)-1)); + assertEquals(Uint32.ZERO, Uint32.saturatedOf((short)-1)); + assertEquals(Uint32.ZERO, Uint32.saturatedOf(-1)); + assertEquals(Uint32.ZERO, Uint32.saturatedOf(-1L)); } @Test public void testLargeValues() { assertThrows(IllegalArgumentException.class, () -> Uint32.valueOf(4294967296L)); + + assertEquals(Uint32.MAX_VALUE, Uint32.saturatedOf(4294967296L)); } @Test diff --git a/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint64Test.java b/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint64Test.java index 521eb33690..cc79d621c0 100644 --- a/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint64Test.java +++ b/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint64Test.java @@ -34,6 +34,19 @@ public class Uint64Test { assertEquals(2170205184637009920L, Uint64.valueOf(new BigInteger("2170205184637009920")).longValue()); } + @Test + public void testSaturatedOf() { + assertEquals(127, Uint64.saturatedOf((byte) 127).byteValue()); + assertEquals(127, Uint64.saturatedOf((short) 127).byteValue()); + assertEquals(127, Uint64.saturatedOf(127).byteValue()); + assertEquals(127, Uint64.saturatedOf(127L).byteValue()); + + assertEquals(255, Uint64.saturatedOf((short) 255).intValue()); + assertEquals(255, Uint64.saturatedOf(255).intValue()); + assertEquals(255L, Uint64.saturatedOf(255L).longValue()); + assertEquals(2170205184637009920L, Uint64.saturatedOf(new BigInteger("2170205184637009920")).longValue()); + } + @Test public void testCompareTo() { final Uint64 five = Uint64.valueOf(5); @@ -144,12 +157,20 @@ public class Uint64Test { assertThrows(IllegalArgumentException.class, () -> Uint64.valueOf(-1)); assertThrows(IllegalArgumentException.class, () -> Uint64.valueOf(-1L)); assertThrows(IllegalArgumentException.class, () -> Uint64.valueOf(new BigInteger("-1"))); + + assertEquals(Uint64.ZERO, Uint64.saturatedOf((byte)-1)); + assertEquals(Uint64.ZERO, Uint64.saturatedOf((short)-1)); + assertEquals(Uint64.ZERO, Uint64.saturatedOf(-1)); + assertEquals(Uint64.ZERO, Uint64.saturatedOf(-1L)); + assertEquals(Uint64.ZERO, Uint64.saturatedOf(new BigInteger("-1"))); } @Test public void testLargeValues() { final BigInteger big = new BigInteger("10000000000000000", 16); assertThrows(IllegalArgumentException.class, () -> Uint64.valueOf(big)); + + assertEquals(Uint64.MAX_VALUE, Uint64.saturatedOf(big)); } @Test diff --git a/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint8Test.java b/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint8Test.java index 83c516ceea..2e316d1a03 100644 --- a/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint8Test.java +++ b/yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/Uint8Test.java @@ -29,6 +29,18 @@ public class Uint8Test { assertEquals(0, Uint8.valueOf("0").intValue()); } + @Test + public void testSaturatedOf() { + assertEquals(127, Uint8.saturatedOf((byte) 127).byteValue()); + assertEquals(127, Uint8.saturatedOf((short) 127).byteValue()); + assertEquals(127, Uint8.saturatedOf(127).byteValue()); + assertEquals(127, Uint8.saturatedOf(127L).byteValue()); + + assertEquals(255, Uint8.saturatedOf((short) 255).intValue()); + assertEquals(255, Uint8.saturatedOf(255).intValue()); + assertEquals(255L, Uint8.saturatedOf(255L).longValue()); + } + @Test public void testCompareTo() { final Uint8 five = Uint8.valueOf(5); @@ -119,6 +131,11 @@ public class Uint8Test { assertThrows(IllegalArgumentException.class, () -> Uint8.valueOf((short)-1)); assertThrows(IllegalArgumentException.class, () -> Uint8.valueOf(-1)); assertThrows(IllegalArgumentException.class, () -> Uint8.valueOf(-1L)); + + assertEquals(Uint8.ZERO, Uint8.saturatedOf((byte)-1)); + assertEquals(Uint8.ZERO, Uint8.saturatedOf((short)-1)); + assertEquals(Uint8.ZERO, Uint8.saturatedOf(-1)); + assertEquals(Uint8.ZERO, Uint8.saturatedOf(-1L)); } @Test @@ -126,6 +143,10 @@ public class Uint8Test { assertThrows(IllegalArgumentException.class, () -> Uint8.valueOf((short)256)); assertThrows(IllegalArgumentException.class, () -> Uint8.valueOf(256)); assertThrows(IllegalArgumentException.class, () -> Uint8.valueOf(256L)); + + assertEquals(Uint8.MAX_VALUE, Uint8.saturatedOf(Short.MAX_VALUE)); + assertEquals(Uint8.MAX_VALUE, Uint8.saturatedOf(Integer.MAX_VALUE)); + assertEquals(Uint8.MAX_VALUE, Uint8.saturatedOf(Long.MAX_VALUE)); } @Test -- 2.36.6