ProtoPool.java revision 42627b850c8f68a594f105e04b97c512b292b698
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 32package org.jf.dexlib2.writer.pool; 33 34import com.google.common.collect.Ordering; 35import org.jf.dexlib2.iface.reference.MethodReference; 36import org.jf.dexlib2.util.MethodUtil; 37import org.jf.dexlib2.writer.pool.ProtoPool.Key; 38import org.jf.dexlib2.writer.ProtoSection; 39import org.jf.util.CharSequenceUtils; 40import org.jf.util.CollectionUtils; 41 42import javax.annotation.Nonnull; 43import javax.annotation.Nullable; 44import java.util.Collection; 45import java.util.List; 46 47public class ProtoPool extends BaseIndexPool<Key> 48 implements ProtoSection<CharSequence, CharSequence, Key, TypeListPool.Key<? extends Collection<? extends CharSequence>>> { 49 @Nonnull private final StringPool stringPool; 50 @Nonnull private final TypePool typePool; 51 @Nonnull private final TypeListPool typeListPool; 52 53 public ProtoPool(@Nonnull StringPool stringPool, @Nonnull TypePool typePool, 54 @Nonnull TypeListPool typeListPool) { 55 this.stringPool = stringPool; 56 this.typePool = typePool; 57 this.typeListPool = typeListPool; 58 } 59 60 public void intern(@Nonnull MethodReference method) { 61 // We can't use method directly, because it is likely a full MethodReference. We use a wrapper that computes 62 // hashCode and equals based only on the prototype fields 63 Key key = new Key(method); 64 Integer prev = internedItems.put(key, 0); 65 if (prev == null) { 66 stringPool.intern(key.getShorty()); 67 typePool.intern(method.getReturnType()); 68 typeListPool.intern(method.getParameterTypes()); 69 } 70 } 71 72 @Nonnull @Override public CharSequence getShorty(@Nonnull Key key) { 73 return key.getShorty(); 74 } 75 76 @Nonnull @Override public CharSequence getReturnType(@Nonnull Key key) { 77 return key.getReturnType(); 78 } 79 80 @Nullable @Override public TypeListPool.Key<List<? extends CharSequence>> getParameters(@Nonnull Key key) { 81 return new TypeListPool.Key<List<? extends CharSequence>>(key.getParameters()); 82 } 83 84 public static class Key implements Comparable<Key> { 85 @Nonnull private final MethodReference method; 86 87 public Key(@Nonnull MethodReference method) { 88 this.method = method; 89 } 90 91 @Nonnull public String getReturnType() { return method.getReturnType(); } 92 @Nonnull public List<? extends CharSequence> getParameters() { 93 return method.getParameterTypes(); 94 } 95 96 public String getShorty() { 97 return MethodUtil.getShorty(method.getParameterTypes(), method.getReturnType()); 98 } 99 100 public String toString() { 101 StringBuilder sb = new StringBuilder(); 102 sb.append('('); 103 for (CharSequence paramType: getParameters()) { 104 sb.append(paramType); 105 } 106 sb.append(')'); 107 sb.append(getReturnType()); 108 return sb.toString(); 109 } 110 111 @Override 112 public int hashCode() { 113 int hashCode = getReturnType().hashCode(); 114 return hashCode*31 + CharSequenceUtils.listHashCode(getParameters()); 115 } 116 117 @Override 118 public boolean equals(@Nullable Object o) { 119 if (o instanceof Key) { 120 Key other = (Key)o; 121 return getReturnType().equals(other.getReturnType()) && 122 CharSequenceUtils.listEquals(getParameters(), other.getParameters()); 123 } 124 return false; 125 } 126 127 @Override 128 public int compareTo(@Nonnull Key o) { 129 int res = getReturnType().compareTo(o.getReturnType()); 130 if (res != 0) return res; 131 return CollectionUtils.compareAsIterable(Ordering.usingToString(), getParameters(), o.getParameters()); 132 } 133 } 134} 135