1 package org.lcsim.detector.identifier;
2
3
4
5
6
7
8
9
10 public class IdentifierField implements IIdentifierField
11 {
12 private String label;
13 private int numberOfBits;
14 private int offset;
15 private boolean isSigned;
16 private int maxValue;
17 private int minValue;
18 private long longMask;
19 private int intMask;
20
21 private static final int MAX_OFFSET = 64;
22 private static final int MIN_OFFSET = 0;
23 private static final int MAX_BITS = 32;
24 private static final int MIN_BITS = 1;
25
26 public static class ValueOutOfRangeException extends RuntimeException
27 {
28 public ValueOutOfRangeException(int value, IIdentifierField field)
29 {
30 super("The value <" + value + "> is outside range <" + field.getMinValue() + ", " + field.getMaxValue()
31 + "> of field <" + field.getLabel() + "> which has <" + field.getNumberOfBits() + "> bits.");
32 }
33 }
34
35 public IdentifierField(String label, int numberOfBits, int offset, boolean isSigned)
36 {
37 if (label == null)
38 {
39 throw new IllegalArgumentException(label + " - label is null.");
40 }
41
42 this.label = label;
43
44 if (numberOfBits > MAX_BITS || numberOfBits < MIN_BITS)
45 {
46 throw new IllegalArgumentException(label + " - number of bits is not between " + MIN_BITS + " and "
47 + MAX_BITS);
48 }
49
50 this.numberOfBits = numberOfBits;
51
52 if (offset > MAX_OFFSET || offset < MIN_OFFSET)
53 {
54 throw new IllegalArgumentException(label + " - offset <" + offset + "> is not between " + MIN_OFFSET
55 + " and " + MAX_OFFSET);
56 }
57
58 if ((offset + numberOfBits) > MAX_OFFSET)
59 {
60 throw new IllegalArgumentException(label + " - offset + numberOfBits <" + (offset + numberOfBits)
61 + "> is greater than " + MAX_OFFSET);
62 }
63
64 if (isSigned && numberOfBits < 2)
65 {
66 throw new IllegalArgumentException("The signed field " + label + " needs at least 2 bits.");
67 }
68
69 this.offset = offset;
70 this.isSigned = isSigned;
71
72 this.intMask = (1 << numberOfBits) - 1;
73 this.longMask = ((1L << numberOfBits) - 1);
74
75
76 if (!isSigned())
77 {
78 maxValue = ((int)Math.pow(2, getNumberOfBits())) - 1;
79 minValue = 0;
80 }
81
82 else
83 {
84
85 maxValue = ((int)Math.pow(2, getNumberOfBits() - 1)) - 1;
86 minValue = -maxValue;
87 }
88 }
89
90 public String getLabel()
91 {
92 return label;
93 }
94
95 public int getNumberOfBits()
96 {
97 return numberOfBits;
98 }
99
100 public int getOffset()
101 {
102 return offset;
103 }
104
105 public boolean isSigned()
106 {
107 return isSigned;
108 }
109
110 public String toString()
111 {
112 return getLabel() + ":" + getOffset() + ":" + getNumberOfBits() + ":" + isSigned() + "\n";
113 }
114
115
116 public int unpack(long value)
117 {
118 int start = getOffset();
119 int length = getNumberOfBits();
120 int mask = getIntegerMask();
121
122 int result = (int)((value >> start) & mask);
123 if (isSigned())
124 {
125 int signBit = 1 << (length - 1);
126 if ((result & signBit) != 0)
127 result -= (1 << length);
128 }
129
130 return result;
131 }
132
133
134 public int unpack(IIdentifier compact)
135 {
136 return unpack(compact.getValue());
137 }
138
139
140 public IIdentifier pack(int value)
141 {
142
143
144 long result = 0;
145 int start = getOffset();
146 long mask = getLongMask();
147 result |= (mask & value) << start;
148 return new Identifier(result);
149 }
150
151
152 public void pack(int value, IIdentifier id)
153 {
154
155
156 long result = id.getValue();
157 int start = getOffset();
158 long mask = getLongMask();
159 result |= (mask & value) << start;
160 id.setValue(result);
161 }
162
163 public int getMaxValue()
164 {
165 return maxValue;
166 }
167
168 public int getMinValue()
169 {
170 return minValue;
171 }
172
173 public int getIntegerMask()
174 {
175 return this.intMask;
176 }
177
178 public long getLongMask()
179 {
180 return this.longMask;
181 }
182
183 public boolean isValidValue(int value)
184 {
185 return value <= getMaxValue() && value >= getMinValue();
186 }
187 }