| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.dx.dex.file; |
| |
| import com.android.dx.rop.annotation.Annotation; |
| import com.android.dx.rop.annotation.AnnotationVisibility; |
| import com.android.dx.rop.annotation.NameValuePair; |
| import com.android.dx.rop.cst.Constant; |
| import com.android.dx.rop.cst.CstAnnotation; |
| import com.android.dx.rop.cst.CstArray; |
| import com.android.dx.rop.cst.CstUtf8; |
| import com.android.dx.util.ByteArrayAnnotatedOutput; |
| import com.android.dx.util.AnnotatedOutput; |
| |
| import java.util.Arrays; |
| import java.util.Comparator; |
| |
| /** |
| * Encoded array of constant values. |
| */ |
| public final class EncodedArrayItem extends OffsettedItem { |
| /** the required alignment for instances of this class */ |
| private static final int ALIGNMENT = 1; |
| |
| /** {@code non-null;} the array to represent */ |
| private final CstArray array; |
| |
| /** |
| * {@code null-ok;} encoded form, ready for writing to a file; set during |
| * {@link #place0} |
| */ |
| private byte[] encodedForm; |
| |
| /** |
| * Constructs an instance. |
| * |
| * @param array {@code non-null;} array to represent |
| */ |
| public EncodedArrayItem(CstArray array) { |
| /* |
| * The write size isn't known up-front because (the variable-lengthed) |
| * leb128 type is used to represent some things. |
| */ |
| super(ALIGNMENT, -1); |
| |
| if (array == null) { |
| throw new NullPointerException("array == null"); |
| } |
| |
| this.array = array; |
| this.encodedForm = null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public ItemType itemType() { |
| return ItemType.TYPE_ENCODED_ARRAY_ITEM; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public int hashCode() { |
| return array.hashCode(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| protected int compareTo0(OffsettedItem other) { |
| EncodedArrayItem otherArray = (EncodedArrayItem) other; |
| |
| return array.compareTo(otherArray.array); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public String toHuman() { |
| return array.toHuman(); |
| } |
| |
| /** {@inheritDoc} */ |
| public void addContents(DexFile file) { |
| ValueEncoder.addContents(file, array); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| protected void place0(Section addedTo, int offset) { |
| // Encode the data and note the size. |
| |
| ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); |
| ValueEncoder encoder = new ValueEncoder(addedTo.getFile(), out); |
| |
| encoder.writeArray(array, false); |
| encodedForm = out.toByteArray(); |
| setWriteSize(encodedForm.length); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| protected void writeTo0(DexFile file, AnnotatedOutput out) { |
| boolean annotates = out.annotates(); |
| |
| if (annotates) { |
| out.annotate(0, offsetString() + " encoded array"); |
| |
| /* |
| * The output is to be annotated, so redo the work previously |
| * done by place0(), except this time annotations will actually |
| * get emitted. |
| */ |
| ValueEncoder encoder = new ValueEncoder(file, out); |
| encoder.writeArray(array, true); |
| } else { |
| out.write(encodedForm); |
| } |
| } |
| } |