14ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver/*
21bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver * Copyright 2013, Google Inc.
34ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * All rights reserved.
44ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver *
54ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * Redistribution and use in source and binary forms, with or without
64ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * modification, are permitted provided that the following conditions are
74ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * met:
84ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver *
94ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver *     * Redistributions of source code must retain the above copyright
104ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * notice, this list of conditions and the following disclaimer.
114ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver *     * Redistributions in binary form must reproduce the above
124ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * copyright notice, this list of conditions and the following disclaimer
134ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * in the documentation and/or other materials provided with the
144ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * distribution.
154ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver *     * Neither the name of Google Inc. nor the names of its
164ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * contributors may be used to endorse or promote products derived from
174ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * this software without specific prior written permission.
184ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver *
194ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
204ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
214ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
224ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
234ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
244ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
254ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
264ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
274ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
284ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
294ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
304ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver */
314ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
321bf6f2324541df184689fdb2c0d8188af5221784Ben Gruverpackage org.jf.dexlib2.writer.pool;
334ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
341bf6f2324541df184689fdb2c0d8188af5221784Ben Gruverimport com.google.common.collect.ImmutableList;
3508d90ec360b43c9febe9638089b1a3815cc62111Ben Gruverimport org.jf.dexlib2.writer.DexWriter;
361bf6f2324541df184689fdb2c0d8188af5221784Ben Gruverimport org.jf.dexlib2.writer.TypeListSection;
3708d90ec360b43c9febe9638089b1a3815cc62111Ben Gruverimport org.jf.dexlib2.writer.pool.TypeListPool.Key;
384ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
394ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruverimport javax.annotation.Nonnull;
4008d90ec360b43c9febe9638089b1a3815cc62111Ben Gruverimport javax.annotation.Nullable;
411bf6f2324541df184689fdb2c0d8188af5221784Ben Gruverimport java.util.Collection;
421bf6f2324541df184689fdb2c0d8188af5221784Ben Gruverimport java.util.Iterator;
434ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
441bf6f2324541df184689fdb2c0d8188af5221784Ben Gruverpublic class TypeListPool extends BaseNullableOffsetPool<Key<? extends Collection<? extends CharSequence>>>
451bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver        implements TypeListSection<CharSequence, Key<? extends Collection<? extends CharSequence>>> {
461bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver    @Nonnull private final TypePool typePool;
474ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
481bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver    public TypeListPool(@Nonnull TypePool typePool) {
491bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver        this.typePool = typePool;
504ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver    }
514ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
524ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver    public void intern(@Nonnull Collection<? extends CharSequence> types) {
5308d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver        if (types.size() > 0) {
5408d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver            Key<? extends Collection<? extends CharSequence>> key = new Key<Collection<? extends CharSequence>>(types);
5508d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver            Integer prev = internedItems.put(key, 0);
5608d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver            if (prev == null) {
5708d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver                for (CharSequence type: types) {
5808d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver                    typePool.intern(type);
5908d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver                }
604ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            }
614ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        }
624ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver    }
634ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
641bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver    @Nonnull @Override
651bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver    public Collection<? extends CharSequence> getTypes(Key<? extends Collection<? extends CharSequence>> typesKey) {
661bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver        if (typesKey == null) {
671bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver            return ImmutableList.of();
684ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        }
691bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver        return typesKey.types;
704ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver    }
714ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
7208d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver    @Override public int getNullableItemOffset(@Nullable Key<? extends Collection<? extends CharSequence>> key) {
7308d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver        if (key == null || key.types.size() == 0) {
7408d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver            return DexWriter.NO_OFFSET;
7508d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver        } else {
7608d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver            return super.getNullableItemOffset(key);
7708d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver        }
7808d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver    }
7908d90ec360b43c9febe9638089b1a3815cc62111Ben Gruver
801bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver    public static class Key<TypeCollection extends Collection<? extends CharSequence>>
811bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver            implements Comparable<Key<? extends Collection<? extends CharSequence>>> {
821bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver        @Nonnull TypeCollection types;
83085cfce948928c19fff95c4bf93ab5ed430991aeIzzat Bahadirov
841bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver        public Key(@Nonnull TypeCollection types) {
854ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            this.types = types;
864ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        }
874ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
884ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        @Override
894ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        public int hashCode() {
904ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            int hashCode = 1;
914ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            for (CharSequence type: types) {
924ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                hashCode = hashCode*31 + type.toString().hashCode();
934ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            }
944ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            return hashCode;
954ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        }
964ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
974ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        @Override
984ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        public boolean equals(Object o) {
994ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            if (o instanceof Key) {
1001bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver                Key<? extends Collection<? extends CharSequence>> other =
1011bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver                        (Key<? extends Collection<? extends CharSequence>>)o;
1024ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                if (types.size() != other.types.size()) {
1034ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                    return false;
1044ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                }
1054ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                Iterator<? extends CharSequence> otherTypes = other.types.iterator();
1064ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                for (CharSequence type: types) {
1074ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                    if (!type.toString().equals(otherTypes.next().toString())) {
1084ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                        return false;
1094ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                    }
1104ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                }
1114ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                return true;
1124ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            }
1134ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            return false;
1144ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        }
1154ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
1164ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        @Override
1174ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        public String toString() {
1184ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            StringBuilder sb = new StringBuilder();
1194ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            for (CharSequence type: types) {
1204ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                sb.append(type.toString());
1214ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            }
1224ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            return sb.toString();
1234ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        }
1244ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver
1254ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        @Override
1261bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver        public int compareTo(Key<? extends Collection<? extends CharSequence>> o) {
1274ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            Iterator<? extends CharSequence> other = o.types.iterator();
1284ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            for (CharSequence type: types) {
1294ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                if (!other.hasNext()) {
1304ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                    return 1;
1314ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                }
1324ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                int comparison = type.toString().compareTo(other.next().toString());
1334ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                if (comparison != 0) {
1344ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                    return comparison;
1354ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                }
1364ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            }
1374ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            if (other.hasNext()) {
1384ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver                return -1;
1394ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            }
1404ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver            return 0;
1414ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver        }
1424ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver    }
1434ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4Ben Gruver}
144