• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018, Google LLC
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google LLC nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 package com.android.tools.smali.dexlib2.builder;
32 
33 import java.util.AbstractSet;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Set;
39 import javax.annotation.Nonnull;
40 import javax.annotation.Nullable;
41 
42 public abstract class LocatedItems<T extends ItemWithLocation> {
43     // We end up creating and keeping around a *lot* of MethodLocation objects
44     // when building a new dex file, so it's worth the trouble of lazily creating
45     // the labels and debugItems lists only when they are needed
46     @Nullable
47     private List<T> items = null;
48 
49     @Nonnull
getItems()50     private List<T> getItems() {
51         if (items == null) {
52             return Collections.emptyList();
53         }
54         return items;
55     }
56 
getModifiableItems(MethodLocation newItemsLocation)57     public Set<T> getModifiableItems(MethodLocation newItemsLocation) {
58         return new AbstractSet<T>() {
59             @Nonnull
60             @Override
61             public Iterator<T> iterator() {
62                 final Iterator<T> it = getItems().iterator();
63 
64                 return new Iterator<T>() {
65                     private @Nullable
66                     T currentItem = null;
67 
68                     @Override
69                     public boolean hasNext() {
70                         return it.hasNext();
71                     }
72 
73                     @Override
74                     public T next() {
75                         currentItem = it.next();
76                         return currentItem;
77                     }
78 
79                     @Override
80                     public void remove() {
81                         if (currentItem != null) {
82                             currentItem.setLocation(null);
83                         }
84                         it.remove();
85                     }
86                 };
87             }
88 
89             @Override
90             public int size() {
91                 return getItems().size();
92             }
93 
94             @Override
95             public boolean add(@Nonnull T item) {
96                 if (item.isPlaced()) {
97                     throw new IllegalArgumentException(getAddLocatedItemError());
98                 }
99                 item.setLocation(newItemsLocation);
100                 addItem(item);
101                 return true;
102             }
103         };
104     }
105 
106     private void addItem(@Nonnull T item) {
107         if (items == null) {
108             items = new ArrayList<>(1);
109         }
110         items.add(item);
111     }
112 
113     protected abstract String getAddLocatedItemError();
114 
115     public void mergeItemsIntoNext(@Nonnull MethodLocation nextLocation, LocatedItems<T> otherLocatedItems) {
116         if (otherLocatedItems == this) {
117             return;
118         }
119         if (items != null) {
120             for (T item : items) {
121                 item.setLocation(nextLocation);
122             }
123             List<T> mergedItems = items;
124             mergedItems.addAll(otherLocatedItems.getItems());
125             otherLocatedItems.items = mergedItems;
126             items = null;
127         }
128     }
129 }
130