1 /*
2  * hunt-proton: AMQP Protocol library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.proton.amqp.UnsignedLong;
13 
14 import hunt.math;
15 import hunt.Number;
16 import std.algorithm.comparison;
17 import std.conv : to;
18 import hunt.logging;
19 
20 import std.concurrency : initOnce;
21 
22 
23 class UnsignedLong : Number
24 {
25     static UnsignedLong[] cachedValues ;
26     static BigInteger TWO_TO_THE_SIXTY_FOUR;
27     static BigInteger LONG_MAX_VALUE;
28     static UnsignedLong ZERO;
29 
30     static UnsignedLong[] initCachedValues()
31     {
32         UnsignedLong[] cachedVal = new UnsignedLong[256];
33         for(int i = 0; i<256; i++)
34         {
35             cachedValues[i] = new UnsignedLong(i);
36         }
37         return cachedVal;
38     }
39 
40     //static UnsignedLong[]  cachedValues() {
41     //    __gshared UnsignedLong[]  inst;
42     //    return initOnce!inst(initCachedValues);
43     //}
44 
45 
46 
47     static this()
48     {
49         cachedValues = new UnsignedLong[256];
50         for(int i = 0; i<256; i++)
51         {
52             cachedValues[i] = new UnsignedLong(i);
53         }
54         UnsignedLong.TWO_TO_THE_SIXTY_FOUR = new BigInteger([1,0,0,0,0,0,0,0,0]);
55         UnsignedLong.LONG_MAX_VALUE = BigInteger.valueOf(0x7FFFFFFFFFFFFFFF);
56         UnsignedLong.ZERO = cachedValues[0];
57     }
58 
59 
60 
61     private long _underlying;
62 
63 
64     this(long underlying)
65     {
66         _underlying = underlying;
67     }
68 
69     override
70     public int intValue()
71     {
72         return cast(int) _underlying;
73     }
74 
75     override
76     public long longValue()
77     {
78         return _underlying;
79     }
80 
81     public BigInteger bigIntegerValue()
82     {
83         if(_underlying >= 0L)
84         {
85             return BigInteger.valueOf(_underlying);
86         }
87         else
88         {
89             return TWO_TO_THE_SIXTY_FOUR.add(BigInteger.valueOf(_underlying));
90         }
91     }
92 
93     override
94     public float floatValue()
95     {
96         return cast(float) (longValue());
97     }
98 
99     override
100     public double doubleValue()
101     {
102         return cast(double) (longValue());
103     }
104 
105     override bool opEquals(Object o)
106     {
107         if (this is o)
108         {
109             return true;
110         }
111         if (o is null || (cast(UnsignedLong)o is null))
112         {
113             return false;
114         }
115 
116         UnsignedLong that = cast(UnsignedLong)o;
117 
118         if (_underlying != that._underlying)
119         {
120             return false;
121         }
122 
123         return true;
124     }
125 
126      override int opCmp(Object o)
127     {
128         UnsignedLong that = cast(UnsignedLong)(o);
129         return cast(int)(longValue() - that.longValue());
130     }
131 
132     //override size_t toHash() @trusted nothrow {
133     //    size_t hashcode = 0;
134     //    hashcode = price * 20;
135     //    hashcode += hashOf(item);
136     //    return hashcode;
137     //}
138 
139     override
140     public  size_t toHash() @trusted nothrow
141     {
142         return cast(size_t)(_underlying ^ (_underlying >>> 32));
143     }
144     //
145     //public string toString()
146     //{
147     //    return String.valueOf(bigIntegerValue());
148     //}
149 
150     public static UnsignedLong valueOf(long underlying)
151     {
152         if((underlying & 0xFFL) == underlying)
153         {
154             return cachedValues[cast(int)(underlying)];
155         }
156         else
157         {
158             return new UnsignedLong(underlying);
159         }
160     }
161 
162     public static UnsignedLong valueOf(string value)
163     {
164         BigInteger bigInt = new BigInteger(value);
165 
166         return valueOf(bigInt);
167     }
168 
169     public static UnsignedLong valueOf(BigInteger bigInt)
170     {
171         if(bigInt.signum() == -1 || bigInt.bitLength() > 64)
172         {
173            // throw new NumberFormatException("Value \""+bigInt+"\" lies outside the range [0 - 2^64).");
174             logError("Value lies outside the range [0 - 2^64).");
175             return null;
176         }
177         else if(bigInt.compareTo(LONG_MAX_VALUE)>=0)
178         {
179             return UnsignedLong.valueOf(bigInt.longValue());
180         }
181         else
182         {
183             return UnsignedLong.valueOf(TWO_TO_THE_SIXTY_FOUR.subtract(bigInt).negate().longValue());
184         }
185     }
186 
187 
188     override
189     byte byteValue()
190     {
191         return 1;
192     }
193 
194     override short shortValue()
195     {
196         return 1;
197     }
198 
199     override string toString()
200     {
201         return "";
202     }
203 }