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