private static int convert()

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


    private static int convert( String oid, byte[] buffer, int start, int nbDigits, int posBuffer, boolean isJointIsoItuT )
    {
        if ( nbDigits < 3 )
        {
            // Speedup when we have a number in [0..99] : it's guaranteed to be hold
            // by a single byte.
            if ( isJointIsoItuT )
            {
                // Another special case : this is an OID that starts with '2.'
                buffer[0] =  ( byte ) ( 80 + ( oid.charAt( 2 ) - '0' ) * 10 + ( oid.charAt( 3 ) - '0' ) );
                
                if ( buffer[0] < 0 )
                {
                    // Here, we need 2 bytes
                    buffer[1] = ( byte ) ( buffer[0] & 0x007F );
                    buffer[0] = ( byte ) 0x81;
                    
                    return 2;
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                if ( nbDigits == 1 )
                {
                    buffer[posBuffer] = ( byte ) ( oid.charAt( start ) - '0' );
                }
                else
                {
                    buffer[posBuffer] = ( byte ) ( ( oid.charAt( start ) - '0' ) * 10 + ( oid.charAt( start + 1 ) - '0' ) );
                    
                }
                return 1;
            }

        }
        else if ( nbDigits < 19 )
        {
            // The value can be hold in a Long if it's up to 999999999999999999 
            // Convert the String to a long :
            String number = oid.substring( start, start + nbDigits );

            long value = Long.parseLong( number );

            if ( isJointIsoItuT )
            {
                value += 80L;
            }
            
            // Convert the long to a byte array
            if ( ( value & 0xFFFFFFFFFFFFFF80L ) == 0 )
            {
                // The value will be hold in one byte
                buffer[posBuffer] = ( byte ) ( value );
                
                return 1;
            }
            
            if ( ( value & 0xFFFFFFFFFFFFC000L ) == 0 )
            {
                // The value is between 0x80 and 0x3FFF : it will be hold in 2 bytes
                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
                buffer[posBuffer + 1] = ( byte ) ( value & 0x000000000000007FL );
                
                return 2;
            }
            
            if ( ( value & 0xFFFFFFFFFFE00000L ) == 0 )
            {
                // The value is between 0x4000 and 0x1FFFFF : it will be hold in 3 bytes
                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
                buffer[posBuffer + 2] = ( byte ) ( value & 0x000000000000007FL );
                
                return 3;
            }
            
            if ( ( value & 0xFFFFFFFFF0000000L ) == 0 )
            {
                // The value is between 0x200000 and 0xFFFFFFF : it will be hold in 4 bytes
                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
                buffer[posBuffer + 3] = ( byte ) ( value & 0x000000000000007FL );
                
                return 4;
            }

            if ( ( value & 0xFFFFFFF800000000L ) == 0 )
            {
                // The value is between 0x10000000 and 0x7FFFFFFFF : it will be hold in 5 bytes
                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
                buffer[posBuffer + 4] = ( byte ) ( value & 0x000000000000007FL );
                
                return 5;
            }

            if ( ( value & 0xFFFFFC0000000000L ) == 0 )
            {
                // The value is between 0x800000000 and 0x3FFFFFFFFFF : it will be hold in 6 bytes
                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
                buffer[posBuffer + 5] = ( byte ) ( value & 0x000000000000007FL );
                
                return 6;
            }

            if ( ( value & 0xFFFE000000000000L ) == 0 )
            {
                // The value is between 0x40000000000 and 0x1FFFFFFFFFFFF : it will be hold in 7 bytes
                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
                buffer[posBuffer + 6] = ( byte ) ( value & 0x000000000000007FL );
                
                return 7;
            }

            if ( ( value & 0xFF00000000000000L ) == 0 )
            {
                // The value is between 0x2000000000000 and 0xFF000000000000 : it will be hold in 8 bytes
                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00FE000000000000L ) >> 49 ) | 0x80 );
                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
                buffer[posBuffer + 6] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
                buffer[posBuffer + 7] = ( byte ) ( value & 0x000000000000007FL );
                
                return 8;
            }
            else
            {
                // The value is between 0x100000000000000 and 0x7F00000000000000 : it will be hold in 9 bytes
                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x7F00000000000000L ) >> 56 ) | 0x80 );
                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00FE000000000000L ) >> 49 ) | 0x80 );
                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
                buffer[posBuffer + 6] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
                buffer[posBuffer + 7] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
                buffer[posBuffer + 8] = ( byte ) ( value & 0x000000000000007FL );
                
                return 9;
            }
        }
        else
        {
            // The value is bigger than 9999999999999999999, we need to use a BigInteger
            // First, get the number of bytes we need to store the value in base 16
            String number = oid.substring( start, start + nbDigits );
            BigInteger bigInteger = new BigInteger( number );
            
            if ( isJointIsoItuT )
            {
                bigInteger = bigInteger.add( JOINT_ISO_ITU_T );
                posBuffer = 0;
            }
            
            byte[] bytes = bigInteger.toByteArray();
            
            // Now, convert this value to the ASN.1 OID format : we store the value
            // as 7 bits bytes 
            int nbNeededBytes = ( bytes.length * 8 ) / 7;
            
            switch ( ( bytes.length - 1 ) % 7 )
            {
                case 0 :
                    if ( ( bytes[0] & 0x0080 ) != 0 )
                    {
                        nbNeededBytes++;
                    }
                    
                    break;
                    
                case 1 :
                    if ( ( bytes[0] & 0x00C0 ) != 0 )
                    {
                        nbNeededBytes++;
                    }
                    
                    break;
                    
                case 2 :
                    if ( ( bytes[0] & 0x00E0 ) != 0 )
                    {
                        nbNeededBytes++;
                    }
                    
                    break;
                    
                case 3 : 
                    if ( ( bytes[0] & 0x00F0 ) != 0 )
                    {
                        nbNeededBytes++;
                    }
                    
                    break;
                    
                case 4 :
                    if ( ( bytes[0] & 0x00F8 ) != 0 )
                    {
                        nbNeededBytes++;
                    }
                    
                    break;
                    
                case 5 :
                    if ( ( bytes[0] & 0x00FC ) != 0 )
                    {
                        nbNeededBytes++;
                    }
                    
                    break;
                    
                case 6 : 
                    if ( ( bytes[0] & 0x00FE ) != 0 )
                    {
                        nbNeededBytes++;
                    }
                    
                    break;
                    
                default :
                    // Exist to please checkstyle...
                    break;
            }
            
            byte[] converted = new byte[nbNeededBytes];
            
            int posConverted = nbNeededBytes - 1;
            int posBytes = bytes.length - 1;
            int counter = 0;
            byte reminder = 0;
            
            while ( posBytes >= 0 )
            {
                byte newByte = ( byte ) ( ( bytes[posBytes] & 0x00FF ) << counter );
                converted[posConverted] = ( byte ) ( reminder | newByte | 0x0080 );
                reminder = ( byte ) ( ( bytes[posBytes] & 0x00FF ) >> ( 7 - counter ) );
                counter =  ( counter + 1 ) % 8; 
                posConverted--;
                
                if ( counter != 0 )
                {
                    posBytes--;
                }
                else
                {
                    reminder = 0;
                }
            }
            
            converted[nbNeededBytes - 1] &= 0x7F;
            
            // Copy the converted bytes in the buffer
            System.arraycopy( converted, 0, buffer, posBuffer, nbNeededBytes );
            
            return nbNeededBytes;
        }
    }