541356fbc5d4ef5d37e2a149a8ae78ad2b991de9
[yangtools.git] / common / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / Uint32.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 java.util.Objects.requireNonNull;
11
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.UnsignedInteger;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.yangtools.concepts.Either;
20
21 /**
22  * Dedicated type for YANG's 'type uint32' type.
23  *
24  * @author Robert Varga
25  */
26 @Beta
27 @NonNullByDefault
28 public class Uint32 extends Number implements CanonicalValue<Uint32> {
29     public static final class Support extends AbstractCanonicalValueSupport<Uint32> {
30         public Support() {
31             super(Uint32.class);
32         }
33
34         @Override
35         public Either<Uint32, CanonicalValueViolation> fromString(final String str) {
36             try {
37                 return Either.ofFirst(Uint32.valueOf(str));
38             } catch (IllegalArgumentException e) {
39                 return CanonicalValueViolation.variantOf(e);
40             }
41         }
42     }
43
44     private static final CanonicalValueSupport<Uint32> SUPPORT = new Support();
45     private static final long serialVersionUID = 1L;
46     private static final long MAX_VALUE_LONG = 4294967295L;
47     private static final String MAX_VALUE_STR = "4294967295";
48
49     private static final String CACHE_SIZE_PROPERTY = "org.opendaylight.yangtools.yang.common.Uint32.cache.size";
50     private static final int DEFAULT_CACHE_SIZE = 256;
51
52     /**
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.
55      */
56     private static final int CACHE_SIZE;
57
58     static {
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;
61     }
62
63     private static final @NonNull Uint32[] CACHE;
64
65     static {
66         final Uint32[] c = new Uint32[CACHE_SIZE];
67         for (int i = 0; i < c.length; ++i) {
68             c[i] = new Uint32(i);
69         }
70         CACHE = c;
71     }
72
73     private static final Interner<Uint32> INTERNER = Interners.newWeakInterner();
74
75     /**
76      * Value of {@code 0}.
77      */
78     public static final Uint32 ZERO = valueOf(0).intern();
79     /**
80      * Value of {@code 1}.
81      */
82     public static final Uint32 ONE = valueOf(1).intern();
83     /**
84      * Value of {@code 2}.
85      */
86     public static final Uint32 TWO = valueOf(2).intern();
87     /**
88      * Value of {@code 10}.
89      */
90     public static final Uint32 TEN = valueOf(10).intern();
91     /**
92      * Value of {@code 4294967295}.
93      */
94     public static final Uint32 MAX_VALUE = valueOf(MAX_VALUE_LONG).intern();
95
96     private final int value;
97
98     private Uint32(final int value) {
99         this.value = value;
100     }
101
102     protected Uint32(final Uint32 other) {
103         this(other.value);
104     }
105
106     private static Uint32 instanceFor(final int value) {
107         final long longSlot = Integer.toUnsignedLong(value);
108         return longSlot < CACHE.length ? CACHE[(int)longSlot] : new Uint32(value);
109     }
110
111     /**
112      * Returns an {@code Uint32} corresponding to a given bit representation. The argument is interpreted as an
113      * unsigned 32-bit value.
114      *
115      * @param bits unsigned bit representation
116      * @return A Uint32 instance
117      */
118     public static Uint32 fromIntBits(final int bits) {
119         return instanceFor(bits);
120     }
121
122     /**
123      * Returns an {@code Uint32} corresponding to a given {@code byteVal}. The inverse operation is
124      * {@link #byteValue()}.
125      *
126      * @param byteVal byte value
127      * @return A Uint32 instance
128      * @throws IllegalArgumentException if byteVal is less than zero
129      */
130     public static Uint32 valueOf(final byte byteVal) {
131         UintConversions.checkNonNegative(byteVal, MAX_VALUE_STR);
132         return instanceFor(byteVal);
133     }
134
135     /**
136      * Returns an {@code Uint32} corresponding to a given {@code shortVal}. The inverse operation is
137      * {@link #shortValue()}.
138      *
139      * @param shortVal short value
140      * @return A Uint32 instance
141      * @throws IllegalArgumentException if shortVal is less than zero
142      */
143     public static Uint32 valueOf(final short shortVal) {
144         UintConversions.checkNonNegative(shortVal, MAX_VALUE_STR);
145         return instanceFor(shortVal);
146     }
147
148     /**
149      * Returns an {@code Uint32} corresponding to a given {@code intVal}. The inverse operation is {@link #intValue()}.
150      *
151      * @param intVal int value
152      * @return A Uint32 instance
153      * @throws IllegalArgumentException if intVal is less than zero
154      */
155     public static Uint32 valueOf(final int intVal) {
156         UintConversions.checkNonNegative(intVal, MAX_VALUE_STR);
157         return instanceFor(intVal);
158     }
159
160     /**
161      * Returns an {@code Uint32} corresponding to a given {@code longVal}. The inverse operation is
162      * {@link #longValue()}.
163      *
164      * @param longVal long value
165      * @return A Uint8 instance
166      * @throws IllegalArgumentException if longVal is less than zero or greater than 4294967295
167      */
168     public static Uint32 valueOf(final long longVal) {
169         UintConversions.checkRange(longVal, MAX_VALUE_LONG);
170         return instanceFor((int)longVal);
171     }
172
173     /**
174      * Returns an {@code Uint32} corresponding to a given {@code uint}.
175      *
176      * @param uint Uint8 value
177      * @return A Uint32 instance
178      * @throws NullPointerException if uint is null
179      */
180     public static Uint32 valueOf(final Uint8 uint) {
181         return instanceFor(uint.shortValue());
182     }
183
184     /**
185      * Returns an {@code Uint32} corresponding to a given {@code uint}.
186      *
187      * @param uint Uint16 value
188      * @return A Uint32 instance
189      * @throws NullPointerException if uint is null
190      */
191     public static Uint32 valueOf(final Uint16 uint) {
192         return instanceFor(uint.intValue());
193     }
194
195     /**
196      * Returns an {@code Uint32} corresponding to a given {@code uint}.
197      *
198      * @param uint Uint64 value
199      * @return A Uint32 instance
200      * @throws NullPointerException if uint is null
201      * @throws IllegalArgumentException if uint is greater than 4294967295
202      */
203     public static Uint32 valueOf(final Uint64 uint) {
204         return valueOf(uint.longValue());
205     }
206
207     /**
208      * Returns an {@code Uint32} corresponding to a given {@code uint}.
209      *
210      * @param uint UnsignedInteger value
211      * @return A Uint32 instance
212      * @throws NullPointerException if uint is null
213      */
214     public static Uint32 valueOf(final UnsignedInteger uint) {
215         return instanceFor(uint.intValue());
216     }
217
218     /**
219      * Returns an {@code Uint32} holding the value of the specified {@code String}, parsed as an unsigned {@code long}
220      * value.
221      *
222      * @param string String to parse
223      * @return A Uint32 instance
224      * @throws NullPointerException if string is null
225      * @throws IllegalArgumentException if the parsed value is less than zero or greater than 4294967295
226      * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long} value.
227      */
228     public static Uint32 valueOf(final String string) {
229         return valueOf(string, 10);
230     }
231
232     /**
233      * Returns an {@code Uint32} holding the value of the specified {@code String}, parsed as an unsigned {@code long}
234      * value.
235      *
236      * @param string String to parse
237      * @param radix Radix to use
238      * @return A Uint32 instance
239      * @throws NullPointerException if string is null
240      * @throws IllegalArgumentException if the parsed value is less than zero or greater than 4294967295
241      * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long} value, or if the
242      *                               {@code radix} is outside of allowed range.
243      */
244     public static Uint32 valueOf(final String string, final int radix) {
245         return instanceFor(Integer.parseUnsignedInt(requireNonNull(string), radix));
246     }
247
248     /**
249      * Returns an {@code Uint32} corresponding to a given {@code byteVal} if it is representable. If the value is
250      * negative {@link #ZERO} will be returned.
251      *
252      * @param byteVal byte value
253      * @return A Uint32 instance
254      */
255     public static Uint32 saturatedOf(final byte byteVal) {
256         return byteVal <= 0 ? Uint32.ZERO : instanceFor(byteVal);
257     }
258
259     /**
260      * Returns an {@code Uint32} corresponding to a given {@code shortVal} if it is representable. If the value is
261      * negative {@link #ZERO} will be returned.
262      *
263      * @param shortVal short value
264      * @return A Uint32 instance
265      */
266     public static Uint32 saturatedOf(final short shortVal) {
267         return shortVal <= 0 ? Uint32.ZERO : instanceFor(shortVal);
268     }
269
270     /**
271      * Returns an {@code Uint32} corresponding to a given {@code intVal} if it is representable. If the value is
272      * negative {@link #ZERO} will be returned.
273      *
274      * @param intVal int value
275      * @return A Uint32 instance
276      */
277     public static Uint32 saturatedOf(final int intVal) {
278         return intVal <= 0 ? Uint32.ZERO : instanceFor(intVal);
279     }
280
281     /**
282      * Returns an {@code Uint32} corresponding to a given {@code longVal} if it is representable. If the value is
283      * negative {@link #ZERO} will be returned. If the value is greater than 4294967295, {@link #MAX_VALUE} will be
284      * returned.
285      *
286      * @param longVal long value
287      * @return A Uint32 instance
288      */
289     public static Uint32 saturatedOf(final long longVal) {
290         if (longVal <= 0) {
291             return Uint32.ZERO;
292         }
293         if (longVal >= MAX_VALUE_LONG) {
294             return Uint32.MAX_VALUE;
295         }
296         return instanceFor((int) longVal);
297     }
298
299     /**
300      * {@inheritDoc}
301      *
302      * <p>
303      * The inverse operation is {@link #fromIntBits(int)}. In case this value is greater than {@link Integer#MAX_VALUE},
304      * the returned value will be equal to {@code this - 2^32}.
305      */
306     @Override
307     public final int intValue() {
308         return value;
309     }
310
311     @Override
312     public final long longValue() {
313         return Integer.toUnsignedLong(value);
314     }
315
316     @Override
317     public final float floatValue() {
318         return longValue();
319     }
320
321     @Override
322     public final double doubleValue() {
323         return longValue();
324     }
325
326     @Override
327     @SuppressWarnings("checkstyle:parameterName")
328     public final int compareTo(final Uint32 o) {
329         return Integer.compareUnsigned(value, o.value);
330     }
331
332     @Override
333     public final String toCanonicalString() {
334         return Integer.toUnsignedString(value);
335     }
336
337     @Override
338     public final CanonicalValueSupport<Uint32> support() {
339         return SUPPORT;
340     }
341
342     /**
343      * Return an interned (shared) instance equivalent to this object. This may return the same object.
344      *
345      * @return A shared instance.
346      */
347     public final Uint32 intern() {
348         return value >= 0 && value < CACHE_SIZE ? this : INTERNER.intern(this);
349     }
350
351     /**
352      * Convert this value to a {@code long}.
353      *
354      * @return A long
355      */
356     public final long toJava() {
357         return longValue();
358     }
359
360     /**
361      * Convert this value to an {@link UnsignedInteger}.
362      *
363      * @return An UnsignedInteger instance
364      */
365     public final UnsignedInteger toGuava() {
366         return UnsignedInteger.fromIntBits(value);
367     }
368
369     /**
370      * Convert this value to a {@code Uint8}.
371      *
372      * @return A Uint8
373      * @throws IllegalArgumentException if this value is greater than 255.
374      */
375     public final Uint8 toUint8() {
376         return Uint8.valueOf(toJava());
377     }
378
379     /**
380      * Convert this value to a {@code Uint16}.
381      *
382      * @return A Uint16
383      * @throws IllegalArgumentException if this value is greater than 65535.
384      */
385     public final Uint16 toUint16() {
386         return Uint16.valueOf(toJava());
387     }
388
389     /**
390      * Convert this value to a {@code Uint64}.
391      *
392      * @return A Uint64
393      */
394     public final Uint64 toUint64() {
395         return Uint64.fromLongBits(longValue());
396     }
397
398     public final Uint8 toSaturatedUint8() {
399         return Uint8.saturatedOf(toJava());
400     }
401
402     public final Uint16 toSaturatedUint16() {
403         return Uint16.saturatedOf(toJava());
404     }
405
406     // FIXME: more saturated conversions
407
408     @Override
409     public final int hashCode() {
410         return Integer.hashCode(value);
411     }
412
413     @Override
414     public final boolean equals(final @Nullable Object obj) {
415         return this == obj || obj instanceof Uint32 && value == ((Uint32)obj).value;
416     }
417
418     /**
419      * A slightly faster version of {@link #equals(Object)}.
420      *
421      * @param obj Uint32 object
422      * @return {@code true} if this object is the same as the obj argument; {@code false} otherwise.
423      */
424     public final boolean equals(final @Nullable Uint32 obj) {
425         return this == obj || obj != null && value == obj.value;
426     }
427
428     @Override
429     public final String toString() {
430         return toCanonicalString();
431     }
432
433     private Object readResolve() {
434         return instanceFor(value);
435     }
436 }