blob: 747e566be0b44a2e0513c8dc0540c2680744e599 [file] [log] [blame]
Andreas Wundsam7c15b172014-04-24 19:02:40 -07001package org.projectfloodlight.openflow.types;
2
3import org.jboss.netty.buffer.ChannelBuffer;
4
5import com.google.common.base.Preconditions;
6import com.google.common.hash.PrimitiveSink;
7
8public class U128 implements OFValueType<U128>, HashValue<U128> {
9
10 static final int LENGTH = 16;
11
12 private final long raw1; // MSBs
13 private final long raw2; // LSBs
14
15 public static final U128 ZERO = new U128(0, 0);
16
17 private U128(long raw1, long raw2) {
18 this.raw1 = raw1;
19 this.raw2 = raw2;
20 }
21
22 public static U128 of(long raw1, long raw2) {
23 if (raw1 == 0 && raw2 == 0)
24 return ZERO;
25 return new U128(raw1, raw2);
26 }
27
28 @Override
29 public int getLength() {
30 return LENGTH;
31 }
32
33
34 public long getMsb() {
35 return raw1;
36 }
37
38 public long getLsb() {
39 return raw2;
40 }
41
42 @Override
43 public U128 applyMask(U128 mask) {
44 return and(mask);
45 }
46
47 @Override
48 public int hashCode() {
49 final int prime = 31;
50 int result = 1;
51 result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
52 result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
53 return result;
54 }
55
56 @Override
57 public boolean equals(Object obj) {
58 if (this == obj)
59 return true;
60 if (obj == null)
61 return false;
62 if (getClass() != obj.getClass())
63 return false;
64 U128 other = (U128) obj;
65 if (raw1 != other.raw1)
66 return false;
67 if (raw2 != other.raw2)
68 return false;
69 return true;
70 }
71
72 public void write16Bytes(ChannelBuffer cb) {
73 cb.writeLong(raw1);
74 cb.writeLong(raw2);
75 }
76
77 public static U128 read16Bytes(ChannelBuffer cb) {
78 long raw1 = cb.readLong();
79 long raw2 = cb.readLong();
80 return of(raw1, raw2);
81 }
82
83 @Override
84 public String toString() {
85 return String.format("0x%016x%016x", raw1, raw2);
86 }
87
88 @Override
89 public int compareTo(U128 o) {
90 long c = this.raw1 - o.raw1;
91 if (c != 0)
92 return Long.signum(c);
93 return Long.signum(this.raw2 - o.raw2);
94 }
95
96 @Override
97 public void putTo(PrimitiveSink sink) {
98 sink.putLong(raw1);
99 sink.putLong(raw2);
100 }
101
102 @Override
103 public U128 inverse() {
104 return U128.of(~raw1, ~raw2);
105 }
106
107 @Override
108 public U128 or(U128 other) {
109 return U128.of(raw1 | other.raw1, raw2 | other.raw2);
110 }
111
112 @Override
113 public U128 and(U128 other) {
114 return U128.of(raw1 & other.raw1, raw2 & other.raw2);
115 }
116
117 @Override
118 public U128 xor(U128 other) {
119 return U128.of(raw1 ^ other.raw1, raw2 ^ other.raw2);
120 }
121
122 @Override
123 public int prefixBits(int numBits) {
124 Preconditions.checkArgument(numBits <= 31, "numBits must be <= 31");
125
126 Preconditions.checkArgument(numBits >= 0 && numBits < 32,
127 "numBits must be in range [0, 32[");
128
129 final int mask = (1 << numBits) -1;
130 final int shiftDown = 64 - numBits;
131
132 return (int) ((raw1 >>> shiftDown) & mask);
133 }
134
135 @Override
136 public U128 combineWithValue(U128 value, int keyBits) {
137 return U128.of(
138 HashValueUtils.combineWithValue(this.raw1, value.raw1, Math.min(64, keyBits)),
139 HashValueUtils.combineWithValue(this.raw2, value.raw2, Math.max(0,keyBits-64))
140 );
141 }
142}