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;
}
}