View Javadoc

1   package org.lcsim.detector.identifier;
2   
3   /**
4    * Implementation of {@link IIdentifierField}.
5    * 
6    * @author Jeremy McCormick
7    * @version $Id: IdentifierField.java,v 1.9 2011/02/25 03:09:38 jeremy Exp $
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          // Range for unsigned field.
76          if (!isSigned())
77          {
78              maxValue = ((int)Math.pow(2, getNumberOfBits())) - 1;
79              minValue = 0;
80          }
81          // Range for signed field.
82          else
83          {
84              // In a signed field, one bit is reserved for the sign bit.
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     // FIXME: Move to IdentifierUtil.
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     // FIXME: Move to IdentifierUtil.
134     public int unpack(IIdentifier compact)
135     {
136         return unpack(compact.getValue());
137     }
138 
139     // FIXME: Move to IdentifierUtil.
140     public IIdentifier pack(int value)
141     {
142         //if (!isValidValue(value))
143         //    throw new ValueOutOfRangeException(value, this);
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     // FIXME: Move to IdentifierUtil.
152     public void pack(int value, IIdentifier id)
153     {
154         //if (!isValidValue(value))
155         //    throw new ValueOutOfRangeException(value, this);
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 }