SymbolTable.h revision ceb9b2f80f853059233cdd29057f39a5960a74ae
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef AAPT_PROCESS_SYMBOLTABLE_H
18#define AAPT_PROCESS_SYMBOLTABLE_H
19
20#include <algorithm>
21#include <memory>
22#include <vector>
23
24#include "android-base/macros.h"
25#include "androidfw/AssetManager.h"
26#include "utils/JenkinsHash.h"
27#include "utils/LruCache.h"
28
29#include "Resource.h"
30#include "ResourceTable.h"
31#include "ResourceValues.h"
32#include "util/Util.h"
33
34namespace aapt {
35
36inline android::hash_t hash_type(const ResourceName& name) {
37  std::hash<std::string> str_hash;
38  android::hash_t hash = 0;
39  hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.package));
40  hash = android::JenkinsHashMix(hash, (uint32_t)name.type);
41  hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.entry));
42  return hash;
43}
44
45inline android::hash_t hash_type(const ResourceId& id) {
46  return android::hash_type(id.id);
47}
48
49class ISymbolSource;
50class NameMangler;
51
52class SymbolTable {
53 public:
54  struct Symbol {
55    Symbol() : Symbol(Maybe<ResourceId>{}) {}
56
57    explicit Symbol(const Maybe<ResourceId>& i) : Symbol(i, nullptr) {}
58
59    Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr)
60        : Symbol(i, attr, false) {}
61
62    Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr,
63           bool pub)
64        : id(i), attribute(attr), is_public(pub) {}
65
66    Symbol(const Symbol&) = default;
67    Symbol(Symbol&&) = default;
68    Symbol& operator=(const Symbol&) = default;
69    Symbol& operator=(Symbol&&) = default;
70
71    Maybe<ResourceId> id;
72    std::shared_ptr<Attribute> attribute;
73    bool is_public = false;
74  };
75
76  SymbolTable(NameMangler* mangler) : mangler_(mangler), cache_(200), id_cache_(200) {}
77
78  // Appends a symbol source. The cache is not cleared since entries that
79  // have already been found would take precedence due to ordering.
80  void AppendSource(std::unique_ptr<ISymbolSource> source);
81
82  // Prepends a symbol source so that its symbols take precedence. This will
83  // cause the existing cache to be cleared.
84  void PrependSource(std::unique_ptr<ISymbolSource> source);
85
86  // NOTE: Never hold on to the result between calls to FindByXXX. The
87  // results are stored in a cache which may evict entries on subsequent calls.
88  const Symbol* FindByName(const ResourceName& name);
89
90  // NOTE: Never hold on to the result between calls to FindByXXX. The
91  // results are stored in a cache which may evict entries on subsequent calls.
92  const Symbol* FindById(const ResourceId& id);
93
94  // Let's the ISymbolSource decide whether looking up by name or ID is faster,
95  // if both are available.
96  // NOTE: Never hold on to the result between calls to FindByXXX. The
97  // results are stored in a cache which may evict entries on subsequent calls.
98  const Symbol* FindByReference(const Reference& ref);
99
100 private:
101  NameMangler* mangler_;
102  std::vector<std::unique_ptr<ISymbolSource>> sources_;
103
104  // We use shared_ptr because unique_ptr is not supported and
105  // we need automatic deletion.
106  android::LruCache<ResourceName, std::shared_ptr<Symbol>> cache_;
107  android::LruCache<ResourceId, std::shared_ptr<Symbol>> id_cache_;
108
109  DISALLOW_COPY_AND_ASSIGN(SymbolTable);
110};
111
112/**
113 * An interface that a symbol source implements in order to surface symbol
114 * information
115 * to the symbol table.
116 */
117class ISymbolSource {
118 public:
119  virtual ~ISymbolSource() = default;
120
121  virtual std::unique_ptr<SymbolTable::Symbol> FindByName(
122      const ResourceName& name) = 0;
123  virtual std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) = 0;
124
125  /**
126   * Default implementation tries the name if it exists, else the ID.
127   */
128  virtual std::unique_ptr<SymbolTable::Symbol> FindByReference(
129      const Reference& ref) {
130    if (ref.name) {
131      return FindByName(ref.name.value());
132    } else if (ref.id) {
133      return FindById(ref.id.value());
134    }
135    return {};
136  }
137};
138
139/**
140 * Exposes the resources in a ResourceTable as symbols for SymbolTable.
141 * Instances of this class must outlive the encompassed ResourceTable.
142 * Lookups by ID are ignored.
143 */
144class ResourceTableSymbolSource : public ISymbolSource {
145 public:
146  explicit ResourceTableSymbolSource(ResourceTable* table) : table_(table) {}
147
148  std::unique_ptr<SymbolTable::Symbol> FindByName(
149      const ResourceName& name) override;
150
151  std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override {
152    return {};
153  }
154
155 private:
156  ResourceTable* table_;
157
158  DISALLOW_COPY_AND_ASSIGN(ResourceTableSymbolSource);
159};
160
161class AssetManagerSymbolSource : public ISymbolSource {
162 public:
163  AssetManagerSymbolSource() = default;
164
165  bool AddAssetPath(const android::StringPiece& path);
166  std::map<size_t, std::string> GetAssignedPackageIds() const;
167
168  std::unique_ptr<SymbolTable::Symbol> FindByName(
169      const ResourceName& name) override;
170  std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override;
171  std::unique_ptr<SymbolTable::Symbol> FindByReference(
172      const Reference& ref) override;
173
174 private:
175  android::AssetManager assets_;
176
177  DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource);
178};
179
180}  // namespace aapt
181
182#endif /* AAPT_PROCESS_SYMBOLTABLE_H */
183