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 {
EncodedValueCodec()26     private EncodedValueCodec() {
27     }
28 
29     /**
30      * Writes a signed integral to {@code out}.
31      */
writeSignedIntegralValue(ByteOutput out, int type, long value)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      */
writeUnsignedIntegralValue(ByteOutput out, int type, long value)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      */
writeRightZeroExtendedValue(ByteOutput out, int type, long value)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      */
readSignedInt(ByteInput in, int zwidth)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      */
readUnsignedInt(ByteInput in, int zwidth, boolean fillOnRight)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      */
readSignedLong(ByteInput in, int zwidth)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      */
readUnsignedLong(ByteInput in, int zwidth, boolean fillOnRight)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