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.annotations.Beta;
13 import com.google.common.collect.Interner;
14 import com.google.common.collect.Interners;
15 import com.google.common.primitives.UnsignedLong;
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.Variant;
23 * Dedicated type for YANG's 'type uint64' type.
25 * @author Robert Varga
29 public class Uint64 extends Number implements CanonicalValue<Uint64> {
30 public static final class Support extends AbstractCanonicalValueSupport<Uint64> {
36 public Variant<Uint64, CanonicalValueViolation> fromString(final String str) {
38 return Variant.ofFirst(Uint64.valueOf(str));
39 } catch (IllegalArgumentException e) {
40 return CanonicalValueViolation.variantOf(e);
45 private static final CanonicalValueSupport<Uint64> SUPPORT = new Support();
46 private static final long serialVersionUID = 1L;
47 private static final String MAX_VALUE_STR = Long.toUnsignedString(-1);
49 private static final String CACHE_SIZE_PROPERTY = "org.opendaylight.yangtools.yang.common.Uint64.cache.size";
50 private static final int DEFAULT_CACHE_SIZE = 256;
53 * Tunable cache for values. By default it holds {@value #DEFAULT_CACHE_SIZE} entries. This can be
54 * changed via {@value #CACHE_SIZE_PROPERTY} system property.
56 private static final long CACHE_SIZE;
59 final int p = Integer.getInteger(CACHE_SIZE_PROPERTY, DEFAULT_CACHE_SIZE);
60 CACHE_SIZE = p >= 0 ? Math.min(p, Integer.MAX_VALUE) : DEFAULT_CACHE_SIZE;
63 private static final @NonNull Uint64[] CACHE;
66 final Uint64[] c = new Uint64[(int) CACHE_SIZE];
67 for (int i = 0; i < c.length; ++i) {
73 private static final Interner<Uint64> INTERNER = Interners.newWeakInterner();
78 public static final Uint64 ZERO = valueOf(0).intern();
82 public static final Uint64 ONE = valueOf(1).intern();
86 public static final Uint64 TWO = valueOf(2).intern();
88 * Value of {@code 10}.
90 public static final Uint64 TEN = valueOf(10).intern();
92 * Value of {@code 18446744073709551615}.
94 public static final Uint64 MAX_VALUE = fromLongBits(-1).intern();
96 private final long value;
98 private Uint64(final long value) {
102 protected Uint64(final Uint64 other) {
106 private static Uint64 instanceFor(final long value) {
107 return value >= 0 && value < CACHE.length ? CACHE[(int) value] : new Uint64(value);
111 * Returns an {@code Uint64} corresponding to a given bit representation. The argument is interpreted as an
112 * unsigned 64-bit value.
114 * @param bits unsigned bit representation
115 * @return A Uint64 instance
117 public static Uint64 fromLongBits(final long bits) {
118 return instanceFor(bits);
122 * Returns an {@code Uint64} corresponding to a given {@code byteVal}. The inverse operation is
123 * {@link #byteValue()}.
125 * @param byteVal byte value
126 * @return A Uint64 instance
127 * @throws IllegalArgumentException if byteVal is less than zero
129 public static Uint64 valueOf(final byte byteVal) {
130 UintConversions.checkNonNegative(byteVal, MAX_VALUE_STR);
131 return instanceFor(byteVal);
135 * Returns an {@code Uint64} corresponding to a given {@code shortVal}. The inverse operation is
136 * {@link #shortValue()}.
138 * @param shortVal short value
139 * @return A Uint64 instance
140 * @throws IllegalArgumentException if shortVal is less than zero
142 public static Uint64 valueOf(final short shortVal) {
143 UintConversions.checkNonNegative(shortVal, MAX_VALUE_STR);
144 return instanceFor(shortVal);
148 * Returns an {@code Uint64} corresponding to a given {@code intVal}. The inverse operation is {@link #intValue()}.
150 * @param intVal int value
151 * @return A Uint64 instance
152 * @throws IllegalArgumentException if intVal is less than zero
154 public static Uint64 valueOf(final int intVal) {
155 UintConversions.checkNonNegative(intVal, MAX_VALUE_STR);
156 return instanceFor(intVal);
160 * Returns an {@code Uint64} corresponding to a given {@code longVal}, which is checked for range.
161 * See also {@link #longValue()} and {@link #fromLongBits(long)}.
163 * @param longVal long value
164 * @return A Uint8 instance
165 * @throws IllegalArgumentException if longVal is less than zero
167 public static Uint64 valueOf(final long longVal) {
169 return instanceFor(longVal);
171 throw new IllegalArgumentException("Invalid range: " + longVal + ", expected: [[0..18446744073709551615]].");
175 * Returns an {@code Uint64} corresponding to a given {@code uint}.
177 * @param uint Uint8 value
178 * @return A Uint64 instance
179 * @throws NullPointerException if uint is null
181 public static Uint64 valueOf(final Uint8 uint) {
182 return instanceFor(uint.shortValue());
186 * Returns an {@code Uint64} corresponding to a given {@code uint}.
188 * @param uint Uint16 value
189 * @return A Uint64 instance
190 * @throws NullPointerException if uint is null
192 public static Uint64 valueOf(final Uint16 uint) {
193 return instanceFor(uint.intValue());
197 * Returns an {@code Uint64} corresponding to a given {@code uint}.
199 * @param uint Uint32 value
200 * @return A Uint64 instance
201 * @throws NullPointerException if uint is null
203 public static Uint64 valueOf(final Uint32 uint) {
204 return instanceFor(uint.longValue());
208 * Returns an {@code Uint64} corresponding to a given {@code ulong}.
210 * @param ulong UnsignedLong value
211 * @return A Uint64 instance
212 * @throws NullPointerException if ulong is null
214 public static Uint64 valueOf(final UnsignedLong ulong) {
215 return instanceFor(ulong.longValue());
219 * Returns an {@code Uint64} corresponding to a given {@code bigInt}.
221 * @param bigInt BigInteger value
222 * @return A Uint64 instance
223 * @throws NullPointerException if bigInt is null
224 * @throws IllegalArgumentException if bigInt is less than zero or greater than 18446744073709551615
226 public static Uint64 valueOf(final BigInteger bigInt) {
227 if (bigInt.signum() >= 0 && bigInt.bitLength() <= Long.SIZE) {
228 return instanceFor(bigInt.longValue());
230 throw new IllegalArgumentException("Invalid range: " + bigInt + ", expected: [[0..18446744073709551615]].");
234 * Returns an {@code Uint32} holding the value of the specified {@code String}, parsed as an unsigned {@code long}
237 * @param string String to parse
238 * @return A Uint64 instance
239 * @throws NullPointerException if string is null
240 * @throws IllegalArgumentException if the parsed value is less than zero or greater than 18446744073709551615
241 * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long} value.
243 public static Uint64 valueOf(final String string) {
244 return valueOf(string, 10);
248 * Returns an {@code Uint64} holding the value of the specified {@code String}, parsed as an unsigned {@code long}
251 * @param string String to parse
252 * @param radix Radix to use
253 * @return A Uint64 instance
254 * @throws NullPointerException if string is null
255 * @throws IllegalArgumentException if the parsed value is less than zero or greater than 18446744073709551615
256 * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long} value, or if the
257 * {@code radix} is outside of allowed range.
259 public static Uint64 valueOf(final String string, final int radix) {
260 return instanceFor(Long.parseUnsignedLong(requireNonNull(string), radix));
264 * Returns an {@code Uint64} corresponding to a given {@code byteVal} if it is representable. If the value is
265 * negative {@link #ZERO} will be returned.
267 * @param byteVal byte value
268 * @return A Uint64 instance
270 public static Uint64 saturatedOf(final byte byteVal) {
271 return byteVal < 0 ? Uint64.ZERO : instanceFor(byteVal);
275 * Returns an {@code Uint32} corresponding to a given {@code shortVal} if it is representable. If the value is
276 * negative {@link #ZERO} will be returned.
278 * @param shortVal short value
279 * @return A Uint32 instance
281 public static Uint64 saturatedOf(final short shortVal) {
282 return shortVal < 0 ? Uint64.ZERO : instanceFor(shortVal);
286 * Returns an {@code Uint64} corresponding to a given {@code intVal} if it is representable. If the value is
287 * negative {@link #ZERO} will be returned.
289 * @param intVal int value
290 * @return A Uint64 instance
292 public static Uint64 saturatedOf(final int intVal) {
293 return intVal < 0 ? Uint64.ZERO : instanceFor(intVal);
297 * Returns an {@code Uint64} corresponding to a given {@code longVal} if it is representable. If the value is
298 * negative {@link #ZERO} will be returned.
300 * @param longVal long value
301 * @return A Uint64 instance
303 public static Uint64 saturatedOf(final long longVal) {
304 return longVal < 0 ? Uint64.ZERO : instanceFor(longVal);
308 * Returns an {@code Uint64} corresponding to a given {@code longVal} if it is representable. If the value is
309 * negative {@link #ZERO} will be returned. If the value is greater than 18446744073709551615, {@link #MAX_VALUE}
312 * @param bigInt BigInteger value
313 * @return A Uint64 instance
314 * @throws NullPointerException if bigInt is null
316 public static Uint64 saturatedOf(final BigInteger bigInt) {
317 if (bigInt.signum() < 0) {
320 return bigInt.bitLength() > Long.SIZE ? Uint64.MAX_VALUE : instanceFor(bigInt.longValue());
324 public final int intValue() {
332 * The inverse operation is {@link #fromLongBits(long)}. In case this value is greater than {@link Long#MAX_VALUE},
333 * the returned value will be equal to {@code this - 2^64}.
336 public final long longValue() {
341 public final float floatValue() {
343 return UnsignedLong.fromLongBits(value).floatValue();
347 public final double doubleValue() {
349 return UnsignedLong.fromLongBits(value).doubleValue();
353 @SuppressWarnings("checkstyle:parameterName")
354 public final int compareTo(final Uint64 o) {
355 return Long.compareUnsigned(value, o.value);
359 public final String toCanonicalString() {
360 return Long.toUnsignedString(value);
364 public final CanonicalValueSupport<Uint64> support() {
369 * Return an interned (shared) instance equivalent to this object. This may return the same object.
371 * @return A shared instance.
373 public final Uint64 intern() {
374 return value >= 0 && value < CACHE_SIZE ? this : INTERNER.intern(this);
378 * Convert this value to a {@link BigInteger}.
380 * @return A BigInteger instance
382 public final BigInteger toJava() {
383 // FIXME: ditch the Guava transition
384 return toGuava().bigIntegerValue();
388 * Convert this value to an {@link UnsignedLong}.
390 * @return An UnsignedLong instance
392 public final UnsignedLong toGuava() {
393 return UnsignedLong.fromLongBits(value);
397 * Convert this value to a {@code Uint8}.
400 * @throws IllegalArgumentException if this value is greater than 255.
402 public final Uint8 toUint8() {
403 if ((value & 0xFFFFFFFFFFFFFF00L) != 0) {
404 UintConversions.throwIAE(toString(), 255);
406 return Uint8.fromByteBits((byte) value);
410 * Convert this value to a {@code Uint16}.
413 * @throws IllegalArgumentException if this value is greater than 65535.
415 public final Uint16 toUint16() {
416 if ((value & 0xFFFFFFFFFFFF0000L) != 0) {
417 UintConversions.throwIAE(toString(), 65535);
419 return Uint16.fromShortBits((short) value);
423 * Convert this value to a {@code Uint64}.
426 * @throws IllegalArgumentException if this value is greater than 4294967295.
428 public final Uint32 toUint32() {
429 if ((value & 0xFFFFFFFF00000000L) != 0) {
430 UintConversions.throwIAE(toString(), 4294967295L);
432 return Uint32.fromIntBits((int) value);
436 public final int hashCode() {
437 return Long.hashCode(value);
441 public final boolean equals(final @Nullable Object obj) {
442 return this == obj || obj instanceof Uint64 && value == ((Uint64)obj).value;
446 * A slightly faster version of {@link #equals(Object)}.
448 * @param obj Uint64 object
449 * @return {@code true} if this object is the same as the obj argument; {@code false} otherwise.
451 public final boolean equals(final @Nullable Uint64 obj) {
452 return this == obj || obj != null && value == obj.value;
456 public final String toString() {
457 return toCanonicalString();
460 private Object readResolve() {
461 return instanceFor(value);