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