View Javadoc

1   // -- FILE ------------------------------------------------------------------
2   // name       : AsnBitString.java
3   // project    : Panter: LI
4   // created    : lep - 2007.01.03
5   // language   : java
6   // environment: JDK 1.5.0
7   // copyright  : (c) 2006 by Panter llc, Switzerland
8   // license    : this is free software licensed under the GPL. see COPYING
9   // --------------------------------------------------------------------------
10  package ch.panter.li.bi.asn.value;
11  
12  import ch.panter.li.bi.asn.model.AsnType;
13  import ch.panter.li.bi.asn.model.AsnTypes;
14  import ch.panter.li.bi.asn.api.BinaryValue;
15  import ch.panter.li.bi.util.HashCodeTool;
16  import ch.panter.li.bi.util.FlagTool;
17  
18  
19  public class AsnBitString extends AsnByteArrayValueBase implements BinaryValue
20  {
21  
22    public AsnBitString()
23    {
24      super( AsnTypes.BIT_STRING );
25    } // AsnBitString
26  
27    public AsnBitString( final byte[] bits )
28    {
29      this();
30      setBits( bits );
31    } // AsnBitString
32  
33    public AsnBitString( final byte[] bits, final int bitCount )
34    {
35      this();
36      setBits( bits, bitCount );
37    } // AsnBitString
38  
39    public AsnBitString( final AsnType type )
40    {
41      super( checkTypeDerivedFrom( type, AsnTypes.BIT_STRING ) );
42    } // AsnBitString
43  
44    public AsnBitString( final AsnBitString copy )
45    {
46      super( copy );
47    } // AsnBitString
48  
49    public AsnBitString copyAsnValue()
50    {
51      return new AsnBitString( this );
52    } // copyAsnValue
53  
54    public final byte[] getContent()
55    {
56      return getBits();
57    } // getContent
58  
59    public final void setContent( final byte[] content )
60    {
61      setBits( content );
62    } // setContent
63  
64    public final int getBitCount()
65    {
66      return bitCount;
67    } // getBitCount
68  
69    public final byte[] getBits()
70    {
71      return getData();
72    } // getBits
73  
74    public final void setBits( final byte[] bits )
75    {
76      setBits( bits, bits != null ? bits.length * 8 : 0 );
77    } // setBits
78  
79    public final void setBits( final byte[] bits, final int bitCount )
80    {
81      if ( bits != null && bits.length * 8 < bitCount ) {
82        throw new IllegalArgumentException( "bitCount " + bitCount +
83          " exceeds byte array length of " + bits.length + " bytes" );
84      }
85      setData( bits );
86      this.bitCount = bitCount;
87    } // setBits
88  
89    // according to ITU-T X.680 - 21.4 the 'leading' bit is numbered 'zero' with following
90    // bits having increasing numbers.
91    // according to ITU-T X.690 - 8.6.2.1 the encoding shall commence with the 'leading'
92    // bit followed by subsequent bits up to the 'trailing' bit (which has the highest number
93    // assigned).
94    // -> given that the bit numbers should be the bit positions in an 'int-value', we
95    // need to reverse the bit order from that in the byte array.
96    public final boolean getBit( final int bitPos )
97    {
98      if ( bitPos >= bitCount ) {
99        throw new IllegalArgumentException( "bitPos must be < " + bitCount + " but is " + bitPos );
100     }
101     final int octetPos = bitPos / 8;
102     final int bitPosWithinOctet = bitPos % 8;
103     final byte octet = getData()[ octetPos ];
104     final byte mask = (byte)( 0x80 >> bitPosWithinOctet );
105     return FlagTool.isSet( octet, mask );
106   } // getBit
107 
108   public void assign( final BinaryValue other )
109   {
110     if ( other != null ) {
111       final byte[] data = other.getContent();
112       if ( data != null ) {
113         if ( other instanceof AsnBitString ) {
114           setBits( data, ((AsnBitString)other).getBitCount() );
115         } else {
116           setBits( data );
117         }
118       } else {
119         setBits( null );
120       }
121     } else {
122       setBits( null );
123     }
124   } // assign
125 
126   protected boolean isEqualTo( final Object compare )
127   {
128     final AsnBitString comp = (AsnBitString)compare;
129     return super.isEqualTo( compare ) &&
130       this.bitCount == comp.bitCount;
131   } // isEqualTo
132 
133   protected int computeHashCode( final int baseHash )
134   {
135     int hash = super.computeHashCode( baseHash );
136     hash = HashCodeTool.addHashCode( hash, bitCount );
137     return hash;
138   } // computeHashCode
139 
140   public String toString()
141   {
142     final StringBuffer buf = new StringBuffer( "[" );
143     buf.append( bitCount );
144     buf.append( "-" );
145     final byte[] bits = getData();
146     if ( bits != null ) {
147       if ( bitCount <= 32 ) {
148         /* // the reversed variant
149         int printedBits = 0;
150         for ( int i = bitCount - 1; i >= 0; i--, printedBits++ ) {
151           if ( printedBits > 0 ) {
152             buf.append( "'" );
153           }
154           buf.append( getBit( i ) ? "1" : "0" );
155         }
156         //*/
157         //* // the 'normal' variant which corresponds to the hex variant
158         final byte msb = (byte)0x80;
159         int printedBits = 0;
160         for ( int i = 0; i < bits.length && printedBits < bitCount; i++ ) {
161           if ( i > 0 ) {
162             buf.append( "'" );
163           }
164           byte block = bits[ i ];
165           for ( int b = 0; b < 8 && printedBits < bitCount; b++ ) {
166             buf.append( FlagTool.isSet( block, msb ) ? "1" : "0" );
167             block = (byte)( ( ( block & 0xFF ) << 1 ) & 0xFF );
168             printedBits++;
169           }
170         }
171         //*/
172       } else {
173         // TODO: encode bits to human readable hex format
174         buf.append( bits );
175       }
176     }
177     buf.append( "]" );
178     return buf.toString();
179   } // toString
180 
181   // members
182   private int bitCount;
183 
184 } // class AsnBitString
185 
186 // -- EOF -------------------------------------------------------------------