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