blob: ddf4faaccbbdca6ee47d078727ae1753a41a934c [file] [log] [blame]
tom0eb04ca2014-08-25 14:34:51 -07001package org.projectfloodlight.openflow.types;
2
3import javax.annotation.Nonnull;
4
5import org.jboss.netty.buffer.ChannelBuffer;
6
7import com.google.common.hash.PrimitiveSink;
8import com.google.common.primitives.UnsignedLongs;
9
10public class U128 implements OFValueType<U128>, HashValue<U128> {
11
12 static final int LENGTH = 16;
13
14 private final long raw1; // MSBs
15 private final long raw2; // LSBs
16
17 public static final U128 ZERO = new U128(0, 0);
18
19 private U128(long raw1, long raw2) {
20 this.raw1 = raw1;
21 this.raw2 = raw2;
22 }
23
24 public static U128 of(long raw1, long raw2) {
25 if (raw1 == 0 && raw2 == 0)
26 return ZERO;
27 return new U128(raw1, raw2);
28 }
29
30 @Override
31 public int getLength() {
32 return LENGTH;
33 }
34
35
36 public long getMsb() {
37 return raw1;
38 }
39
40 public long getLsb() {
41 return raw2;
42 }
43
44 @Override
45 public U128 applyMask(U128 mask) {
46 return and(mask);
47 }
48
49 @Override
50 public int hashCode() {
51 final int prime = 31;
52 int result = 1;
53 result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
54 result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
55 return result;
56 }
57
58 @Override
59 public boolean equals(Object obj) {
60 if (this == obj)
61 return true;
62 if (obj == null)
63 return false;
64 if (getClass() != obj.getClass())
65 return false;
66 U128 other = (U128) obj;
67 if (raw1 != other.raw1)
68 return false;
69 if (raw2 != other.raw2)
70 return false;
71 return true;
72 }
73
74 public void write16Bytes(ChannelBuffer cb) {
75 cb.writeLong(raw1);
76 cb.writeLong(raw2);
77 }
78
79 public static U128 read16Bytes(ChannelBuffer cb) {
80 long raw1 = cb.readLong();
81 long raw2 = cb.readLong();
82 return of(raw1, raw2);
83 }
84
85 @Override
86 public String toString() {
87 return String.format("0x%016x%016x", raw1, raw2);
88 }
89
90 @Override
91 public int compareTo(@Nonnull U128 o) {
92 int msb = UnsignedLongs.compare(this.raw1, o.raw1);
93 if(msb != 0)
94 return msb;
95 else
96 return UnsignedLongs.compare(this.raw2, o.raw2);
97 }
98
99 @Override
100 public void putTo(PrimitiveSink sink) {
101 sink.putLong(raw1);
102 sink.putLong(raw2);
103 }
104
105 @Override
106 public U128 inverse() {
107 return U128.of(~raw1, ~raw2);
108 }
109
110 @Override
111 public U128 or(U128 other) {
112 return U128.of(raw1 | other.raw1, raw2 | other.raw2);
113 }
114
115 @Override
116 public U128 and(U128 other) {
117 return U128.of(raw1 & other.raw1, raw2 & other.raw2);
118 }
119
120 @Override
121 public U128 xor(U128 other) {
122 return U128.of(raw1 ^ other.raw1, raw2 ^ other.raw2);
123 }
124
125 @Override
126 public U128 add(U128 other) {
127 long newRaw2 = this.raw2 + other.raw2;
128 long newRaw1 = this.raw1 + other.raw1;
129 if(UnsignedLongs.compare(newRaw2, this.raw2) < 0) {
130 // raw2 overflow
131 newRaw1+=1;
132 }
133 return U128.of(newRaw1, newRaw2);
134 }
135
136 @Override
137 public U128 subtract(U128 other) {
138 long newRaw2 = this.raw2 - other.raw2;
139 long newRaw1 = this.raw1 - other.raw1;
140 if(UnsignedLongs.compare(this.raw2, other.raw2) < 0) {
141 newRaw1 -= 1;
142 }
143 return U128.of(newRaw1, newRaw2);
144 }
145 @Override
146 public int prefixBits(int numBits) {
147 return HashValueUtils.prefixBits(this.raw1, numBits);
148 }
149
150 @Override
151 public HashValue.Builder<U128> builder() {
152 return new U128Builder(raw1, raw2);
153 }
154
155 static class U128Builder implements HashValue.Builder<U128> {
156 private long raw1, raw2;
157
158 public U128Builder(long raw1, long raw2) {
159 this.raw1 = raw1;
160 this.raw2 = raw2;
161 }
162
163 @Override
164 public Builder<U128> add(U128 other) {
165 raw2 += other.raw2;
166 raw1 += other.raw1;
167 if(UnsignedLongs.compare(raw2, other.raw2) < 0) {
168 // raw2 overflow
169 raw1+=1;
170 }
171 return this;
172 }
173
174 @Override
175 public Builder<U128> subtract(
176 U128 other) {
177 if(UnsignedLongs.compare(this.raw2, other.raw2) >= 0) {
178 raw2 -= other.raw2;
179 raw1 -= other.raw1;
180 } else {
181 // raw2 overflow
182 raw2 -= other.raw2;
183 raw1 = this.raw1 - other.raw1 - 1;
184 }
185 return this;
186 }
187
188 @Override
189 public Builder<U128> invert() {
190 raw1 = ~raw1;
191 raw2 = ~raw2;
192 return this;
193 }
194
195 @Override
196 public Builder<U128> or(U128 other) {
197 raw1 |= other.raw1;
198 raw2 |= other.raw2;
199 return this;
200 }
201
202 @Override
203 public Builder<U128> and(U128 other) {
204 raw1 &= other.raw1;
205 raw2 &= other.raw2;
206 return this;
207 }
208
209 @Override
210 public Builder<U128> xor(U128 other) {
211 raw1 ^= other.raw1;
212 raw2 ^= other.raw2;
213 return this;
214 }
215
216 @Override
217 public U128 build() {
218 return U128.of(raw1, raw2);
219 }
220 }
221
222}