Coverage Report - org.jaudiotagger.tag.id3.ID3SyncSafeInteger
 
Classes in this File Line Coverage Branch Coverage Complexity
ID3SyncSafeInteger
95%
20/21
100%
8/8
2.2
 
 1  
 package org.jaudiotagger.tag.id3;
 2  
 
 3  
 import java.nio.ByteBuffer;
 4  
 
 5  
 /**
 6  
  * Peforms encoding/decoding of an syncsafe integer
 7  
  * <p/>
 8  
  * <p>Syncsafe integers are used for the size in the tag header of v23 and v24 tags, and in the frame size in
 9  
  * the frame header of v24 frames.
 10  
  * <p/>
 11  
  * <p>In some parts of the tag it is inconvenient to use the
 12  
  * unsychronisation scheme because the size of unsynchronised data is
 13  
  * not known in advance, which is particularly problematic with size
 14  
  * descriptors. The solution in ID3v2 is to use synchsafe integers, in
 15  
  * which there can never be any false synchs. Synchsafe integers are
 16  
  * integers that keep its highest bit (bit 7) zeroed, making seven bits
 17  
  * out of eight available. Thus a 32 bit synchsafe integer can store 28
 18  
  * bits of information.
 19  
  * <p/>
 20  
  * Example:
 21  
  * <p/>
 22  
  * 255 (%11111111) encoded as a 16 bit synchsafe integer is 383
 23  
  * (%00000001 01111111).
 24  
  */
 25  0
 public class ID3SyncSafeInteger
 26  
 {
 27  
     public static final int INTEGRAL_SIZE = 4;
 28  
 
 29  
     /**
 30  
      * Sizes equal or smaller than this are the same whether held as sync safe integer or normal integer so
 31  
      * it doesnt matter.
 32  
      */
 33  
     public static final int MAX_SAFE_SIZE = 127;
 34  
 
 35  
     /**
 36  
      * Read syncsafe value from byteArray in format specified in spec and convert to int.
 37  
      *
 38  
      * @param buffer syncsafe integer
 39  
      * @return decoded int
 40  
      */
 41  
     private static int bufferToValue(byte[] buffer)
 42  
     {
 43  
         //Note Need to && with 0xff otherwise if value is greater than 128 we get a negative number
 44  
         //when cast byte to int
 45  6132
         return ((buffer[0] & 0xff) << 21) + ((buffer[1] & 0xff) << 14) + ((buffer[2] & 0xff) << 7) + ((buffer[3]) & 0xff);
 46  
     }
 47  
 
 48  
     /**
 49  
      * Read syncsafe value from buffer in format specified in spec and convert to int.
 50  
      * <p/>
 51  
      * The buffers position is moved to just after the location of the syscsafe integer
 52  
      *
 53  
      * @param buffer syncsafe integer
 54  
      * @return decoded int
 55  
      */
 56  
     protected static int bufferToValue(ByteBuffer buffer)
 57  
     {
 58  6132
         byte byteBuffer[] = new byte[INTEGRAL_SIZE];
 59  6132
         buffer.get(byteBuffer, 0, INTEGRAL_SIZE);
 60  6132
         return bufferToValue(byteBuffer);
 61  
     }
 62  
 
 63  
     /**
 64  
      * Is buffer holding a value that is definently not syncsafe
 65  
      * <p/>
 66  
      * We cannot guarantee a buffer is holding a syncsafe integer but there are some checks
 67  
      * we can do to show that it definently is not.
 68  
      * <p/>
 69  
      * The buffer is NOT moved after reading.
 70  
      * <p/>
 71  
      * This function is useful for reading ID3v24 frames created in iTunes because iTunes does not use syncsafe
 72  
      * integers in  its frames.
 73  
      *
 74  
      * @param buffer
 75  
      * @return true if this buffer is definently not holding a syncsafe integer
 76  
      */
 77  
     protected static boolean isBufferNotSyncSafe(ByteBuffer buffer)
 78  
     {
 79  189
         int position = buffer.position();
 80  
 
 81  
         //Check Bit7 not set
 82  921
         for (int i = 0; i < INTEGRAL_SIZE; i++)
 83  
         {
 84  748
             byte nextByte = buffer.get(position + i);
 85  748
             if ((nextByte & 0x80) > 0)
 86  
             {
 87  16
                 return true;
 88  
             }
 89  
         }
 90  173
         return false;
 91  
     }
 92  
 
 93  
     /**
 94  
      * Checks if the buffer just contains zeros
 95  
      * <p/>
 96  
      * This can be used to identify when accessing padding of a tag
 97  
      *
 98  
      * @param buffer
 99  
      * @return true if buffer only contains zeros
 100  
      */
 101  
     protected static boolean isBufferEmpty(byte[] buffer)
 102  
     {
 103  332
         for (byte aBuffer : buffer)
 104  
         {
 105  268
             if (aBuffer != 0)
 106  
             {
 107  12
                 return false;
 108  
             }
 109  
         }
 110  64
         return true;
 111  
     }
 112  
 
 113  
     /**
 114  
      * Convert int value to syncsafe value held in bytearray
 115  
      *
 116  
      * @param size
 117  
      * @return buffer syncsafe integer
 118  
      */
 119  
     protected static byte[] valueToBuffer(int size)
 120  
     {
 121  3133
         byte[] buffer = new byte[4];
 122  3133
         buffer[0] = (byte) ((size & 0x0FE00000) >> 21);
 123  3133
         buffer[1] = (byte) ((size & 0x001FC000) >> 14);
 124  3133
         buffer[2] = (byte) ((size & 0x00003F80) >> 7);
 125  3133
         buffer[3] = (byte) (size & 0x0000007F);
 126  3133
         return buffer;
 127  
     }
 128  
 }