]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/primitives/UnsignedLong.java
isImmutable can NPE
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / primitives / UnsignedLong.java
1 package org.simantics.databoard.primitives;
2
3 import java.math.BigInteger;
4
5
6 /**
7  * Unsigned immutable 64-bit integer value. The value is between 0 and 18446744073709551615.
8  *
9  * @author Toni Kalajainen <toni.kalajainen@iki.fi>
10  */
11 public abstract class UnsignedLong extends Number implements Comparable<Number> {
12
13         static final long serialVersionUID = 1L;
14         static final long L_MIN_VALUE = 0;
15         static final BigInteger HALF = new BigInteger("9223372036854775808"); // 2^63
16         static final BigInteger BI_MIN_VALUE = new BigInteger("0");
17         static final BigInteger BI_MAX_VALUE = new BigInteger("18446744073709551615"); // 2^64-1
18         
19         public static final UnsignedLong MIN_VALUE, MAX_VALUE, ZERO;
20         
21
22         /** Value container */
23         long value;
24         
25         /**
26          * Get cached or create new immutable unsigned long
27          *  
28          * @param value
29          * @return immutable unsigned long
30          */
31     public static UnsignedLong valueOf(long value) {
32                 if ( value>=0 && value<CACHE.length ) return CACHE[(int)value];
33         if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
34                 return new UnsignedLong.Immutable(value);       
35     }    
36         
37     /**
38      * Get cached or create new immutable unsigned long
39      * 
40      * @param bits long bits
41      * @return immutable unsigned long
42      */
43     public static UnsignedLong fromBits(long bits) {
44                 if (bits>=0 && bits<CACHE.length) return CACHE[(int)bits];
45         UnsignedLong result = new UnsignedLong.Immutable();     
46         result.value = bits;
47         return result;
48     }
49     
50         public static class Mutable extends UnsignedLong {
51         
52                 private static final long serialVersionUID = 1L;
53
54                 Mutable() {}
55                 
56                 public Mutable(int value) throws IllegalArgumentException {
57                 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
58                 this.value = value;
59             }
60
61             public Mutable(long value) throws IllegalArgumentException {
62                 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
63                 this.value = (int) value;
64             }
65
66             public Mutable(BigInteger value) throws IllegalArgumentException {
67                         if (value.compareTo(BI_MIN_VALUE)<0 || value.compareTo(BI_MAX_VALUE)>0) throw new IllegalArgumentException("Argument is not within range");             
68                         this.value = value.compareTo(HALF)<0 ? value.longValue() : value.subtract(HALF).longValue() | 0x80000000l;
69                 }
70             
71             public Mutable(String stringValue) throws IllegalArgumentException {
72                 long value = Long.parseLong(stringValue);
73                 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
74                 this.value = (int) value;
75             }   
76             
77             public static Mutable fromBits(long bits) {
78                 Mutable result = new Mutable();
79                 result.value = bits;
80                 return result;
81             }       
82             
83             public void setFromBits(int intBits) {
84                 this.value = intBits;
85             }
86             
87             public void setValue(int value) {
88                 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
89                 this.value = value;
90             }
91             
92             public void setValue(long value) {
93                 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
94                 this.value = (int) value;
95             }
96
97             public void setValue(BigInteger value) {
98                         if (value.compareTo(BI_MIN_VALUE)<0 || value.compareTo(BI_MAX_VALUE)>0) throw new IllegalArgumentException("Argument is not within range");             
99                         this.value = value.compareTo(HALF)<0 ? value.longValue() : value.subtract(HALF).longValue() | 0x80000000l;
100             }       
101             
102         }
103         
104         public final static class Immutable extends UnsignedLong {
105                 
106                 private static final long serialVersionUID = 1L;
107
108                 Immutable() {}
109                 
110                 public Immutable(int value) throws IllegalArgumentException {
111                 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
112                 this.value = value;
113             }
114
115             public Immutable(long value) throws IllegalArgumentException {
116                 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
117                 this.value = (int) value;
118             }
119
120             public Immutable(BigInteger value) throws IllegalArgumentException {
121                         if (value.compareTo(BI_MIN_VALUE)<0 || value.compareTo(BI_MAX_VALUE)>0) throw new IllegalArgumentException("Argument is not within range");             
122                         this.value = value.compareTo(HALF)<0 ? value.longValue() : value.subtract(HALF).longValue() | 0x80000000l;
123                 }
124             
125             public Immutable(String stringValue) throws IllegalArgumentException {
126                 long value = Long.parseLong(stringValue);
127                 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
128                 this.value = (int) value;
129             }   
130             
131         }       
132         
133     public long toBits() {
134         return value;
135     }
136         
137         @Override
138         public int intValue() {
139                 return (int) value;
140         }
141         
142         @Override
143         public long longValue() {
144                 return value;
145         }
146         
147         @Override
148         public float floatValue() {
149                 return value;
150         }
151         @Override
152         public double doubleValue() {
153                 return value;
154         }
155         
156         /**
157          * Create big integer value
158          * 
159          * @return new big integer
160          */
161         public BigInteger toBigInteger() {
162                 return value>=0 ? BigInteger.valueOf(value) : BigInteger.valueOf(value & 0x7fffffff).add(HALF); 
163         }       
164         
165     @Override
166         public boolean equals(Object obj) {
167                 if (obj == null) return false;
168                 if (obj == this) return true;
169                 
170                 if (obj instanceof UnsignedLong == false) return false;
171                 UnsignedLong other = (UnsignedLong) obj;
172                 return value == other.value;
173         }
174     
175     @Override
176     public String toString() {
177         return value>=0 ? Long.toString(value) : toBigInteger().toString();
178     }
179     
180         @Override
181         public int compareTo(Number obj) {
182                 return value>=0 ? Long.signum( value - obj.longValue() ) : 1;
183         }
184         
185         @Override
186         public int hashCode() {
187             return (int)value | (int)(value>>32);
188         }
189
190         // Initialize Cache
191         private static int CACHE_SIZE = 16;
192         private static UnsignedLong.Immutable[] CACHE;
193         static {
194                 CACHE = new UnsignedLong.Immutable[CACHE_SIZE];
195                 for (int i=0; i<CACHE_SIZE; i++) CACHE[i] = new UnsignedLong.Immutable(i);
196                 ZERO = MIN_VALUE = CACHE[0];
197                 MAX_VALUE = UnsignedLong.fromBits(0xFFFFFFFF);
198         }
199
200 }