You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2005/05/02 23:12:05 UTC

svn commit: r165688 - /directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/primitives/BitString.java

Author: elecharny
Date: Mon May  2 14:12:04 2005
New Revision: 165688

URL: http://svn.apache.org/viewcvs?rev=165688&view=rev
Log:
Added the BitString primitive class

Added:
    directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/primitives/BitString.java

Added: directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/primitives/BitString.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/primitives/BitString.java?rev=165688&view=auto
==============================================================================
--- directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/primitives/BitString.java (added)
+++ directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/primitives/BitString.java Mon May  2 14:12:04 2005
@@ -0,0 +1,347 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.asn1.primitives;
+
+import org.apache.asn1.DecoderException;
+import org.apache.asn1.util.pools.PoolObject;
+
+
+/**
+ * Implement the Bit String primitive type.
+ * 
+ * A BitString is internally stored as an array of int. 
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class BitString extends PoolObject
+{
+    //~ Static fields/initializers -----------------------------------------------------------------
+
+    /** A null MutableString */
+    public static final BitString EMPTY_STRING = new BitString();
+
+    /** A flag to mark the OctetString as Streamed (for OctetString larger than 1024 chars) */
+    // TODO implement the streaming...
+    public static final boolean STREAMED = true;
+
+    /** The default length of an BitString */
+    private static final int DEFAULT_LENGTH = 8;
+
+    //~ Instance fields ----------------------------------------------------------------------------
+
+    /** The number of unused ints */
+    private int nbUnusedBits;
+
+    /** Tells if the OctetString is streamed or not */
+    private boolean isStreamed;
+
+    /** The string is stored in a int array */
+    private int[] ints;
+
+    /** Actual length of the int array */
+    private int nbInts;
+
+    /** Actual length of the bit string */
+    private int nbBits;
+
+    //~ Constructors -------------------------------------------------------------------------------
+
+    /**
+     * Creates a BitString, with a default length.
+     */
+    public BitString()
+    {
+        ints         = new int[DEFAULT_LENGTH];
+        nbInts       = 0;
+        isStreamed   = false;
+        nbUnusedBits = 0;
+        nbBits       = 0;
+    }
+
+    /**
+     * Creates a BitString with a specific length (length is the number
+     * of ints).
+     *
+     * @param length The BitString length (it's a byte number)
+    */
+    public BitString(  int length )
+    {
+        nbBits = length;
+
+        // As we store values in an int, we must divide the length by 32
+        nbInts       = ( length / 32 ) + ( ( ( length % 32 ) != 0 ) ? 1 : 0 );
+
+        nbUnusedBits = length % 8;
+
+        if ( nbInts > DEFAULT_LENGTH )
+        {
+
+            // TODO : implement the streaming
+            isStreamed = true;
+            ints       = new int[nbInts];
+        }
+        else
+        {
+            isStreamed = false;
+            ints       = new int[nbInts];
+        }
+    }
+
+    /**
+     * Creates a streamed BitString with a specific length.
+     * Actually, it's just a simple BitString.
+     * TODO Implement streaming.
+     * 
+     * @param length The BitString length, in number of ints 
+     * @param isStreamed Tells if the BitString must be streamed or not 
+    */
+    public BitString(  int length, boolean isStreamed )
+    {
+        nbBits          = length;
+        this.isStreamed = isStreamed;
+        nbInts          = ( length / 32 ) + ( ( ( length % 32 ) != 0 ) ? 1 : 0 );
+
+        nbUnusedBits    = length % 8;
+
+        if ( isStreamed )
+        {
+
+            // TODO : implement the streaming
+            ints = new int[nbInts];
+        }
+        else
+        {
+            ints = new int[nbInts];
+        }
+    }
+
+    /**
+     * Creates a BitString with a value.  
+     * 
+     * @param bytes The value to store. The first byte contains the number 
+     * of unused ints
+     */
+    public BitString(  byte[] bytes )
+    {
+        nbInts = ( bytes.length / 4 ) + ( ( ( bytes.length % 4 ) != 0 ) ? 1 : 0 );
+
+        // The first byte contains the number of unused ints
+        nbUnusedBits = bytes[0] & 0x07;
+        nbBits       = ( bytes.length * 8 ) - nbUnusedBits;
+
+        if ( nbInts > DEFAULT_LENGTH )
+        {
+            isStreamed = true;
+
+            // It will be a streamed OctetString.
+            // TODO : implement the streaming
+            ints = new int[nbInts];
+        }
+        else
+        {
+            isStreamed = false;
+
+            ints       = new int[nbInts];
+        }
+
+        // We have to transfer the data from bytes to ints
+        int pos      = 1;
+        int bytesPos = 1;
+
+        for ( int i = 0; i < nbInts; i++ )
+        {
+
+            for ( int j = 0; j < 4; j++ )
+            {
+
+                if ( bytesPos == ( nbInts - 1 ) )
+                {
+                    ints[i] = ( ints[i] << ( 8 - nbUnusedBits ) ) +
+                        ( bytes[bytesPos] >> nbUnusedBits );
+                    break;
+                }
+                else
+                {
+                    ints[i] = ( ints[i] << 8 ) + bytes[bytesPos++];
+                }
+            }
+        }
+    }
+
+    //~ Methods ------------------------------------------------------------------------------------
+
+    /**
+     * Set a new BitString in the BitString. It will replace the old BitString,
+     * and reset the current length with the new one.
+     * 
+     * @param bytes The string to store
+     */
+    public void setData( byte[] bytes )
+    {
+
+        if ( ( bytes == null ) || ( bytes.length == 0 ) )
+        {
+            nbBits = -1;
+            return;
+        }
+
+        int nbBytes = bytes.length - 1;
+
+        int nbInts  = ( nbBytes / 4 ) + ( ( ( nbBytes % 4 ) != 0 ) ? 1 : 0 );
+
+        // The first byte contains the number of unused ints
+        nbUnusedBits = bytes[0] & 0x07;
+        nbBits       = ( nbBytes * 8 ) - nbUnusedBits;
+
+        if ( ( nbInts > DEFAULT_LENGTH ) && ( ints.length < nbInts ) )
+        {
+
+            // The current size is too small.
+            // We have to allocate more space
+            // TODO : implement the streaming
+            ints = new int[nbInts];
+        }
+
+        // We have to transfer the data from bytes to ints
+        int pos      = 1;
+        int bytesPos = 1;
+
+        for ( int i = 0; i < ( nbInts - 1 ); i++ )
+        {
+            ints[i] =
+                ( ( bytes[( i * 4 ) + 1] & 0x00FF ) << 24 ) +
+                ( ( bytes[( i * 4 ) + 2] & 0x00FF ) << 16 ) +
+                ( ( bytes[( i * 4 ) + 3] & 0x00FF ) << 8 ) +
+                ( bytes[( i * 4 ) + 4] & 0x00FF );
+        }
+
+        switch ( nbBytes % 4 )
+        {
+
+            case 0 :
+                ints[nbInts - 1] = ( bytes[( ( nbInts - 1 ) * 4 ) + pos] & 0x00FF );
+                pos++;
+                // fallthrough
+
+            case 3 :
+                ints[nbInts - 1] = ( ints[nbInts - 1] << 8 ) +
+                    ( bytes[( ( nbInts - 1 ) * 4 ) + pos] & 0x00FF );
+                pos++;
+                // fallthrough
+
+            case 2 :
+                ints[nbInts - 1] = ( ints[nbInts - 1] << 8 ) +
+                    ( bytes[( ( nbInts - 1 ) * 4 ) + pos] & 0x00FF );
+                pos++;
+                // fallthrough
+
+            case 1 :
+                ints[nbInts - 1] = ( ints[nbInts - 1] << 8 ) +
+                    ( bytes[( ( nbInts - 1 ) * 4 ) + pos] & 0x00FF );
+                pos++;
+                // fallthrough
+
+            default :
+            // Nothing to do...
+        }
+
+        ints[nbInts - 1] >>= nbUnusedBits;
+    }
+
+    /**
+     * Get the bit stored into the BitString at a specific position? The position start at 0,
+     * which is on the left :
+     * With '1001 000x', where x is an unused bit, 
+     *       ^ ^    ^^ 
+     *       | |    ||
+     *       | |    |+---- getBit(7) -> DecoderException
+     *       | |    +----- getBit(6) = 0
+     *       | +---------- getBit(2) = 0
+     *       +------------ getBit(0) = 1 
+     * @param pos The position of the requested bit.
+     * @return <code>true</code> if the bit is set, <code>false</code> otherwise
+     */
+    public boolean getBit( int pos ) throws DecoderException
+    {
+
+        if ( pos > nbBits )
+        {
+            throw new DecoderException(
+                "Cannot get a bit at position " + pos + " when the BitString contains only " +
+                nbBits + " ints" );
+        }
+
+        int posInt = pos / 32;
+
+        if ( ( pos / 32 ) < ( nbBits / 32 ) )
+        {
+
+            int bitNumber = 31 - ( pos % 32 );
+            int res       = ints[posInt] & ( 1 << bitNumber );
+            return res != 0;
+        }
+        else
+        {
+
+            int bitNumber = ( nbBits % 32 ) - ( pos % 32 );
+            return ( ints[posInt] & ( ( 0x01 << bitNumber ) - 1 ) ) != 0;
+        }
+
+    }
+
+    /**
+     * Return a native String representation of the BitString.
+     * @return A String representing the BitString
+    */
+    public String toString()
+    {
+
+        StringBuffer sb = new StringBuffer();
+
+        try
+        {
+
+            for ( int i = 0; i < nbBits; i++ )
+            {
+
+                if ( getBit( i ) )
+                {
+                    sb.append( '1' );
+                }
+                else
+                {
+                    sb.append( '0' );
+                }
+            }
+        }
+        catch ( DecoderException de )
+        {
+            return "Invalid BitString";
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Tells if the OctetString is streamed or not
+     * @return <code>true</code> if the OctetString is streamed.
+     */
+    public boolean isStreamed()
+    {
+        return isStreamed;
+    }
+}