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 com.google.common.base.Preconditions.checkArgument;
12 import com.google.common.annotations.Beta;
13 import com.google.common.cache.CacheBuilder;
14 import com.google.common.cache.CacheLoader;
15 import com.google.common.cache.LoadingCache;
16 import com.google.common.primitives.UnsignedLong;
17 import java.math.BigInteger;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.kohsuke.MetaInfServices;
21 import org.opendaylight.yangtools.concepts.Variant;
24 * Dedicated type for YANG's 'type uint64' type.
26 * @author Robert Varga
30 public class Uint64 extends Number implements CanonicalValue<Uint64> {
31 @MetaInfServices(value = CanonicalValueSupport.class)
32 public static final class Support extends AbstractCanonicalValueSupport<Uint64> {
38 public Variant<Uint64, CanonicalValueViolation> fromString(final String str) {
40 return Variant.ofFirst(Uint64.valueOf(str));
41 } catch (IllegalArgumentException e) {
42 return CanonicalValueViolation.variantOf(e);
47 private static final CanonicalValueSupport<Uint64> SUPPORT = new Support();
48 private static final long serialVersionUID = 1L;
49 private static final long MIN_VALUE_LONG = 0;
52 * Cache of first 256 values.
54 private static final Uint64[] CACHE = new Uint64[256];
56 * Commonly encountered values.
58 private static final Uint64[] COMMON = {
59 new Uint64(Short.MAX_VALUE + 1L),
63 new Uint64(Integer.MAX_VALUE),
64 new Uint64(Integer.MAX_VALUE + 1L),
65 new Uint64(Long.MAX_VALUE),
69 public static final Uint64 MIN_VALUE = valueOf(MIN_VALUE_LONG);
70 public static final Uint64 MAX_VALUE = fromLongBits(-1);
73 * Tunable weak LRU cache for other values. By default it holds {@value #DEFAULT_LRU_SIZE} entries. This can be
74 * changed via {@value #LRU_SIZE_PROPERTY} system property.
76 private static final int DEFAULT_LRU_SIZE = 1024;
77 private static final String LRU_SIZE_PROPERTY = "org.opendaylight.yangtools.yang.common.Uint64.LRU.size";
78 private static final int MAX_LRU_SIZE = 0xffffff;
79 private static final int LRU_SIZE;
82 final int p = Integer.getInteger(LRU_SIZE_PROPERTY, DEFAULT_LRU_SIZE);
83 LRU_SIZE = p >= 0 ? Math.min(p, MAX_LRU_SIZE) : DEFAULT_LRU_SIZE;
86 private static final LoadingCache<Long, Uint64> LRU = CacheBuilder.newBuilder().weakValues().maximumSize(LRU_SIZE)
87 .build(new CacheLoader<Long, Uint64>() {
89 public Uint64 load(final Long key) {
90 return new Uint64(key);
94 private final long value;
96 Uint64(final long value) {
100 protected Uint64(final Uint64 other) {
101 this.value = other.value;
104 private static Uint64 instanceFor(final long value) {
105 final int slot = (int)value;
106 return slot >= 0 && slot < CACHE.length ? fromCache(slot, value) : fromCommon(value);
109 private static Uint64 fromCommon(final long value) {
110 for (Uint64 c : COMMON) {
111 if (c.value == value) {
115 return LRU.getUnchecked(value);
118 private static Uint64 fromCache(final int slot, final long value) {
119 // FIXME: 4.0.0: use VarHandles here
120 Uint64 ret = CACHE[slot];
122 synchronized (CACHE) {
125 ret = new Uint64(value);
133 public static Uint64 fromLongBits(final long bits) {
134 return instanceFor(bits);
137 public static Uint64 fromUnsignedLong(final UnsignedLong ulong) {
138 return instanceFor(ulong.longValue());
141 public static Uint64 valueOf(final byte byteVal) {
142 checkArgument(byteVal >= MIN_VALUE_LONG, "Negative values are not allowed");
143 return instanceFor(byteVal);
146 public static Uint64 valueOf(final short shortVal) {
147 checkArgument(shortVal >= MIN_VALUE_LONG, "Negative values are not allowed");
148 return instanceFor(shortVal);
151 public static Uint64 valueOf(final int intVal) {
152 checkArgument(intVal >= MIN_VALUE_LONG, "Value %s is outside of allowed range", intVal);
153 return instanceFor(intVal);
156 public static Uint64 valueOf(final long longVal) {
157 checkArgument(longVal >= MIN_VALUE_LONG, "Value %s is outside of allowed range", longVal);
158 return instanceFor(longVal);
161 public static Uint64 valueOf(final Uint8 uint) {
162 return instanceFor(uint.shortValue());
165 public static Uint64 valueOf(final Uint16 uint) {
166 return instanceFor(uint.intValue());
169 public static Uint64 valueOf(final Uint32 uint) {
170 return instanceFor(uint.longValue());
173 public static Uint64 valueOf(final String string) {
174 return valueOf(string, 10);
177 public static Uint64 valueOf(final String string, final int radix) {
178 return instanceFor(Long.parseUnsignedLong(string, radix));
181 public static Uint64 valueOf(final BigInteger bigInt) {
182 checkArgument(bigInt.signum() >= 0, "Negative values not allowed");
183 checkArgument(bigInt.bitLength() <= Long.SIZE, "Value %s is outside of allowed range", bigInt);
185 return instanceFor(bigInt.longValue());
189 public final int intValue() {
194 public final long longValue() {
199 public final float floatValue() {
201 return UnsignedLong.fromLongBits(value).floatValue();
205 public final double doubleValue() {
207 return UnsignedLong.fromLongBits(value).doubleValue();
210 public final UnsignedLong toUnsignedLong() {
211 return UnsignedLong.fromLongBits(value);
215 @SuppressWarnings("checkstyle:parameterName")
216 public final int compareTo(final Uint64 o) {
217 return Long.compareUnsigned(value, o.value);
221 public final String toCanonicalString() {
222 return Long.toUnsignedString(value);
226 public final CanonicalValueSupport<Uint64> support() {
231 public final int hashCode() {
232 return Long.hashCode(value);
236 public final boolean equals(final @Nullable Object obj) {
237 return this == obj || obj instanceof Uint64 && value == ((Uint64)obj).value;
241 public final String toString() {
242 return toCanonicalString();
245 private Object readResolve() {
246 return instanceFor(value);