Home | History | Annotate | Download | only in rawdex
      1 /*
      2  * Copyright (C) 2014 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 dexfuzz.rawdex;
     18 
     19 import java.io.IOException;
     20 
     21 public class EncodedValue implements RawDexObject {
     22   public byte valueArg;
     23   public byte valueType;
     24   public byte[] value;
     25   public EncodedArray encodedArray;
     26   public EncodedAnnotation encodedAnnotation;
     27 
     28   private static final byte VALUE_BYTE = 0x00;
     29   private static final byte VALUE_ARRAY = 0x1c;
     30   private static final byte VALUE_ANNOTATION = 0x1d;
     31   private static final byte VALUE_NULL = 0x1e;
     32   private static final byte VALUE_BOOLEAN = 0x1f;
     33 
     34   @Override
     35   public void read(DexRandomAccessFile file) throws IOException {
     36     int valueArgAndType = file.readUnsignedByte();
     37 
     38     // Get lower 5 bits.
     39     valueType = (byte) (valueArgAndType & 0x1f);
     40     // Get upper 3 bits.
     41     valueArg = (byte) ((valueArgAndType & 0xe0) >> 5);
     42 
     43     int size = 0;
     44 
     45     switch (valueType) {
     46       case VALUE_BYTE:
     47         size = 1;
     48         break;
     49       case VALUE_ARRAY:
     50         (encodedArray = new EncodedArray()).read(file);
     51         size = 0; // So we don't read into value.
     52         break;
     53       case VALUE_ANNOTATION:
     54         (encodedAnnotation = new EncodedAnnotation()).read(file);
     55         size = 0; // So we don't read into value.
     56         break;
     57       case VALUE_NULL:
     58       case VALUE_BOOLEAN:
     59         // No value
     60         size = 0;
     61         break;
     62       default:
     63         // All others encode value_arg as (size - 1), so...
     64         size = valueArg + 1;
     65         break;
     66     }
     67 
     68     if (size != 0) {
     69       value = new byte[size];
     70       for (int i = 0; i < size; i++) {
     71         value[i] = file.readByte();
     72       }
     73     }
     74   }
     75 
     76   @Override
     77   public void write(DexRandomAccessFile file) throws IOException {
     78     int valueArgAndType = ((valueType) | (valueArg << 5));
     79     file.writeByte(valueArgAndType);
     80 
     81     if (encodedArray != null) {
     82       encodedArray.write(file);
     83     } else if (encodedAnnotation != null) {
     84       encodedAnnotation.write(file);
     85     } else if (value != null) {
     86       file.write(value);
     87     }
     88   }
     89 
     90   @Override
     91   public void incrementIndex(IndexUpdateKind kind, int insertedIdx) {
     92     if (encodedArray != null) {
     93       encodedArray.incrementIndex(kind, insertedIdx);
     94     } else if (encodedAnnotation != null) {
     95       encodedAnnotation.incrementIndex(kind, insertedIdx);
     96     }
     97   }
     98 }
     99