blob: 25f756522580ca40c3c232d66e484b1e545c995d [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
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
Adam Lesinskice5e56e2016-10-21 17:56:45 -070020#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
Adam Lesinski1ab598f2015-08-14 14:26:04 -070029#include "Resource.h"
30#include "ResourceTable.h"
31#include "ResourceValues.h"
32#include "util/Util.h"
33
Adam Lesinski1ab598f2015-08-14 14:26:04 -070034namespace aapt {
35
Adam Lesinski1ab598f2015-08-14 14:26:04 -070036inline android::hash_t hash_type(const ResourceName& name) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070037 std::hash<std::string> str_hash;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070038 android::hash_t hash = 0;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070039 hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.package));
Adam Lesinskicacb28f2016-10-19 12:18:14 -070040 hash = android::JenkinsHashMix(hash, (uint32_t)name.type);
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.entry));
Adam Lesinskicacb28f2016-10-19 12:18:14 -070042 return hash;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070043}
44
45inline android::hash_t hash_type(const ResourceId& id) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070046 return android::hash_type(id.id);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070047}
48
Adam Lesinski64587af2016-02-18 18:33:06 -080049class ISymbolSource;
50
51class SymbolTable {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070052 public:
53 struct Symbol {
54 Symbol() : Symbol(Maybe<ResourceId>{}) {}
Adam Lesinski626b3db2016-04-07 13:24:59 -070055
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 explicit Symbol(const Maybe<ResourceId>& i) : Symbol(i, nullptr) {}
Adam Lesinski626b3db2016-04-07 13:24:59 -070057
Adam Lesinskicacb28f2016-10-19 12:18:14 -070058 Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr)
59 : Symbol(i, attr, false) {}
Adam Lesinski626b3db2016-04-07 13:24:59 -070060
Adam Lesinskicacb28f2016-10-19 12:18:14 -070061 Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr,
62 bool pub)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070063 : id(i), attribute(attr), is_public(pub) {}
Adam Lesinski626b3db2016-04-07 13:24:59 -070064
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 Symbol(const Symbol&) = default;
66 Symbol(Symbol&&) = default;
67 Symbol& operator=(const Symbol&) = default;
68 Symbol& operator=(Symbol&&) = default;
Adam Lesinski626b3db2016-04-07 13:24:59 -070069
Adam Lesinskicacb28f2016-10-19 12:18:14 -070070 Maybe<ResourceId> id;
71 std::shared_ptr<Attribute> attribute;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070072 bool is_public = false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070073 };
Adam Lesinski64587af2016-02-18 18:33:06 -080074
Adam Lesinskice5e56e2016-10-21 17:56:45 -070075 SymbolTable() : cache_(200), id_cache_(200) {}
Adam Lesinski64587af2016-02-18 18:33:06 -080076
Adam Lesinskice5e56e2016-10-21 17:56:45 -070077 void AppendSource(std::unique_ptr<ISymbolSource> source);
78 void PrependSource(std::unique_ptr<ISymbolSource> source);
Adam Lesinski64587af2016-02-18 18:33:06 -080079
Adam Lesinskicacb28f2016-10-19 12:18:14 -070080 /**
Adam Lesinskice5e56e2016-10-21 17:56:45 -070081 * Never hold on to the result between calls to FindByName or FindById. The
82 * results stored in a cache which may evict entries.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070083 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -070084 const Symbol* FindByName(const ResourceName& name);
85 const Symbol* FindById(const ResourceId& id);
Adam Lesinski64587af2016-02-18 18:33:06 -080086
Adam Lesinskicacb28f2016-10-19 12:18:14 -070087 /**
88 * Let's the ISymbolSource decide whether looking up by name or ID is faster,
Adam Lesinskice5e56e2016-10-21 17:56:45 -070089 * if both are available.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -070091 const Symbol* FindByReference(const Reference& ref);
Adam Lesinski76565542016-03-10 21:55:04 -080092
Adam Lesinskicacb28f2016-10-19 12:18:14 -070093 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070094 std::vector<std::unique_ptr<ISymbolSource>> sources_;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070095
Adam Lesinskicacb28f2016-10-19 12:18:14 -070096 // We use shared_ptr because unique_ptr is not supported and
97 // we need automatic deletion.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070098 android::LruCache<ResourceName, std::shared_ptr<Symbol>> cache_;
99 android::LruCache<ResourceId, std::shared_ptr<Symbol>> id_cache_;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700100
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 DISALLOW_COPY_AND_ASSIGN(SymbolTable);
Adam Lesinski64587af2016-02-18 18:33:06 -0800102};
103
104/**
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700105 * An interface that a symbol source implements in order to surface symbol
106 * information
Adam Lesinski64587af2016-02-18 18:33:06 -0800107 * to the symbol table.
108 */
109class ISymbolSource {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700110 public:
111 virtual ~ISymbolSource() = default;
Adam Lesinski64587af2016-02-18 18:33:06 -0800112
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700113 virtual std::unique_ptr<SymbolTable::Symbol> FindByName(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700114 const ResourceName& name) = 0;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700115 virtual std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) = 0;
Adam Lesinski76565542016-03-10 21:55:04 -0800116
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 /**
118 * Default implementation tries the name if it exists, else the ID.
119 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700120 virtual std::unique_ptr<SymbolTable::Symbol> FindByReference(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700121 const Reference& ref) {
122 if (ref.name) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700123 return FindByName(ref.name.value());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700124 } else if (ref.id) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700125 return FindById(ref.id.value());
Adam Lesinski76565542016-03-10 21:55:04 -0800126 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700127 return {};
128 }
Adam Lesinski64587af2016-02-18 18:33:06 -0800129};
130
131/**
132 * Exposes the resources in a ResourceTable as symbols for SymbolTable.
133 * Instances of this class must outlive the encompassed ResourceTable.
134 * Lookups by ID are ignored.
135 */
136class ResourceTableSymbolSource : public ISymbolSource {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700137 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700138 explicit ResourceTableSymbolSource(ResourceTable* table) : table_(table) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700139
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700140 std::unique_ptr<SymbolTable::Symbol> FindByName(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700141 const ResourceName& name) override;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700142
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 return {};
145 }
Adam Lesinski64587af2016-02-18 18:33:06 -0800146
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700147 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700148 ResourceTable* table_;
Adam Lesinski64587af2016-02-18 18:33:06 -0800149
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700150 DISALLOW_COPY_AND_ASSIGN(ResourceTableSymbolSource);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700151};
152
Adam Lesinski64587af2016-02-18 18:33:06 -0800153class AssetManagerSymbolSource : public ISymbolSource {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700154 public:
155 AssetManagerSymbolSource() = default;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700156
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700157 bool AddAssetPath(const StringPiece& path);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700158
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700159 std::unique_ptr<SymbolTable::Symbol> FindByName(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700160 const ResourceName& name) override;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700161 std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override;
162 std::unique_ptr<SymbolTable::Symbol> FindByReference(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700163 const Reference& ref) override;
Adam Lesinski64587af2016-02-18 18:33:06 -0800164
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700166 android::AssetManager assets_;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700167
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168 DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700169};
170
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700171} // namespace aapt
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700172
173#endif /* AAPT_PROCESS_SYMBOLTABLE_H */