Home | History | Annotate | Download | only in writer
      1 /*
      2  * Copyright 2013, Google Inc.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 package org.jf.dexlib2.writer;
     33 
     34 import com.google.common.collect.Ordering;
     35 import org.jf.dexlib2.ValueType;
     36 import org.jf.dexlib2.base.BaseAnnotationElement;
     37 import org.jf.dexlib2.iface.reference.FieldReference;
     38 import org.jf.dexlib2.iface.reference.MethodReference;
     39 
     40 import javax.annotation.Nonnull;
     41 import java.io.IOException;
     42 import java.util.Collection;
     43 
     44 public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends FieldReference,
     45         MethodRefKey extends MethodReference, AnnotationElement extends org.jf.dexlib2.iface.AnnotationElement,
     46         EncodedValue> {
     47     @Nonnull private final DexDataWriter writer;
     48     @Nonnull private final StringSection<StringKey, ?> stringSection;
     49     @Nonnull private final TypeSection<?, TypeKey, ?> typeSection;
     50     @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
     51     @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
     52     @Nonnull private final AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection;
     53 
     54     public EncodedValueWriter(
     55             @Nonnull DexDataWriter writer,
     56             @Nonnull StringSection<StringKey, ?> stringSection,
     57             @Nonnull TypeSection<?, TypeKey, ?> typeSection,
     58             @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
     59             @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
     60             @Nonnull AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection) {
     61         this.writer = writer;
     62         this.stringSection = stringSection;
     63         this.typeSection = typeSection;
     64         this.fieldSection = fieldSection;
     65         this.methodSection = methodSection;
     66         this.annotationSection = annotationSection;
     67     }
     68 
     69     protected abstract void writeEncodedValue(@Nonnull EncodedValue encodedValue) throws IOException;
     70 
     71     public void writeAnnotation(TypeKey annotationType,
     72                                 Collection<? extends AnnotationElement> elements) throws IOException {
     73         writer.writeEncodedValueHeader(ValueType.ANNOTATION, 0);
     74         writer.writeUleb128(typeSection.getItemIndex(annotationType));
     75         writer.writeUleb128(elements.size());
     76 
     77         Collection<? extends AnnotationElement> sortedElements = Ordering.from(BaseAnnotationElement.BY_NAME)
     78                 .immutableSortedCopy(elements);
     79 
     80         for (AnnotationElement element: sortedElements) {
     81             writer.writeUleb128(stringSection.getItemIndex(annotationSection.getElementName(element)));
     82             writeEncodedValue(annotationSection.getElementValue(element));
     83         }
     84     }
     85 
     86     public void writeArray(Collection<? extends EncodedValue> elements) throws IOException {
     87         writer.writeEncodedValueHeader(ValueType.ARRAY, 0);
     88         writer.writeUleb128(elements.size());
     89         for (EncodedValue element: elements) {
     90             writeEncodedValue(element);
     91         }
     92     }
     93 
     94     public void writeBoolean(boolean value) throws IOException {
     95         writer.writeEncodedValueHeader(ValueType.BOOLEAN, value ? 1 : 0);
     96     }
     97 
     98     public void writeByte(byte value) throws IOException {
     99         writer.writeEncodedInt(ValueType.BYTE, value);
    100     }
    101 
    102     public void writeChar(char value) throws IOException {
    103         writer.writeEncodedUint(ValueType.CHAR, value);
    104     }
    105 
    106     public void writeDouble(double value) throws IOException {
    107         writer.writeEncodedDouble(ValueType.DOUBLE, value);
    108     }
    109 
    110     public void writeEnum(@Nonnull FieldRefKey value) throws IOException {
    111         writer.writeEncodedUint(ValueType.ENUM, fieldSection.getItemIndex(value));
    112     }
    113 
    114     public void writeField(@Nonnull FieldRefKey value) throws IOException {
    115         writer.writeEncodedUint(ValueType.FIELD, fieldSection.getItemIndex(value));
    116     }
    117 
    118     public void writeFloat(float value) throws IOException {
    119         writer.writeEncodedFloat(ValueType.FLOAT, value);
    120     }
    121 
    122     public void writeInt(int value) throws IOException {
    123         writer.writeEncodedInt(ValueType.INT, value);
    124     }
    125 
    126     public void writeLong(long value) throws IOException {
    127         writer.writeEncodedLong(ValueType.LONG, value);
    128     }
    129 
    130     public void writeMethod(@Nonnull MethodRefKey value) throws IOException {
    131         writer.writeEncodedUint(ValueType.METHOD, methodSection.getItemIndex(value));
    132     }
    133 
    134     public void writeNull() throws IOException {
    135         writer.write(ValueType.NULL);
    136     }
    137 
    138     public void writeShort(int value) throws IOException {
    139         writer.writeEncodedInt(ValueType.SHORT, value);
    140     }
    141 
    142     public void writeString(@Nonnull StringKey value) throws IOException {
    143         writer.writeEncodedUint(ValueType.STRING, stringSection.getItemIndex(value));
    144     }
    145 
    146     public void writeType(@Nonnull TypeKey value) throws IOException {
    147         writer.writeEncodedUint(ValueType.TYPE, typeSection.getItemIndex(value));
    148     }
    149 }
    150