blob: 7c00adee2989ae48e1d3d72feccd6812864123c2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* https://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.directory.api.asn1.ber.tlv;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import org.apache.directory.api.asn1.EncoderException;
import org.apache.directory.api.asn1.util.Asn1Buffer;
import org.apache.directory.api.asn1.util.Asn1StringUtils;
import org.apache.directory.api.asn1.util.BitString;
import org.apache.directory.api.asn1.util.Oid;
import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.util.Strings;
/**
* This class stores the data decoded from a TLV.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class BerValue
{
/** The data buffer. */
private byte[] data;
/** The current position of the last byte in the data buffer */
private int currentPos;
/** The encoded byte for a TRUE value */
public static final byte TRUE_VALUE = ( byte ) 0xFF;
/** The encoded byte for a FALSE value */
public static final byte FALSE_VALUE = ( byte ) 0x00;
/** Pre-encoded PDUs for a TRUE TLV */
private static final byte[] ENCODED_TRUE = new byte[]
{ 0x01, 0x01, TRUE_VALUE };
/** Pre-encoded PDUs for a FALSE TLV */
private static final byte[] ENCODED_FALSE = new byte[]
{ 0x01, 0x01, FALSE_VALUE };
/** Integer limits for encoding : 0x7F */
private static final int ONE_BYTE_MAX = ( 1 << 7 ) - 1;
/** Integer limits for encoding : -0x7F */
private static final int ONE_BYTE_MIN = -( 1 << 7 );
/** Integer limits for encoding : 0x7FFF */
private static final int TWO_BYTE_MAX = ( 1 << 15 ) - 1;
/** Integer limits for encoding : -0x7FFF */
private static final int TWO_BYTE_MIN = -( 1 << 15 );
/** Integer limits for encoding : 0x7FFFFF */
private static final int THREE_BYTE_MAX = ( 1 << 23 ) - 1;
/** Integer limits for encoding : -0x7FFFFF */
private static final int THREE_BYTE_MIN = -( 1 << 23 );
/** Integer limits for encoding : 0x7FFFFFFF */
private static final long FOUR_BYTE_MAX = ( 1L << 31 ) - 1L;
/** Integer limits for encoding : -0x7FFFFFFF */
private static final long FOUR_BYTE_MIN = -( 1L << 31 );
/** Integer limits for encoding : 0x7FFFFFFFFF */
private static final long FIVE_BYTE_MAX = ( 1L << 39 ) - 1L;
/** Integer limits for encoding : -0x7FFFFFFFFF */
private static final long FIVE_BYTE_MIN = -( 1L << 39 );
/** Integer limits for encoding : 0x7FFFFFFFFFFF */
private static final long SIX_BYTE_MAX = ( 1L << 47 ) - 1L;
/** Integer limits for encoding : -0x7FFFFFFFFFFF */
private static final long SIX_BYTE_MIN = -( 1L << 47 );
/** Integer limits for encoding : 0x7FFFFFFFFFFF */
private static final long SEVEN_BYTE_MAX = ( 1L << 55 ) - 1L;
/** Integer limits for encoding : -0x7FFFFFFFFFFF */
private static final long SEVEN_BYTE_MIN = -( 1L << 55 );
/**
* Creates a new Value from a byte[]
*
* @param value the associated value
*/
public BerValue( byte[] value )
{
// Do a copy of the byte array
data = new byte[value.length];
System.arraycopy( value, 0, data, 0, value.length );
currentPos = 0;
}
/**
* The default constructor.
*/
public BerValue()
{
data = null;
currentPos = 0;
}
/**
* Initialize the Value
*
* @param size The data size to allocate.
*/
public void init( int size )
{
data = new byte[size];
currentPos = 0;
}
/**
* Reset the Value so that it can be reused
*/
public void reset()
{
data = null;
currentPos = 0;
}
/**
* Get the Values'data
*
* @return Returns the data.
*/
public byte[] getData()
{
return data;
}
/**
* Set a block of bytes in the Value
*
* @param data The data to set.
*/
public void setData( ByteBuffer data )
{
int length = data.remaining();
data.get( this.data, 0, length );
currentPos = length;
}
/**
* Append some bytes to the data buffer.
*
* @param buffer The data to append.
*/
public void addData( ByteBuffer buffer )
{
int length = buffer.remaining();
buffer.get( data, currentPos, length );
currentPos += length;
}
/**
* Set a block of bytes in the Value
*
* @param data The data to set.
*/
public void setData( byte[] data )
{
System.arraycopy( data, 0, this.data, 0, data.length );
currentPos = data.length;
}
/**
* Append some bytes to the data buffer.
*
* @param array The data to append.
*/
public void addData( byte[] array )
{
System.arraycopy( array, 0, this.data, currentPos, array.length );
currentPos = array.length;
}
/**
* @return The number of bytes actually stored
*/
public int getCurrentLength()
{
return currentPos;
}
/**
* Utility function that return the number of bytes necessary to store an
* integer value. Note that this value must be in [Integer.MIN_VALUE,
* Integer.MAX_VALUE].
*
* @param value The value to store in a byte array
* @return The number of bytes necessary to store the value.
*/
public static int getNbBytes( int value )
{
if ( ( value >= ONE_BYTE_MIN ) && ( value <= ONE_BYTE_MAX ) )
{
return 1;
}
else if ( ( value >= TWO_BYTE_MIN ) && ( value <= TWO_BYTE_MAX ) )
{
return 2;
}
else if ( ( value >= THREE_BYTE_MIN ) && ( value <= THREE_BYTE_MAX ) )
{
return 3;
}
else
{
return 4;
}
}
/**
* Utility function that return the number of bytes necessary to store a
* long value. Note that this value must be in [Long.MIN_VALUE,
* Long.MAX_VALUE].
*
* @param value The value to store in a byte array
* @return The number of bytes necessary to store the value.
*/
public static int getNbBytes( long value )
{
if ( ( value >= ONE_BYTE_MIN ) && ( value <= ONE_BYTE_MAX ) )
{
return 1;
}
else if ( ( value >= TWO_BYTE_MIN ) && ( value <= TWO_BYTE_MAX ) )
{
return 2;
}
else if ( ( value >= THREE_BYTE_MIN ) && ( value <= THREE_BYTE_MAX ) )
{
return 3;
}
else if ( ( value >= FOUR_BYTE_MIN ) && ( value <= FOUR_BYTE_MAX ) )
{
return 4;
}
else if ( ( value >= FIVE_BYTE_MIN ) && ( value <= FIVE_BYTE_MAX ) )
{
return 5;
}
else if ( ( value >= SIX_BYTE_MIN ) && ( value <= SIX_BYTE_MAX ) )
{
return 6;
}
else if ( ( value >= SEVEN_BYTE_MIN ) && ( value <= SEVEN_BYTE_MAX ) )
{
return 7;
}
else
{
return 8;
}
}
/**
* Utility function that return a byte array representing the Value We must
* respect the ASN.1 BER encoding scheme :
* <pre>
* 1) positive integer
* - [0 - 0x7F] : 0xVV
* - [0x80 - 0xFF] : 0x00 0xVV
* - [0x0100 - 0x7FFF] : 0xVV 0xVV
* - [0x8000 - 0xFFFF] : 0x00 0xVV 0xVV
* - [0x010000 - 0x7FFFFF] : 0xVV 0xVV 0xVV
* - [0x800000 - 0xFFFFFF] : 0x00 0xVV 0xVV 0xVV
* - [0x01000000 - 0x7FFFFFFF] : 0xVV 0xVV 0xVV 0xVV
* 2) Negative number - (~value) + 1
* </pre>
*
* @param value The value to store in a byte array
* @return The byte array representing the value.
*/
public static byte[] getBytes( int value )
{
byte[] bytes;
if ( value >= 0 )
{
if ( ( value >= 0 ) && ( value <= ONE_BYTE_MAX ) )
{
bytes = new byte[1];
bytes[0] = ( byte ) value;
}
else if ( ( value > ONE_BYTE_MAX ) && ( value <= TWO_BYTE_MAX ) )
{
bytes = new byte[2];
bytes[1] = ( byte ) value;
bytes[0] = ( byte ) ( value >> 8 );
}
else if ( ( value > TWO_BYTE_MAX ) && ( value <= THREE_BYTE_MAX ) )
{
bytes = new byte[3];
bytes[2] = ( byte ) value;
bytes[1] = ( byte ) ( value >> 8 );
bytes[0] = ( byte ) ( value >> 16 );
}
else
{
bytes = new byte[4];
bytes[3] = ( byte ) value;
bytes[2] = ( byte ) ( value >> 8 );
bytes[1] = ( byte ) ( value >> 16 );
bytes[0] = ( byte ) ( value >> 24 );
}
}
else
{
// On special case : 0x80000000
if ( value == 0x80000000 )
{
bytes = new byte[4];
bytes[3] = ( byte ) value;
bytes[2] = ( byte ) ( value >> 8 );
bytes[1] = ( byte ) ( value >> 16 );
bytes[0] = ( byte ) ( value >> 24 );
}
else
{
// We have to compute the complement, and add 1
if ( value >= 0xFFFFFF80 )
{
bytes = new byte[1];
bytes[0] = ( byte ) value;
}
else if ( value >= 0xFFFF8000 )
{
bytes = new byte[2];
bytes[1] = ( byte ) ( value );
bytes[0] = ( byte ) ( value >> 8 );
}
else if ( value >= 0xFF800000 )
{
bytes = new byte[3];
bytes[2] = ( byte ) value;
bytes[1] = ( byte ) ( value >> 8 );
bytes[0] = ( byte ) ( value >> 16 );
}
else
{
bytes = new byte[4];
bytes[3] = ( byte ) value;
bytes[2] = ( byte ) ( value >> 8 );
bytes[1] = ( byte ) ( value >> 16 );
bytes[0] = ( byte ) ( value >> 24 );
}
}
}
return bytes;
}
/**
* Utility function that return a byte array representing the Value.
* We must respect the ASN.1 BER encoding scheme : <br>
* <pre>
* 1) positive integer
* - [0 - 0x7F] : 0xVV
* - [0x80 - 0xFF] : 0x00 0xVV
* - [0x0100 - 0x7FFF] : 0xVV 0xVV
* - [0x8000 - 0xFFFF] : 0x00 0xVV 0xVV
* - [0x010000 - 0x7FFFFF] : 0xVV 0xVV 0xVV
* - [0x800000 - 0xFFFFFF] : 0x00 0xVV 0xVV 0xVV
* - [0x01000000 - 0x7FFFFFFF] : 0xVV 0xVV 0xVV 0xVV
* 2) Negative number - (~value) + 1
* </pre>
* They are encoded following the table (the <br>
* encode bytes are those enclosed by squared braquets) :<br>
* <br>
* <pre>
* -1 -&gt; FF FF FF FF FF FF FF [FF]
* -127 -&gt; FF FF FF FF FF FF FF [81]
* -128 -&gt; FF FF FF FF FF FF FF [80]
* -129 -&gt; FF FF FF FF FF FF [FF 7F]
* -255 -&gt; FF FF FF FF FF FF [FF 01]
* -256 -&gt; FF FF FF FF FF FF [FF 00]
* -257 -&gt; FF FF FF FF FF FF [FE FF]
* -32767 -&gt; FF FF FF FF FF FF [80 01]
* -32768 -&gt; FF FF FF FF FF FF [80 00]
* -32769 -&gt; FF FF FF FF FF [FF 7F FF]
* -65535 -&gt; FF FF FF FF FF [FF 00 01]
* -65536 -&gt; FF FF FF FF FF [FF 00 00]
* -65537 -&gt; FF FF FF FF FF [FE FF FF]
* -8388607 -&gt; FF FF FF FF FF [80 00 01]
* -8388608 -&gt; FF FF FF FF FF [80 00 00]
* -8388609 -&gt; FF FF FF FF [FF 7F FF FF]
* -16777215 -&gt; FF FF FF FF [FF 00 00 01]
* -16777216 -&gt; FF FF FF FF [FF 00 00 00]
* -16777217 -&gt; FF FF FF FF [FE FF FF FF]
* -2147483647 -&gt; FF FF FF FF [80 00 00 01]
* -2147483648 -&gt; FF FF FF FF [80 00 00 00]
* -2147483649 -&gt; FF FF FF [FF 7F FF FF FF]
* -4294967295 -&gt; FF FF FF [FF 00 00 00 01]
* -4294967296 -&gt; FF FF FF [FF 00 00 00 00]
* -4294967297 -&gt; FF FF FF [FE FF FF FF FF]
* -549755813887 -&gt; FF FF FF [80 00 00 00 01]
* -549755813888 -&gt; FF FF FF [80 00 00 00 00]
* -549755813889 -&gt; FF FF [FF 7F FF FF FF FF]
* -1099511627775 -&gt; FF FF [FF 00 00 00 00 01]
* -1099511627776 -&gt; FF FF [FF 00 00 00 00 00]
* -1099511627777 -&gt; FF FF [FE FF FF FF FF FF]
* -140737488355327 -&gt; FF FF [80 00 00 00 00 01]
* -140737488355328 -&gt; FF FF [80 00 00 00 00 00]
* -140737488355329 -&gt; FF [FF 7F FF FF FF FF FF]
* -281474976710655 -&gt; FF [FF 00 00 00 00 00 01]
* -281474976710656 -&gt; FF [FF 00 00 00 00 00 00]
* -281474976710657 -&gt; FF [FE FF FF FF FF FF FF]
* -36028797018963967 -&gt; FF [80 00 00 00 00 00 01]
* -36028797018963968 -&gt; FF [80 00 00 00 00 00 00]
* -36028797018963969 -&gt; [FF 7F FF FF FF FF FF FF]
* -72057594037927936 -&gt; [FF 00 00 00 00 00 00 00]
* -72057594037927937 -&gt; [FE FF FF FF FF FF FF FF]
* -9223372036854775807 -&gt; [80 00 00 00 00 00 00 01]
* -9223372036854775808 -&gt; [80 00 00 00 00 00 00 00]
* </pre>
* @param value The value to store in a byte array
* @return The byte array representing the value.
*/
public static byte[] getBytes( long value )
{
byte[] bytes;
if ( value >= 0 )
{
if ( ( value >= 0 ) && ( value <= ONE_BYTE_MAX ) )
{
bytes = new byte[1];
bytes[0] = ( byte ) value;
}
else if ( ( value > ONE_BYTE_MAX ) && ( value <= TWO_BYTE_MAX ) )
{
bytes = new byte[2];
bytes[1] = ( byte ) value;
bytes[0] = ( byte ) ( value >> 8 );
}
else if ( ( value > TWO_BYTE_MAX ) && ( value <= THREE_BYTE_MAX ) )
{
bytes = new byte[3];
bytes[2] = ( byte ) value;
bytes[1] = ( byte ) ( value >> 8 );
bytes[0] = ( byte ) ( value >> 16 );
}
else if ( ( value > THREE_BYTE_MAX ) && ( value <= FOUR_BYTE_MAX ) )
{
bytes = new byte[4];
bytes[3] = ( byte ) value;
bytes[2] = ( byte ) ( value >> 8 );
bytes[1] = ( byte ) ( value >> 16 );
bytes[0] = ( byte ) ( value >> 24 );
}
else if ( ( value > FOUR_BYTE_MAX ) && ( value <= FIVE_BYTE_MAX ) )
{
bytes = new byte[5];
bytes[4] = ( byte ) value;
bytes[3] = ( byte ) ( value >> 8 );
bytes[2] = ( byte ) ( value >> 16 );
bytes[1] = ( byte ) ( value >> 24 );
bytes[0] = ( byte ) ( value >> 32 );
}
else if ( ( value > FIVE_BYTE_MAX ) && ( value <= SIX_BYTE_MAX ) )
{
bytes = new byte[6];
bytes[5] = ( byte ) value;
bytes[4] = ( byte ) ( value >> 8 );
bytes[3] = ( byte ) ( value >> 16 );
bytes[2] = ( byte ) ( value >> 24 );
bytes[1] = ( byte ) ( value >> 32 );
bytes[0] = ( byte ) ( value >> 40 );
}
else if ( ( value > SIX_BYTE_MAX ) && ( value <= SEVEN_BYTE_MAX ) )
{
bytes = new byte[7];
bytes[6] = ( byte ) value;
bytes[5] = ( byte ) ( value >> 8 );
bytes[4] = ( byte ) ( value >> 16 );
bytes[3] = ( byte ) ( value >> 24 );
bytes[2] = ( byte ) ( value >> 32 );
bytes[1] = ( byte ) ( value >> 40 );
bytes[0] = ( byte ) ( value >> 48 );
}
else
{
bytes = new byte[8];
bytes[7] = ( byte ) value;
bytes[6] = ( byte ) ( value >> 8 );
bytes[5] = ( byte ) ( value >> 16 );
bytes[4] = ( byte ) ( value >> 24 );
bytes[3] = ( byte ) ( value >> 32 );
bytes[2] = ( byte ) ( value >> 40 );
bytes[1] = ( byte ) ( value >> 48 );
bytes[0] = ( byte ) ( value >> 56 );
}
}
else
{
// On special case : 0x80000000
if ( value == 0x8000000000000000L )
{
bytes = new byte[8];
bytes[7] = ( byte ) 0x00;
bytes[6] = ( byte ) 0x00;
bytes[5] = ( byte ) 0x00;
bytes[4] = ( byte ) 0x00;
bytes[3] = ( byte ) 0x00;
bytes[2] = ( byte ) 0x00;
bytes[1] = ( byte ) 0x00;
bytes[0] = ( byte ) 0x80;
}
else
{
// We have to compute the complement, and add 1
if ( value >= 0xFFFFFFFFFFFFFF80L )
{
bytes = new byte[1];
bytes[0] = ( byte ) value;
}
else if ( value >= 0xFFFFFFFFFFFF8000L )
{
bytes = new byte[2];
bytes[1] = ( byte ) ( value );
bytes[0] = ( byte ) ( value >> 8 );
}
else if ( value >= 0xFFFFFFFFFF800000L )
{
bytes = new byte[3];
bytes[2] = ( byte ) value;
bytes[1] = ( byte ) ( value >> 8 );
bytes[0] = ( byte ) ( value >> 16 );
}
else if ( value >= 0xFFFFFFFF80000000L )
{
bytes = new byte[4];
bytes[3] = ( byte ) value;
bytes[2] = ( byte ) ( value >> 8 );
bytes[1] = ( byte ) ( value >> 16 );
bytes[0] = ( byte ) ( value >> 24 );
}
else if ( value >= 0xFFFFFF8000000000L )
{
bytes = new byte[5];
bytes[4] = ( byte ) value;
bytes[3] = ( byte ) ( value >> 8 );
bytes[2] = ( byte ) ( value >> 16 );
bytes[1] = ( byte ) ( value >> 24 );
bytes[0] = ( byte ) ( value >> 32 );
}
else if ( value >= 0xFFFF800000000000L )
{
bytes = new byte[6];
bytes[5] = ( byte ) value;
bytes[4] = ( byte ) ( value >> 8 );
bytes[3] = ( byte ) ( value >> 16 );
bytes[2] = ( byte ) ( value >> 24 );
bytes[1] = ( byte ) ( value >> 32 );
bytes[0] = ( byte ) ( value >> 40 );
}
else if ( value >= 0xFF80000000000000L )
{
bytes = new byte[7];
bytes[6] = ( byte ) value;
bytes[5] = ( byte ) ( value >> 8 );
bytes[4] = ( byte ) ( value >> 16 );
bytes[3] = ( byte ) ( value >> 24 );
bytes[2] = ( byte ) ( value >> 32 );
bytes[1] = ( byte ) ( value >> 40 );
bytes[0] = ( byte ) ( value >> 48 );
}
else
{
bytes = new byte[8];
bytes[7] = ( byte ) value;
bytes[6] = ( byte ) ( value >> 8 );
bytes[5] = ( byte ) ( value >> 16 );
bytes[4] = ( byte ) ( value >> 24 );
bytes[3] = ( byte ) ( value >> 32 );
bytes[2] = ( byte ) ( value >> 40 );
bytes[1] = ( byte ) ( value >> 48 );
bytes[0] = ( byte ) ( value >> 56 );
}
}
}
return bytes;
}
/**
* Encode a boolean value
*
* @param buffer The PDU in which the value will be put
* @param bool The boolean to be encoded
*/
public static void encodeBoolean( Asn1Buffer buffer, boolean bool )
{
if ( bool )
{
buffer.put( ENCODED_TRUE );
}
else
{
buffer.put( ENCODED_FALSE );
}
}
/**
* Encode a boolean value
*
* @param buffer The PDU in which the value will be put
* @param tag the TAG to use
* @param bool The boolean to be encoded
*/
public static void encodeBoolean( Asn1Buffer buffer, byte tag, boolean bool )
{
if ( bool )
{
buffer.put( TRUE_VALUE );
buffer.put( ( byte ) 0x01 );
buffer.put( tag );
}
else
{
buffer.put( FALSE_VALUE );
buffer.put( ( byte ) 0x01 );
buffer.put( tag );
}
}
/**
* Encode an integer value
*
* @param buffer The PDU in which the value will be put
* @param value The integer to be encoded
*/
public static void encodeInteger( Asn1Buffer buffer, int value )
{
buffer.put( getBytes( value ) );
buffer.put( ( byte ) getNbBytes( value ) );
buffer.put( UniversalTag.INTEGER.getValue() );
}
/**
* Encode an integer value, with a specific tag
*
* @param buffer The PDU in which the value will be put
* @param tag The tag to use
* @param value The integer to be encoded
*/
public static void encodeInteger( Asn1Buffer buffer, byte tag, int value )
{
buffer.put( getBytes( value ) );
buffer.put( ( byte ) getNbBytes( value ) );
buffer.put( tag );
}
/**
* Encode an integer value
*
* @param buffer The PDU in which the value will be put
* @param value The long to be encoded
*/
public static void encodeInteger( Asn1Buffer buffer, long value )
{
buffer.put( getBytes( value ) );
buffer.put( ( byte ) getNbBytes( value ) );
buffer.put( UniversalTag.INTEGER.getValue() );
}
/**
* Encode an integer value, with a specific tag
*
* @param buffer The PDU in which the value will be put
* @param tag The tag to use
* @param value The long to be encoded
*/
public static void encodeInteger( Asn1Buffer buffer, byte tag, long value )
{
buffer.put( getBytes( value ) );
buffer.put( ( byte ) getNbBytes( value ) );
buffer.put( tag );
}
/**
* Encode an OctetString
*
* @param buffer The PDU in which the value will be put
* @param data The byte[] to be encoded
*/
public static void encodeOctetString( Asn1Buffer buffer, byte[] data )
{
if ( Strings.isEmpty( data ) )
{
buffer.put( ( byte ) 0 );
}
else
{
buffer.put( data );
buffer.put( TLV.getBytes( data.length ) );
}
buffer.put( UniversalTag.OCTET_STRING.getValue() );
}
/**
* Encode an OctetString
*
* @param buffer The PDU in which the value will be put
* @param value The String to be encoded
*/
public static void encodeOctetString( Asn1Buffer buffer, String value )
{
if ( Strings.isEmpty( value ) )
{
buffer.put( ( byte ) 0 );
}
else
{
byte[] bytes = Strings.getBytesUtf8Ascii( value );
buffer.put( bytes );
buffer.put( TLV.getBytes( bytes.length ) );
}
buffer.put( UniversalTag.OCTET_STRING.getValue() );
}
/**
* Encode an OctetString
*
* @param buffer The PDU in which the value will be put
* @param tag The tag to use
* @param data The OctetString to be encoded
*/
public static void encodeOctetString( Asn1Buffer buffer, byte tag, byte[] data )
{
if ( Strings.isEmpty( data ) )
{
buffer.put( ( byte ) 0 );
}
else
{
buffer.put( data );
buffer.put( TLV.getBytes( data.length ) );
}
buffer.put( tag );
}
/**
* Encode an OctetString
*
* @param buffer The PDU in which the value will be put
* @param tag The tag to use
* @param value The OctetString to be encoded
*/
public static void encodeOctetString( Asn1Buffer buffer, byte tag, String value )
{
if ( Strings.isEmpty( value ) )
{
buffer.put( ( byte ) 0 );
}
else
{
byte[] bytes = Strings.getBytesUtf8Ascii( value );
buffer.put( bytes );
buffer.put( TLV.getBytes( bytes.length ) );
}
buffer.put( tag );
}
/**
* Encode a Sequence
*
* @param buffer The PDU in which the Sequence will be put
*/
public static void encodeSequence( Asn1Buffer buffer )
{
buffer.put( TLV.getBytes( buffer.getPos() ) );
buffer.put( UniversalTag.SEQUENCE.getValue() );
}
/**
* Encode a Sequence, with a specific length
*
* @param buffer The PDU in which the Sequence will be put
* @param start The Sequence length
*/
public static void encodeSequence( Asn1Buffer buffer, int start )
{
buffer.put( TLV.getBytes( buffer.getPos() - start ) );
buffer.put( UniversalTag.SEQUENCE.getValue() );
}
/**
* Encode a Sequence, with a specific tag
*
* @param buffer The PDU in which the Sequence will be put
* @param tag The tag to use
*/
public static void encodeSequence( Asn1Buffer buffer, byte tag )
{
buffer.put( TLV.getBytes( buffer.getPos() ) );
buffer.put( tag );
}
/**
* Encode a Sequence, with a specific length and tag
*
* @param buffer The PDU in which the Sequence will be put
* @param tag The tag to use
* @param start The position in the buffer this Sequence starts
*/
public static void encodeSequence( Asn1Buffer buffer, byte tag, int start )
{
buffer.put( TLV.getBytes( buffer.getPos() - start ) );
buffer.put( tag );
}
/**
* Encode a Set
*
* @param buffer The PDU in which the Set will be put
*/
public static void encodeSet( Asn1Buffer buffer )
{
buffer.put( TLV.getBytes( buffer.getPos() ) );
buffer.put( UniversalTag.SET.getValue() );
}
/**
* Encode a Set, with a specific length
*
* @param buffer The PDU in which the Set will be put
* @param start The Set length
*/
public static void encodeSet( Asn1Buffer buffer, int start )
{
buffer.put( TLV.getBytes( buffer.getPos() - start ) );
buffer.put( UniversalTag.SET.getValue() );
}
/**
* Encode a Set, with a specific tag
*
* @param buffer The PDU in which the value will be put
* @param tag The tag to use
*/
public static void encodeSet( Asn1Buffer buffer, byte tag )
{
buffer.put( TLV.getBytes( buffer.getPos() ) );
buffer.put( tag );
}
/**
* Encode a Set, with a specific length and tag
*
* @param buffer The PDU in which the set will be put
* @param tag The tag to use
* @param start The position in the buffer this Set starts
*/
public static void encodeSet( Asn1Buffer buffer, byte tag, int start )
{
buffer.put( TLV.getBytes( buffer.getPos() - start ) );
buffer.put( tag );
}
/**
* Encode a String value
*
* @param buffer The PDU in which the value will be put
* @param string The String to be encoded. It is supposed to be UTF-8
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encode( ByteBuffer buffer, String string ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
buffer.put( UniversalTag.OCTET_STRING.getValue() );
byte[] value = Asn1StringUtils.getBytesUtf8( string );
buffer.put( TLV.getBytes( value.length ) );
if ( value.length != 0 )
{
buffer.put( value );
}
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Encode a BIT STRING value
*
* @param buffer The PDU in which the value will be put
* @param bitString The BitString to be encoded.
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encode( ByteBuffer buffer, BitString bitString ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
buffer.put( UniversalTag.BIT_STRING.getValue() );
// The BitString length. We add one byte for the unused number
// of bits
byte[] bytes = bitString.getData();
int length = bytes.length;
buffer.put( TLV.getBytes( length ) );
buffer.put( bytes );
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Encode an OctetString value
*
* @param buffer The PDU in which the value will be put
* @param bytes The bytes to be encoded
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encode( ByteBuffer buffer, byte[] bytes ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
buffer.put( UniversalTag.OCTET_STRING.getValue() );
if ( ( bytes == null ) || ( bytes.length == 0 ) )
{
buffer.put( ( byte ) 0 );
}
else
{
buffer.put( TLV.getBytes( bytes.length ) );
buffer.put( bytes );
}
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Encode an OID value
*
* @param buffer The PDU in which the value will be put
* @param oid The OID to be encoded
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encode( ByteBuffer buffer, Oid oid ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
buffer.put( UniversalTag.OCTET_STRING.getValue() );
buffer.put( TLV.getBytes( oid.getEncodedLength() ) );
if ( oid.getEncodedLength() != 0 )
{
oid.writeBytesTo( buffer );
}
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Encode an integer value
*
* @param buffer The PDU in which the value will be put
* @param value The integer to be encoded
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encode( ByteBuffer buffer, int value ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
buffer.put( UniversalTag.INTEGER.getValue() );
buffer.put( ( byte ) getNbBytes( value ) );
buffer.put( getBytes( value ) );
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Encode a long value
*
* @param buffer The PDU in which the value will be put
* @param value The long to be encoded
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encode( ByteBuffer buffer, long value ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
buffer.put( UniversalTag.INTEGER.getValue() );
buffer.put( ( byte ) getNbBytes( value ) );
buffer.put( getBytes( value ) );
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Encode an integer value
*
* @param buffer The PDU in which the value will be put
* @param tag The tag if it's not an UNIVERSAL one
* @param value The integer to be encoded
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encode( ByteBuffer buffer, byte tag, int value ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
buffer.put( tag );
buffer.put( ( byte ) getNbBytes( value ) );
buffer.put( getBytes( value ) );
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Encode an enumerated value
*
* @param buffer The PDU in which the value will be put
* @param value The integer to be encoded
*/
public static void encodeEnumerated( Asn1Buffer buffer, int value )
{
buffer.put( getBytes( value ) );
buffer.put( TLV.getBytes( getNbBytes( value ) ) );
buffer.put( UniversalTag.ENUMERATED.getValue() );
}
/**
* Encode an enumerated value
*
* @param buffer The PDU in which the value will be put
* @param tag The tag to use
* @param value The integer to be encoded
*/
public static void encodeEnumerated( Asn1Buffer buffer, byte tag, int value )
{
buffer.put( getBytes( value ) );
buffer.put( TLV.getBytes( getNbBytes( value ) ) );
buffer.put( tag );
}
/**
* Encode an enumerated value
*
* @param buffer The PDU in which the value will be put
* @param value The integer to be encoded
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encodeEnumerated( ByteBuffer buffer, int value ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
buffer.put( UniversalTag.ENUMERATED.getValue() );
buffer.put( TLV.getBytes( getNbBytes( value ) ) );
buffer.put( getBytes( value ) );
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Encode a boolean value
*
* @param buffer The PDU in which the value will be put
* @param bool The boolean to be encoded
* @throws EncoderException if the PDU in which the value should be encoded is
* two small
*/
public static void encode( ByteBuffer buffer, boolean bool ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_01300_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
}
try
{
if ( bool )
{
buffer.put( ENCODED_TRUE );
}
else
{
buffer.put( ENCODED_FALSE );
}
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_01301_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
}
}
/**
* Return a string representing the Value
*
* @return A string representing the value
*/
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( "DATA" );
if ( data != null )
{
sb.append( '[' );
sb.append( Asn1StringUtils.dumpBytes( data ) );
sb.append( ']' );
}
else
{
return "[]";
}
return sb.toString();
}
}