Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.dex;
     18 
     19 import com.android.dex.util.ByteInput;
     20 import com.android.dex.util.ByteOutput;
     21 
     22 /**
     23  * Read and write {@code encoded_value} primitives.
     24  */
     25 public final class EncodedValueCodec {
     26     private EncodedValueCodec() {
     27     }
     28 
     29     /**
     30      * Writes a signed integral to {@code out}.
     31      */
     32     public static void writeSignedIntegralValue(ByteOutput out, int type, long value) {
     33         /*
     34          * Figure out how many bits are needed to represent the value,
     35          * including a sign bit: The bit count is subtracted from 65
     36          * and not 64 to account for the sign bit. The xor operation
     37          * has the effect of leaving non-negative values alone and
     38          * unary complementing negative values (so that a leading zero
     39          * count always returns a useful number for our present
     40          * purpose).
     41          */
     42         int requiredBits = 65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
     43 
     44         // Round up the requiredBits to a number of bytes.
     45         int requiredBytes = (requiredBits + 0x07) >> 3;
     46 
     47         /*
     48          * Write the header byte, which includes the type and
     49          * requiredBytes - 1.
     50          */
     51         out.writeByte(type | ((requiredBytes - 1) << 5));
     52 
     53         // Write the value, per se.
     54         while (requiredBytes > 0) {
     55             out.writeByte((byte) value);
     56             value >>= 8;
     57             requiredBytes--;
     58         }
     59     }
     60 
     61     /**
     62      * Writes an unsigned integral to {@code out}.
     63      */
     64     public static void writeUnsignedIntegralValue(ByteOutput out, int type, long value) {
     65         // Figure out how many bits are needed to represent the value.
     66         int requiredBits = 64 - Long.numberOfLeadingZeros(value);
     67         if (requiredBits == 0) {
     68             requiredBits = 1;
     69         }
     70 
     71         // Round up the requiredBits to a number of bytes.
     72         int requiredBytes = (requiredBits + 0x07) >> 3;
     73 
     74         /*
     75          * Write the header byte, which includes the type and
     76          * requiredBytes - 1.
     77          */
     78         out.writeByte(type | ((requiredBytes - 1) << 5));
     79 
     80         // Write the value, per se.
     81         while (requiredBytes > 0) {
     82             out.writeByte((byte) value);
     83             value >>= 8;
     84             requiredBytes--;
     85         }
     86     }
     87 
     88     /**
     89      * Writes a right-zero-extended value to {@code out}.
     90      */
     91     public static void writeRightZeroExtendedValue(ByteOutput out, int type, long value) {
     92         // Figure out how many bits are needed to represent the value.
     93         int requiredBits = 64 - Long.numberOfTrailingZeros(value);
     94         if (requiredBits == 0) {
     95             requiredBits = 1;
     96         }
     97 
     98         // Round up the requiredBits to a number of bytes.
     99         int requiredBytes = (requiredBits + 0x07) >> 3;
    100 
    101         // Scootch the first bits to be written down to the low-order bits.
    102         value >>= 64 - (requiredBytes * 8);
    103 
    104         /*
    105          * Write the header byte, which includes the type and
    106          * requiredBytes - 1.
    107          */
    108         out.writeByte(type | ((requiredBytes - 1) << 5));
    109 
    110         // Write the value, per se.
    111         while (requiredBytes > 0) {
    112             out.writeByte((byte) value);
    113             value >>= 8;
    114             requiredBytes--;
    115         }
    116     }
    117 
    118     /**
    119      * Read a signed integer.
    120      *
    121      * @param zwidth byte count minus one
    122      */
    123     public static int readSignedInt(ByteInput in, int zwidth) {
    124         int result = 0;
    125         for (int i = zwidth; i >= 0; i--) {
    126             result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
    127         }
    128         result >>= (3 - zwidth) * 8;
    129         return result;
    130     }
    131 
    132     /**
    133      * Read an unsigned integer.
    134      *
    135      * @param zwidth byte count minus one
    136      * @param fillOnRight true to zero fill on the right; false on the left
    137      */
    138     public static int readUnsignedInt(ByteInput in, int zwidth, boolean fillOnRight) {
    139         int result = 0;
    140         if (!fillOnRight) {
    141             for (int i = zwidth; i >= 0; i--) {
    142                 result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
    143             }
    144             result >>>= (3 - zwidth) * 8;
    145         } else {
    146             for (int i = zwidth; i >= 0; i--) {
    147                 result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
    148             }
    149         }
    150         return result;
    151     }
    152 
    153     /**
    154      * Read a signed long.
    155      *
    156      * @param zwidth byte count minus one
    157      */
    158     public static long readSignedLong(ByteInput in, int zwidth) {
    159         long result = 0;
    160         for (int i = zwidth; i >= 0; i--) {
    161             result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
    162         }
    163         result >>= (7 - zwidth) * 8;
    164         return result;
    165     }
    166 
    167     /**
    168      * Read an unsigned long.
    169      *
    170      * @param zwidth byte count minus one
    171      * @param fillOnRight true to zero fill on the right; false on the left
    172      */
    173     public static long readUnsignedLong(ByteInput in, int zwidth, boolean fillOnRight) {
    174         long result = 0;
    175         if (!fillOnRight) {
    176             for (int i = zwidth; i >= 0; i--) {
    177                 result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
    178             }
    179             result >>>= (7 - zwidth) * 8;
    180         } else {
    181             for (int i = zwidth; i >= 0; i--) {
    182                 result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
    183             }
    184         }
    185         return result;
    186     }
    187 }
    188