public static Oid fromBytes()

in asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java [316:494]


    public static Oid fromBytes( byte[] oidBytes ) throws DecoderException
    {
        if ( ( oidBytes == null ) || ( oidBytes.length < 1 ) )
        {
            throw new DecoderException( I18n.err( I18n.ERR_00003_INVALID_OID, Arrays.toString( oidBytes ) ) );
        }

        StringBuilder builder = new StringBuilder();
        long value = 0;
        int valStart = 0;
        int valLength = 0;
        boolean firstArc = true;
        
        for ( int i = 0; i < oidBytes.length; i++ )
        {
            value |= oidBytes[i] & 0x7F;

            if ( oidBytes[i] < 0 )
            {
                // leading 1, so value continues
                value = value << 7;
                valLength++;
            }
            else
            {
                valLength++;
                
                if ( valLength > 8 )
                {
                    // Above 9 bytes, we won't be able to store the value in a long...
                    // Compute the number of necessary bytes
                    int nbBytes = valLength * 7 / 8;
                    
                    if ( valLength % 7 != 0 )
                    {
                        nbBytes++;
                    }
                    
                    byte[] result = new byte[nbBytes];
                    
                    // Now iterate on the incoming bytes
                    int pos = nbBytes - 1;
                    int valEnd = valStart + valLength - 1;
                    int j = 0;
                    
                    while ( j < valLength - 8 )
                    {
                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 1] << 7 ) | ( oidBytes[valEnd - j] & 0x7F ) );
                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 2] << 6 ) | ( ( oidBytes[valEnd - j - 1] & 0x7E ) >> 1 ) );
                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 3] << 5 ) | ( ( oidBytes[valEnd - j - 2] & 0x7C ) >> 2 ) );
                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 4] << 4 ) | ( ( oidBytes[valEnd - j - 3] & 0x78 ) >> 3 ) );
                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 5] << 3 ) | ( ( oidBytes[valEnd - j - 4] & 0x70 ) >> 4 ) );
                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 6] << 2 ) | ( ( oidBytes[valEnd - j - 5] & 0x60 ) >> 5 ) );
                        result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 7] << 1 ) | ( ( oidBytes[valEnd - j - 6] & 0x40 ) >> 6 ) );
                        j += 8;
                    }
                    
                    switch ( valLength - j )
                    {
                        case 7 :
                            result[pos--] = ( byte ) ( ( oidBytes[5] << 7 ) | ( oidBytes[6] & 0x7F ) );
                            result[pos--] = ( byte ) ( ( oidBytes[4] << 6 ) | ( ( oidBytes[5] & 0x7E ) >> 1 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[3] << 5 ) | ( ( oidBytes[4] & 0x7C ) >> 2 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[2] << 4 ) | ( ( oidBytes[3] & 0x78 ) >> 3 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[1] << 3 ) | ( ( oidBytes[2] & 0x70 ) >> 4 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[0] << 2 ) | ( ( oidBytes[1] & 0x60 ) >> 5 ) );
                            result[pos] = ( byte ) ( ( oidBytes[0] & 0x40 ) >> 6 );
                            break;
                            
                        case 6 :
                            result[pos--] = ( byte ) ( ( oidBytes[4] << 7 ) | ( oidBytes[5] & 0x7F ) );
                            result[pos--] = ( byte ) ( ( oidBytes[3] << 6 ) | ( ( oidBytes[4] & 0x7E ) >> 1 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[2] << 5 ) | ( ( oidBytes[3] & 0x7C ) >> 2 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[1] << 4 ) | ( ( oidBytes[2] & 0x78 ) >> 3 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[0] << 3 ) | ( ( oidBytes[1] & 0x70 ) >> 4 ) );
                            result[pos] = ( byte ) ( ( oidBytes[0] & 0x60 ) >> 5 );
                            break;

                        case 5 :
                            result[pos--] = ( byte ) ( ( oidBytes[3] << 7 ) | ( oidBytes[4] & 0x7F ) );
                            result[pos--] = ( byte ) ( ( oidBytes[2] << 6 ) | ( ( oidBytes[3] & 0x7E ) >> 1 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[1] << 5 ) | ( ( oidBytes[2] & 0x7C ) >> 2 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[0] << 4 ) | ( ( oidBytes[1] & 0x78 ) >> 3 ) );
                            result[pos] = ( byte ) ( ( oidBytes[0] & 0x70 ) >> 4 );
                            break;
                            
                        case 4 :
                            result[pos--] = ( byte ) ( ( oidBytes[2] << 7 ) | ( oidBytes[3] & 0x7F ) );
                            result[pos--] = ( byte ) ( ( oidBytes[1] << 6 ) | ( ( oidBytes[2] & 0x7E ) >> 1 ) );
                            result[pos--] = ( byte ) ( ( oidBytes[0] << 5 ) | ( ( oidBytes[1] & 0x7C ) >> 2 ) );
                            result[pos] = ( byte ) ( ( oidBytes[0] & 0x78 ) >> 3 );
                            break;
                            
                        case 3 :
                            result[pos--] = ( byte ) ( ( oidBytes[1] << 7 ) | ( oidBytes[2] & 0x7F ) );
                            result[pos--] = ( byte ) ( ( oidBytes[0] << 6 ) | ( ( oidBytes[1] & 0x7E ) >> 1 ) );
                            result[pos] = ( byte ) ( ( oidBytes[0] & 0x7C ) >> 2 );
                            break;

                        case 2 :
                            result[pos--] = ( byte ) ( ( oidBytes[0] << 7 ) | ( oidBytes[1] & 0x7F ) );
                            result[pos] = ( byte ) ( ( oidBytes[0] & 0x7E ) >> 1 );
                            break;
                            
                        case 1 :
                            result[pos] = ( byte ) ( oidBytes[0] & 0x7F );
                            break;
                            
                        default :
                            // Exist to please checkstyle...
                            break;
                    }
                    
                    BigInteger bigInteger;
                    
                    if ( ( result[0] & 0x80 ) == 0x80 )
                    {
                        byte[] newResult = new byte[result.length + 1];
                        System.arraycopy( result, 0, newResult, 1, result.length );
                        result = newResult;
                    }
                    
                    bigInteger = new BigInteger( result );
                    
                    if ( firstArc )
                    {
                        // This is a joint-iso-itu-t(2) arc
                        bigInteger = bigInteger.subtract( JOINT_ISO_ITU_T );
                        builder.append( '2' );
                    }
                    
                    builder.append( '.' ).append( bigInteger.toString() );
                }
                else
                {
                    // value completed
                    if ( firstArc )
                    {
                        // first value special processing
                        if ( value >= 80 )
                        {
                            // starts with 2
                            builder.append( '2' );
                            value = value - 80;
                        }
                        else
                        {
                            // starts with 0 or 1
                            long one = value / 40;
                            long two = value % 40;
    
                            if ( ( one < 0 ) || ( one > 2 ) || ( two < 0 ) || ( ( one < 2 ) && ( two > 39 ) ) )
                            {
                                throw new DecoderException( I18n.err( I18n.ERR_00003_INVALID_OID,
                                    Arrays.toString( oidBytes ) ) );
                            }
    
                            if ( one < 2 )
                            {
                                builder.append( one );
                                value = two;
                            }
                        }
                        
                        firstArc = false;
                    }
    
                    // normal processing
                    builder.append( '.' ).append( value );
                }
                
                valStart = i;
                valLength = 0;
                value = 0;
            }
        }
    
        return new Oid( builder.toString(), oidBytes );
    }