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