2 * Copyright (c) 2015 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.common;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.collect.Interner;
13 import com.google.common.collect.Interners;
14 import com.google.common.primitives.UnsignedLong;
15 import java.io.Serial;
16 import java.math.BigInteger;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.opendaylight.yangtools.concepts.Either;
23 * Dedicated type for YANG's {@code type uint64} type.
26 public class Uint64 extends Number implements CanonicalValue<Uint64> {
27 public static final class Support extends AbstractCanonicalValueSupport<Uint64> {
33 public Either<Uint64, CanonicalValueViolation> fromString(final String str) {
35 return Either.ofFirst(Uint64.valueOf(str));
36 } catch (IllegalArgumentException e) {
37 return CanonicalValueViolation.variantOf(e);
42 private static final CanonicalValueSupport<Uint64> SUPPORT = new Support();
44 private static final long serialVersionUID = 1L;
45 private static final String MAX_VALUE_STR = Long.toUnsignedString(-1);
47 private static final String CACHE_SIZE_PROPERTY = "org.opendaylight.yangtools.yang.common.Uint64.cache.size";
48 private static final int DEFAULT_CACHE_SIZE = 256;
51 * Tunable cache for values. By default it holds {@value #DEFAULT_CACHE_SIZE} entries. This can be
52 * changed via {@value #CACHE_SIZE_PROPERTY} system property.
54 private static final long CACHE_SIZE;
57 final int p = Integer.getInteger(CACHE_SIZE_PROPERTY, DEFAULT_CACHE_SIZE);
58 CACHE_SIZE = p >= 0 ? Math.min(p, Integer.MAX_VALUE) : DEFAULT_CACHE_SIZE;
61 private static final @NonNull Uint64[] CACHE;
64 final Uint64[] c = new Uint64[(int) CACHE_SIZE];
65 for (int i = 0; i < c.length; ++i) {
71 private static final Interner<Uint64> INTERNER = Interners.newWeakInterner();
76 public static final Uint64 ZERO = valueOf(0).intern();
80 public static final Uint64 ONE = valueOf(1).intern();
84 public static final Uint64 TWO = valueOf(2).intern();
86 * Value of {@code 10}.
88 public static final Uint64 TEN = valueOf(10).intern();
90 * Value of {@code 18446744073709551615}.
92 public static final Uint64 MAX_VALUE = fromLongBits(-1).intern();
94 private final long value;
96 private Uint64(final long value) {
100 protected Uint64(final Uint64 other) {
104 private static Uint64 instanceFor(final long value) {
105 return value >= 0 && value < CACHE.length ? CACHE[(int) value] : new Uint64(value);
109 * Returns an {@code Uint64} corresponding to a given bit representation. The argument is interpreted as an
110 * unsigned 64-bit value.
112 * @param bits unsigned bit representation
113 * @return A Uint64 instance
115 public static Uint64 fromLongBits(final long bits) {
116 return instanceFor(bits);
120 * Returns an {@code Uint64} corresponding to a given {@code byteVal}. The inverse operation is
121 * {@link #byteValue()}.
123 * @param byteVal byte value
124 * @return A Uint64 instance
125 * @throws IllegalArgumentException if byteVal is less than zero
127 public static Uint64 valueOf(final byte byteVal) {
128 UintConversions.checkNonNegative(byteVal, MAX_VALUE_STR);
129 return instanceFor(byteVal);
133 * Returns an {@code Uint64} corresponding to a given {@code shortVal}. The inverse operation is
134 * {@link #shortValue()}.
136 * @param shortVal short value
137 * @return A Uint64 instance
138 * @throws IllegalArgumentException if shortVal is less than zero
140 public static Uint64 valueOf(final short shortVal) {
141 UintConversions.checkNonNegative(shortVal, MAX_VALUE_STR);
142 return instanceFor(shortVal);
146 * Returns an {@code Uint64} corresponding to a given {@code intVal}. The inverse operation is {@link #intValue()}.
148 * @param intVal int value
149 * @return A Uint64 instance
150 * @throws IllegalArgumentException if intVal is less than zero
152 public static Uint64 valueOf(final int intVal) {
153 UintConversions.checkNonNegative(intVal, MAX_VALUE_STR);
154 return instanceFor(intVal);
158 * Returns an {@code Uint64} corresponding to a given {@code longVal}, which is checked for range.
159 * See also {@link #longValue()} and {@link #fromLongBits(long)}.
161 * @param longVal long value
162 * @return A Uint8 instance
163 * @throws IllegalArgumentException if longVal is less than zero
165 public static Uint64 valueOf(final long longVal) {
167 return instanceFor(longVal);
169 throw new IllegalArgumentException("Invalid range: " + longVal + ", expected: [[0..18446744073709551615]].");
173 * Returns an {@code Uint64} corresponding to a given {@code uint}.
175 * @param uint Uint8 value
176 * @return A Uint64 instance
177 * @throws NullPointerException if uint is null
179 public static Uint64 valueOf(final Uint8 uint) {
180 return instanceFor(uint.shortValue());
184 * Returns an {@code Uint64} corresponding to a given {@code uint}.
186 * @param uint Uint16 value
187 * @return A Uint64 instance
188 * @throws NullPointerException if uint is null
190 public static Uint64 valueOf(final Uint16 uint) {
191 return instanceFor(uint.intValue());
195 * Returns an {@code Uint64} corresponding to a given {@code uint}.
197 * @param uint Uint32 value
198 * @return A Uint64 instance
199 * @throws NullPointerException if uint is null
201 public static Uint64 valueOf(final Uint32 uint) {
202 return instanceFor(uint.longValue());
206 * Returns an {@code Uint64} corresponding to a given {@code ulong}.
208 * @param ulong UnsignedLong value
209 * @return A Uint64 instance
210 * @throws NullPointerException if ulong is null
212 public static Uint64 valueOf(final UnsignedLong ulong) {
213 return instanceFor(ulong.longValue());
217 * Returns an {@code Uint64} corresponding to a given {@code bigInt}.
219 * @param bigInt BigInteger value
220 * @return A Uint64 instance
221 * @throws NullPointerException if bigInt is null
222 * @throws IllegalArgumentException if bigInt is less than zero or greater than 18446744073709551615
224 public static Uint64 valueOf(final BigInteger bigInt) {
225 if (bigInt.signum() >= 0 && bigInt.bitLength() <= Long.SIZE) {
226 return instanceFor(bigInt.longValue());
228 throw new IllegalArgumentException("Invalid range: " + bigInt + ", expected: [[0..18446744073709551615]].");
232 * Returns an {@code Uint32} holding the value of the specified {@code String}, parsed as an unsigned {@code long}
235 * @param string String to parse
236 * @return A Uint64 instance
237 * @throws NullPointerException if string is null
238 * @throws IllegalArgumentException if the parsed value is less than zero or greater than 18446744073709551615
239 * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long} value.
241 public static Uint64 valueOf(final String string) {
242 return valueOf(string, 10);
246 * Returns an {@code Uint64} holding the value of the specified {@code String}, parsed as an unsigned {@code long}
249 * @param string String to parse
250 * @param radix Radix to use
251 * @return A Uint64 instance
252 * @throws NullPointerException if string is null
253 * @throws IllegalArgumentException if the parsed value is less than zero or greater than 18446744073709551615
254 * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long} value, or if the
255 * {@code radix} is outside of allowed range.
257 public static Uint64 valueOf(final String string, final int radix) {
258 return instanceFor(Long.parseUnsignedLong(requireNonNull(string), radix));
262 * Returns an {@code Uint64} corresponding to a given {@code byteVal} if it is representable. If the value is
263 * negative {@link #ZERO} will be returned.
265 * @param byteVal byte value
266 * @return A Uint64 instance
268 public static Uint64 saturatedOf(final byte byteVal) {
269 return byteVal <= 0 ? Uint64.ZERO : instanceFor(byteVal);
273 * Returns an {@code Uint32} corresponding to a given {@code shortVal} if it is representable. If the value is
274 * negative {@link #ZERO} will be returned.
276 * @param shortVal short value
277 * @return A Uint32 instance
279 public static Uint64 saturatedOf(final short shortVal) {
280 return shortVal <= 0 ? Uint64.ZERO : instanceFor(shortVal);
284 * Returns an {@code Uint64} corresponding to a given {@code intVal} if it is representable. If the value is
285 * negative {@link #ZERO} will be returned.
287 * @param intVal int value
288 * @return A Uint64 instance
290 public static Uint64 saturatedOf(final int intVal) {
291 return intVal <= 0 ? Uint64.ZERO : instanceFor(intVal);
295 * Returns an {@code Uint64} corresponding to a given {@code longVal} if it is representable. If the value is
296 * negative {@link #ZERO} will be returned.
298 * @param longVal long value
299 * @return A Uint64 instance
301 public static Uint64 saturatedOf(final long longVal) {
302 return longVal <= 0 ? Uint64.ZERO : instanceFor(longVal);
306 * Returns an {@code Uint64} corresponding to a given {@code longVal} if it is representable. If the value is
307 * negative {@link #ZERO} will be returned. If the value is greater than 18446744073709551615, {@link #MAX_VALUE}
310 * @param bigInt BigInteger value
311 * @return A Uint64 instance
312 * @throws NullPointerException if bigInt is null
314 public static Uint64 saturatedOf(final BigInteger bigInt) {
315 if (bigInt.signum() <= 0) {
318 return bigInt.bitLength() > Long.SIZE ? Uint64.MAX_VALUE : instanceFor(bigInt.longValue());
322 public final int intValue() {
330 * The inverse operation is {@link #fromLongBits(long)}. In case this value is greater than {@link Long#MAX_VALUE},
331 * the returned value will be equal to {@code this - 2^64}.
334 public final long longValue() {
339 public final float floatValue() {
341 return UnsignedLong.fromLongBits(value).floatValue();
345 public final double doubleValue() {
347 return UnsignedLong.fromLongBits(value).doubleValue();
351 @SuppressWarnings("checkstyle:parameterName")
352 public final int compareTo(final Uint64 o) {
353 return Long.compareUnsigned(value, o.value);
357 public final String toCanonicalString() {
358 return Long.toUnsignedString(value);
362 public final CanonicalValueSupport<Uint64> support() {
367 * Return an interned (shared) instance equivalent to this object. This may return the same object.
369 * @return A shared instance.
371 public final Uint64 intern() {
372 return value >= 0 && value < CACHE_SIZE ? this : INTERNER.intern(this);
376 * Convert this value to a {@link BigInteger}.
378 * @return A BigInteger instance
380 public final BigInteger toJava() {
381 // FIXME: ditch the Guava transition
382 return toGuava().bigIntegerValue();
386 * Convert this value to an {@link UnsignedLong}.
388 * @return An UnsignedLong instance
390 public final UnsignedLong toGuava() {
391 return UnsignedLong.fromLongBits(value);
395 * Convert this value to a {@code Uint8}.
398 * @throws IllegalArgumentException if this value is greater than 255.
400 public final Uint8 toUint8() {
401 if ((value & 0xFFFFFFFFFFFFFF00L) != 0) {
402 throw iae(toString(), 255);
404 return Uint8.fromByteBits((byte) value);
408 * Convert this value to a {@code Uint16}.
411 * @throws IllegalArgumentException if this value is greater than 65535.
413 public final Uint16 toUint16() {
414 if ((value & 0xFFFFFFFFFFFF0000L) != 0) {
415 throw iae(toString(), 65535);
417 return Uint16.fromShortBits((short) value);
421 * Convert this value to a {@code Uint64}.
424 * @throws IllegalArgumentException if this value is greater than 4294967295.
426 public final Uint32 toUint32() {
427 if ((value & 0xFFFFFFFF00000000L) != 0) {
428 throw iae(toString(), 4294967295L);
430 return Uint32.fromIntBits((int) value);
433 static IllegalArgumentException iae(final String value, final long max) {
434 // "Invalid range: 65536, expected: [[0..65535]]."
435 return new IllegalArgumentException("Invalid range: " + value + ", expected: [[0.." + max + "]].");
439 public final int hashCode() {
440 return Long.hashCode(value);
444 public final boolean equals(final @Nullable Object obj) {
445 return this == obj || obj instanceof Uint64 other && value == other.value;
449 * A slightly faster version of {@link #equals(Object)}.
451 * @param obj Uint64 object
452 * @return {@code true} if this object is the same as the obj argument; {@code false} otherwise.
454 public final boolean equals(final @Nullable Uint64 obj) {
455 return this == obj || obj != null && value == obj.value;
459 public final String toString() {
460 return toCanonicalString();
464 private Object readResolve() {
465 return instanceFor(value);