FileDocCategorySizeDatePackage
NumberVariableLength.javaAPI DocJaudiotagger 2.0.47323Wed Mar 30 16:12:12 BST 2011org.jaudiotagger.tag.datatype

NumberVariableLength

public class NumberVariableLength extends AbstractDataType
Represents a number which may span a number of bytes when written to file depending what size is to be represented.

The bitorder in ID3v2 is most significant bit first (MSB). The byteorder in multibyte numbers is most significant byte first (e.g. $12345678 would be encoded $12 34 56 78), also known as big endian and network byte order.

In ID3Specification would be denoted as $xx xx xx xx (xx ...) , this denotes at least four bytes but may be more. Sometimes may be completely optional (zero bytes)

Fields Summary
private static final int
MINIMUM_NO_OF_DIGITS
private static final int
MAXIMUM_NO_OF_DIGITS
int
minLength
Constructors Summary
public NumberVariableLength(String identifier, org.jaudiotagger.tag.id3.AbstractTagFrameBody frameBody, int minimumSize)
Creates a new ObjectNumberVariableLength datatype, set minimum length to zero if this datatype is optional.

param
identifier
param
frameBody
param
minimumSize



                              
          
    
        super(identifier, frameBody);

        //Set minimum length, which can be zero if optional
        this.minLength = minimumSize;

    
public NumberVariableLength(NumberVariableLength copy)

        super(copy);
        this.minLength = copy.minLength;
    
Methods Summary
public booleanequals(java.lang.Object obj)

param
obj
return

        if (!(obj instanceof NumberVariableLength))
        {
            return false;
        }

        NumberVariableLength object = (NumberVariableLength) obj;

        return this.minLength == object.minLength && super.equals(obj);

    
public intgetMaximumLenth()
Return the maximum number of digits that can be used to express the number

return
the maximum number of digits that can be used to express the number

        return MAXIMUM_NO_OF_DIGITS;
    
public intgetMinimumLength()
Return the minimum number of digits that can be used to express the number

return
the minimum number of digits that can be used to express the number

        return minLength;
    
public intgetSize()

return
the number of bytes required to write this to a file

        if (value == null)
        {
            return 0;
        }
        else
        {
            int current;
            long temp = ID3Tags.getWholeNumber(value);
            int size = 0;

            for (int i = MINIMUM_NO_OF_DIGITS; i <= MAXIMUM_NO_OF_DIGITS; i++)
            {
                current = (byte) temp & 0xFF;

                if (current != 0)
                {
                    size = i;
                }

                temp >>= MAXIMUM_NO_OF_DIGITS;
            }

            return (minLength > size) ? minLength : size;
        }
    
public voidreadByteArray(byte[] arr, int offset)
Read from Byte Array

param
arr
param
offset
throws
NullPointerException
throws
IndexOutOfBoundsException

        //Coding error, should never happen
        if (arr == null)
        {
            throw new NullPointerException("Byte array is null");
        }

        //Coding error, should never happen as far as I can see
        if (offset < 0)
        {
            throw new IllegalArgumentException("negativer offset into an array offset:" + offset);
        }

        //If optional then set value to zero, this will mean that if this frame is written back to file it will be created
        //with this additional datatype wheras it didnt exist but I think this is probably an advantage the frame is
        //more likely to be parsed by other applications if it contains optional fields.
        //if not optional problem with this frame
        if (offset >= arr.length)
        {
            if (minLength == 0)
            {
                value = (long) 0;
                return;
            }
            else
            {
                throw new InvalidDataTypeException("Offset to byte array is out of bounds: offset = " + offset + ", array.length = " + arr.length);
            }
        }

        long lvalue = 0;

        //Read the bytes (starting from offset), the most significant byte of the number being constructed is read first,
        //we then shift the resulting long one byte over to make room for the next byte
        for (int i = offset; i < arr.length; i++)
        {
            lvalue <<= 8;
            lvalue += (arr[i] & 0xff);
        }

        value = lvalue;
    
public voidsetMinimumSize(int minimumSize)

param
minimumSize

        if (minimumSize > 0)
        {
            this.minLength = minimumSize;
        }
    
public java.lang.StringtoString()

return
String representation of the number

        if (value == null)
        {
            return "";
        }
        else
        {
            return value.toString();
        }
    
public byte[]writeByteArray()
Write to Byte Array

return
the datatype converted to a byte array

        int size = getSize();
        byte[] arr;

        if (size == 0)
        {
            arr = new byte[0];
        }
        else
        {
            long temp = ID3Tags.getWholeNumber(value);
            arr = new byte[size];

            //keeps shifting the number downwards and masking the last 8 bist to get the value for the next byte
            //to be written
            for (int i = size - 1; i >= 0; i--)
            {
                arr[i] = (byte) (temp & 0xFF);
                temp >>= 8;
            }
        }
        return arr;