Correct cache sizing for Uint types
[yangtools.git] / yang / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / Uint8.java
1 /*
2  * Copyright (c) 2015 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.common;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.annotations.Beta;
13 import org.eclipse.jdt.annotation.NonNullByDefault;
14 import org.eclipse.jdt.annotation.Nullable;
15 import org.kohsuke.MetaInfServices;
16 import org.opendaylight.yangtools.concepts.Variant;
17
18 /**
19  * Dedicated type for YANG's 'type uint8' type.
20  *
21  * @author Robert Varga
22  */
23 @Beta
24 @NonNullByDefault
25 public class Uint8 extends Number implements CanonicalValue<Uint8> {
26     @MetaInfServices(value = CanonicalValueSupport.class)
27     public static final class Support extends AbstractCanonicalValueSupport<Uint8> {
28         public Support() {
29             super(Uint8.class);
30         }
31
32         @Override
33         public Variant<Uint8, CanonicalValueViolation> fromString(final String str) {
34             try {
35                 return Variant.ofFirst(Uint8.valueOf(str));
36             } catch (IllegalArgumentException e) {
37                 return CanonicalValueViolation.variantOf(e);
38             }
39         }
40     }
41
42     private static final CanonicalValueSupport<Uint8> SUPPORT = new Support();
43
44     private static final short MIN_VALUE_SHORT = 0;
45     private static final short MAX_VALUE_SHORT = 255;
46
47     private static final long serialVersionUID = 1L;
48     private static final Uint8[] CACHE = new Uint8[MAX_VALUE_SHORT + 1];
49
50     public static final Uint8 MIN_VALUE = valueOf(MIN_VALUE_SHORT);
51     public static final Uint8 MAX_VALUE = valueOf(MAX_VALUE_SHORT);
52
53     private final byte value;
54
55     private Uint8(final byte value) {
56         this.value = value;
57     }
58
59     protected Uint8(final Uint8 other) {
60         this.value = other.value;
61     }
62
63     private static Uint8 instanceFor(final byte value) {
64         final int slot = Byte.toUnsignedInt(value);
65
66         // FIXME: 4.0.0: use VarHandles here
67         Uint8 ret = CACHE[slot];
68         if (ret == null) {
69             synchronized (CACHE) {
70                 ret = CACHE[slot];
71                 if (ret == null) {
72                     ret = new Uint8(value);
73                     CACHE[slot] = ret;
74                 }
75             }
76         }
77
78         return ret;
79     }
80
81     public static Uint8 fromByteBits(final byte bits) {
82         return instanceFor(bits);
83     }
84
85     public static Uint8 valueOf(final byte byteVal) {
86         checkArgument(byteVal >= MIN_VALUE_SHORT, "Negative values are not allowed");
87         return instanceFor(byteVal);
88     }
89
90     public static Uint8 valueOf(final short shortVal) {
91         checkArgument(shortVal >= MIN_VALUE_SHORT && shortVal <= MAX_VALUE_SHORT,
92                 "Value %s is outside of allowed range", shortVal);
93         return instanceFor((byte)(shortVal & 0xff));
94     }
95
96     public static Uint8 valueOf(final int intVal) {
97         checkArgument(intVal >= MIN_VALUE_SHORT && intVal <= MAX_VALUE_SHORT,
98                 "Value %s is outside of allowed range", intVal);
99         return instanceFor((byte)(intVal & 0xff));
100     }
101
102     public static Uint8 valueOf(final long longVal) {
103         checkArgument(longVal >= MIN_VALUE_SHORT && longVal <= MAX_VALUE_SHORT,
104                 "Value %s is outside of allowed range", longVal);
105         return instanceFor((byte)(longVal & 0xff));
106     }
107
108     public static Uint8 valueOf(final Uint16 uint) {
109         return valueOf(uint.intValue());
110     }
111
112     public static Uint8 valueOf(final Uint32 uint) {
113         return valueOf(uint.longValue());
114     }
115
116     public static Uint8 valueOf(final Uint64 uint) {
117         return valueOf(uint.longValue());
118     }
119
120     public static Uint8 valueOf(final String string) {
121         return valueOf(string, 10);
122     }
123
124     public static Uint8 valueOf(final String string, final int radix) {
125         return valueOf(Short.parseShort(string, radix));
126     }
127
128     @Override
129     public final byte byteValue() {
130         return value;
131     }
132
133     @Override
134     public final int intValue() {
135         return Byte.toUnsignedInt(value);
136     }
137
138     @Override
139     public final long longValue() {
140         return Byte.toUnsignedLong(value);
141     }
142
143     @Override
144     public final float floatValue() {
145         return intValue();
146     }
147
148     @Override
149     public final double doubleValue() {
150         return intValue();
151     }
152
153     @Override
154     @SuppressWarnings("checkstyle:parameterName")
155     public final int compareTo(final Uint8 o) {
156         return intValue() - o.intValue();
157     }
158
159     @Override
160     public final String toCanonicalString() {
161         return String.valueOf(intValue());
162     }
163
164     @Override
165     public final CanonicalValueSupport<Uint8> support() {
166         return SUPPORT;
167     }
168
169     @Override
170     public final int hashCode() {
171         return Byte.hashCode(value);
172     }
173
174     @Override
175     public final boolean equals(final @Nullable Object obj) {
176         return this == obj || obj instanceof Uint8 && value == ((Uint8)obj).value;
177     }
178
179     @Override
180     public final String toString() {
181         return toCanonicalString();
182     }
183
184     private Object readResolve() {
185         return instanceFor(value);
186     }
187 }