16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License. 66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at 76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software 116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and 146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License. 156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 17cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#include "ResourceTable.h" 186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ConfigDescription.h" 19769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include "NameMangler.h" 206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceValues.h" 211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ValueVisitor.h" 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h" 236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <android-base/logging.h> 256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <androidfw/ResourceTypes.h> 26cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#include <algorithm> 276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <memory> 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string> 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <tuple> 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 31d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece; 32d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 35b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskistatic bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs, ResourceType rhs) { 36cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return lhs->type < rhs; 376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T> 40b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskistatic bool less_than_struct_with_name(const std::unique_ptr<T>& lhs, const StringPiece& rhs) { 41cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return lhs->name.compare(0, lhs->name.size(), rhs.data(), rhs.size()) < 0; 426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceTablePackage* ResourceTable::FindPackage(const StringPiece& name) { 45cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const auto last = packages.end(); 46b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski auto iter = std::lower_bound(packages.begin(), last, name, 47b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski less_than_struct_with_name<ResourceTablePackage>); 48cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != last && name == (*iter)->name) { 49cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return iter->get(); 50cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 51cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return nullptr; 526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceTablePackage* ResourceTable::FindPackageById(uint8_t id) { 55cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& package : packages) { 56cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (package->id && package->id.value() == id) { 57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return package.get(); 586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 59cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 60cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return nullptr; 616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 63b1afa07745280c7a36077beda6293b69c6ba4ea2Adam LesinskiResourceTablePackage* ResourceTable::CreatePackage(const StringPiece& name, Maybe<uint8_t> id) { 64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTablePackage* package = FindOrCreatePackage(name); 65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (id && !package->id) { 66cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski package->id = id; 679ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski return package; 68cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 70cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (id && package->id && package->id.value() != id.value()) { 71cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return nullptr; 72cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return package; 74cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 76b1afa07745280c7a36077beda6293b69c6ba4ea2Adam LesinskiResourceTablePackage* ResourceTable::FindOrCreatePackage(const StringPiece& name) { 77cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const auto last = packages.end(); 78b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski auto iter = std::lower_bound(packages.begin(), last, name, 79b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski less_than_struct_with_name<ResourceTablePackage>); 80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != last && name == (*iter)->name) { 81cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return iter->get(); 82cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 83cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 84b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski std::unique_ptr<ResourceTablePackage> new_package = util::make_unique<ResourceTablePackage>(); 85d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski new_package->name = name.to_string(); 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return packages.emplace(iter, std::move(new_package))->get(); 871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceTableType* ResourceTablePackage::FindType(ResourceType type) { 90cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const auto last = types.end(); 91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto iter = std::lower_bound(types.begin(), last, type, less_than_type); 92cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != last && (*iter)->type == type) { 93cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return iter->get(); 94cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 95cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return nullptr; 961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceTableType* ResourceTablePackage::FindOrCreateType(ResourceType type) { 99cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const auto last = types.end(); 100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto iter = std::lower_bound(types.begin(), last, type, less_than_type); 101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != last && (*iter)->type == type) { 102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return iter->get(); 103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return types.emplace(iter, new ResourceTableType(type))->get(); 1051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceEntry* ResourceTableType::FindEntry(const StringPiece& name) { 108cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const auto last = entries.end(); 109b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski auto iter = 110b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski std::lower_bound(entries.begin(), last, name, less_than_struct_with_name<ResourceEntry>); 111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != last && name == (*iter)->name) { 112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return iter->get(); 113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return nullptr; 1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceEntry* ResourceTableType::FindOrCreateEntry(const StringPiece& name) { 118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski auto last = entries.end(); 119b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski auto iter = 120b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski std::lower_bound(entries.begin(), last, name, less_than_struct_with_name<ResourceEntry>); 121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != last && name == (*iter)->name) { 122cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return iter->get(); 123cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return entries.emplace(iter, new ResourceEntry(name))->get(); 1251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 127ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config) { 128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return FindValue(config, StringPiece()); 129e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 130e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 131e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskistruct ConfigKey { 132cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ConfigDescription* config; 133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const StringPiece& product; 134e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski}; 135e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 136b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskibool ltConfigKeyRef(const std::unique_ptr<ResourceConfigValue>& lhs, const ConfigKey& rhs) { 137cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski int cmp = lhs->config.compare(*rhs.config); 138cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (cmp == 0) { 139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski cmp = StringPiece(lhs->product).compare(rhs.product); 140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return cmp < 0; 142e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 143e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config, 145e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product) { 146b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski auto iter = 147b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product}, ltConfigKeyRef); 148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != values.end()) { 149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceConfigValue* value = iter->get(); 150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (value->config == config && StringPiece(value->product) == product) { 151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return value; 152cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 153cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 154cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return nullptr; 155e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 156e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 157b1afa07745280c7a36077beda6293b69c6ba4ea2Adam LesinskiResourceConfigValue* ResourceEntry::FindOrCreateValue(const ConfigDescription& config, 158b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski const StringPiece& product) { 159b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski auto iter = 160b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product}, ltConfigKeyRef); 161cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != values.end()) { 162cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceConfigValue* value = iter->get(); 163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (value->config == config && StringPiece(value->product) == product) { 164cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return value; 165cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceConfigValue* newValue = 168b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski values.insert(iter, util::make_unique<ResourceConfigValue>(config, product))->get(); 169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return newValue; 170e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 171e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 172b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskistd::vector<ResourceConfigValue*> ResourceEntry::FindAllValues(const ConfigDescription& config) { 173cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::vector<ResourceConfigValue*> results; 174cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 175cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski auto iter = values.begin(); 176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (; iter != values.end(); ++iter) { 177cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceConfigValue* value = iter->get(); 178cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (value->config == config) { 179cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski results.push_back(value); 180cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ++iter; 181cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski break; 182e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 183cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 184e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 185cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (; iter != values.end(); ++iter) { 186cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceConfigValue* value = iter->get(); 187cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (value->config == config) { 188cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski results.push_back(value); 189e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 190cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 191cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return results; 192e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 193e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<ResourceConfigValue*> ResourceEntry::FindValuesIf( 195cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::function<bool(ResourceConfigValue*)>& f) { 196cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::vector<ResourceConfigValue*> results; 197cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski for (auto& configValue : values) { 198cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (f(configValue.get())) { 199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski results.push_back(configValue.get()); 200cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 201cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 202cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return results; 203458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski} 204458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski 2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 2065c3464c75fc517c0306a4ffd39c59671ccfde544Adam Lesinski * The default handler for collisions. 2078197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * 208cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Typically, a weak value will be overridden by a strong value. An existing 209cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * weak 2108197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * value will not be overridden by an incoming weak value. 2118197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * 2128197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * There are some exceptions: 2138197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * 2148197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * Attributes: There are two types of Attribute values: USE and DECL. 2158197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * 216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * USE is anywhere an Attribute is declared without a format, and in a place 217cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * that would 2188197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * be legal to declare if the Attribute already existed. This is typically in a 219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * <declare-styleable> tag. Attributes defined in a <declare-styleable> are also 220cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * weak. 2218197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * 222cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * DECL is an absolute declaration of an Attribute and specifies an explicit 223cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * format. 2248197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * 225cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * A DECL will override a USE without error. Two DECLs must match in their 226cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * format for there to be 2278197cc460e02c6445434eace435e3d38ebe475c6Adam Lesinski * no error. 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 229b1afa07745280c7a36077beda6293b69c6ba4ea2Adam LesinskiResourceTable::CollisionResult ResourceTable::ResolveValueCollision(Value* existing, 230b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski Value* incoming) { 231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* existing_attr = ValueCast<Attribute>(existing); 232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* incoming_attr = ValueCast<Attribute>(incoming); 233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!incoming_attr) { 234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (incoming->IsWeak()) { 235cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We're trying to add a weak resource but a resource 236cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // already exists. Keep the existing. 237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return CollisionResult::kKeepOriginal; 238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (existing->IsWeak()) { 239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Override the weak resource with the new strong resource. 240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return CollisionResult::kTakeNew; 241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 242cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The existing and incoming values are strong, this is an error 243cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // if the values are not both attributes. 244cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return CollisionResult::kConflict; 245cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!existing_attr) { 248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (existing->IsWeak()) { 249cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The existing value is not an attribute and it is weak, 250cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // so take the incoming attribute value. 251cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return CollisionResult::kTakeNew; 2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 253cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The existing value is not an attribute and it is strong, 254cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // so the incoming attribute value is an error. 2555c3464c75fc517c0306a4ffd39c59671ccfde544Adam Lesinski return CollisionResult::kConflict; 256cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(incoming_attr != nullptr && existing_attr != nullptr); 259cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 260cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // 261cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Attribute specific handling. At this point we know both 262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // values are attributes. Since we can declare and define 263cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // attributes all-over, we do special handling to see 264cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // which definition sticks. 265cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // 266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (existing_attr->type_mask == incoming_attr->type_mask) { 267cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The two attributes are both DECLs, but they are plain attributes 268cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // with the same formats. 269cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Keep the strongest one. 270b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return existing_attr->IsWeak() ? CollisionResult::kTakeNew : CollisionResult::kKeepOriginal; 271cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 272cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 273b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski if (existing_attr->IsWeak() && existing_attr->type_mask == android::ResTable_map::TYPE_ANY) { 274cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Any incoming attribute is better than this. 275cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return CollisionResult::kTakeNew; 276cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 277cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 278b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski if (incoming_attr->IsWeak() && incoming_attr->type_mask == android::ResTable_map::TYPE_ANY) { 279cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The incoming attribute may be a USE instead of a DECL. 280cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Keep the existing attribute. 281cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return CollisionResult::kKeepOriginal; 282cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 283cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return CollisionResult::kConflict; 2846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 286d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinskistatic constexpr const char* kValidNameChars = "._-"; 287b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski 288b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskistatic StringPiece ValidateName(const StringPiece& name) { 289b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski auto iter = util::FindNonAlphaNumericAndNotInSet(name, kValidNameChars); 290b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski if (iter != name.end()) { 291b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return StringPiece(iter, 1); 292b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski } 293b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return {}; 294b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski} 295b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski 296b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskistatic StringPiece SkipValidateName(const StringPiece& /*name*/) { 297b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return {}; 298b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski} 299330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool ResourceTable::AddResource(const ResourceNameRef& name, 301e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 302e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 303e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski std::unique_ptr<Value> value, 304e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski IDiagnostics* diag) { 305b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return AddResourceImpl(name, {}, config, product, std::move(value), ValidateName, 306b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski ResolveValueCollision, diag); 307330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 3086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool ResourceTable::AddResource(const ResourceNameRef& name, 310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ResourceId& res_id, 311e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 312e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 313e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski std::unique_ptr<Value> value, 314e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski IDiagnostics* diag) { 315b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return AddResourceImpl(name, res_id, config, product, std::move(value), ValidateName, 316b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski ResolveValueCollision, diag); 3171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 3181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool ResourceTable::AddFileReference(const ResourceNameRef& name, 320e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 321e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const Source& source, 322d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski const StringPiece& path, 3231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski IDiagnostics* diag) { 324b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return AddFileReferenceImpl(name, config, source, path, nullptr, ValidateName, diag); 325fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski} 326fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 327ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool ResourceTable::AddFileReferenceAllowMangled( 328cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceNameRef& name, const ConfigDescription& config, 329cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const Source& source, const StringPiece& path, io::IFile* file, 330cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski IDiagnostics* diag) { 331b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return AddFileReferenceImpl(name, config, source, path, file, SkipValidateName, diag); 332355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 333355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 334b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskibool ResourceTable::AddFileReferenceImpl(const ResourceNameRef& name, 335b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski const ConfigDescription& config, const Source& source, 336b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski const StringPiece& path, io::IFile* file, 337b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski NameValidator name_validator, IDiagnostics* diag) { 338cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<FileReference> fileRef = 339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::make_unique<FileReference>(string_pool.MakeRef(path)); 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski fileRef->SetSource(source); 341cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski fileRef->file = file; 342b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return AddResourceImpl(name, ResourceId{}, config, StringPiece{}, std::move(fileRef), 343b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski name_validator, ResolveValueCollision, diag); 344330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 345330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool ResourceTable::AddResourceAllowMangled(const ResourceNameRef& name, 347330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski const ConfigDescription& config, 348e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 3491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<Value> value, 3501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski IDiagnostics* diag) { 351b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return AddResourceImpl(name, ResourceId{}, config, product, std::move(value), SkipValidateName, 352b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski ResolveValueCollision, diag); 353330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 354330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool ResourceTable::AddResourceAllowMangled(const ResourceNameRef& name, 3569b8528fee4eed35b8e887ded0851d08eb2b10db6Chih-Hung Hsieh const ResourceId& id, 3579e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski const ConfigDescription& config, 358e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 3599e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski std::unique_ptr<Value> value, 3609e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski IDiagnostics* diag) { 361b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return AddResourceImpl(name, id, config, product, std::move(value), SkipValidateName, 362b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski ResolveValueCollision, diag); 3639e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski} 3649e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 365b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskibool ResourceTable::AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id, 366b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski const ConfigDescription& config, const StringPiece& product, 367b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski std::unique_ptr<Value> value, NameValidator name_validator, 368b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski const CollisionResolverFunc& conflictResolver, 369b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski IDiagnostics* diag) { 370ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(value != nullptr); 371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(diag != nullptr); 372cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 373b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski const StringPiece bad_char = name_validator(name.entry); 374b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski if (!bad_char.empty()) { 375b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski diag->Error(DiagMessage(value->GetSource()) << "resource '" << name 376b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski << "' has invalid entry name '" << name.entry 377b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski << "'. Invalid character '" << bad_char << "'"); 378b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski 379cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 380cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 381cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTablePackage* package = FindOrCreatePackage(name.package); 383ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) { 384ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(value->GetSource()) 385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "trying to add resource '" << name << "' with ID " << res_id 386cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << " but package '" << package->name << "' already has ID " 387cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << std::hex << (int)package->id.value() << std::dec); 388cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 389cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 390cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTableType* type = package->FindOrCreateType(name.type); 392ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (res_id.is_valid_dynamic() && type->id && type->id.value() != res_id.type_id()) { 393ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(value->GetSource()) 394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "trying to add resource '" << name << "' with ID " << res_id 395cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << " but type '" << type->type << "' already has ID " 396cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << std::hex << (int)type->id.value() << std::dec); 397cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 399cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceEntry* entry = type->FindOrCreateEntry(name.entry); 401ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (res_id.is_valid_dynamic() && entry->id && entry->id.value() != res_id.entry_id()) { 402ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(value->GetSource()) 403ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "trying to add resource '" << name << "' with ID " << res_id 404cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << " but resource already has ID " 405cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << ResourceId(package->id.value(), type->id.value(), 406cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski entry->id.value())); 407cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 408cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 409cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceConfigValue* config_value = entry->FindOrCreateValue(config, product); 411ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!config_value->value) { 412cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Resource does not exist, add it now. 413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski config_value->value = std::move(value); 414cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 415cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 416ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (conflictResolver(config_value->value.get(), value.get())) { 417cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski case CollisionResult::kTakeNew: 418cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Take the incoming value. 419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski config_value->value = std::move(value); 420cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski break; 4216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 422cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski case CollisionResult::kConflict: 423ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(value->GetSource()) 424cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "duplicate value for resource '" << name << "' " 425cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "with config '" << config << "'"); 426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(config_value->value->GetSource()) 427cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "resource previously defined here"); 4286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 429e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 430cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski case CollisionResult::kKeepOriginal: 431cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski break; 4326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 433cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 4346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 435ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (res_id.is_valid_dynamic()) { 436ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package->id = res_id.package_id(); 437ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski type->id = res_id.type_id(); 438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski entry->id = res_id.entry_id(); 439cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 440cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 4416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4434488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinskibool ResourceTable::SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id, 444e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const Symbol& symbol, IDiagnostics* diag) { 445b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return SetSymbolStateImpl(name, res_id, symbol, ValidateName, diag); 446330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 447330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool ResourceTable::SetSymbolStateAllowMangled(const ResourceNameRef& name, 449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ResourceId& res_id, 450cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const Symbol& symbol, 451cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski IDiagnostics* diag) { 452b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski return SetSymbolStateImpl(name, res_id, symbol, SkipValidateName, diag); 453330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 454330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 455b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinskibool ResourceTable::SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id, 456b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski const Symbol& symbol, NameValidator name_validator, 457e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski IDiagnostics* diag) { 458ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(diag != nullptr); 459cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 460b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski const StringPiece bad_char = name_validator(name.entry); 461b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski if (!bad_char.empty()) { 462b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski diag->Error(DiagMessage(symbol.source) << "resource '" << name << "' has invalid entry name '" 463b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski << name.entry << "'. Invalid character '" << bad_char 464b1afa07745280c7a36077beda6293b69c6ba4ea2Adam Lesinski << "'"); 465cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 467cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTablePackage* package = FindOrCreatePackage(name.package); 469ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) { 470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(symbol.source) 471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "trying to add resource '" << name << "' with ID " << res_id 472cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << " but package '" << package->name << "' already has ID " 473cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << std::hex << (int)package->id.value() << std::dec); 474cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 475cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTableType* type = package->FindOrCreateType(name.type); 478ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (res_id.is_valid_dynamic() && type->id && type->id.value() != res_id.type_id()) { 479ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(symbol.source) 480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "trying to add resource '" << name << "' with ID " << res_id 481cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << " but type '" << type->type << "' already has ID " 482cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << std::hex << (int)type->id.value() << std::dec); 483cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 484cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 486ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceEntry* entry = type->FindOrCreateEntry(name.entry); 487ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (res_id.is_valid_dynamic() && entry->id && entry->id.value() != res_id.entry_id()) { 488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(symbol.source) 489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "trying to add resource '" << name << "' with ID " << res_id 490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << " but resource already has ID " 4914488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski << ResourceId(package->id.value(), type->id.value(), entry->id.value())); 492cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 494cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 495ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (res_id.is_valid_dynamic()) { 496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package->id = res_id.package_id(); 497ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski type->id = res_id.type_id(); 498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski entry->id = res_id.entry_id(); 499cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 500cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 501cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Only mark the type state as public, it doesn't care about being private. 502cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (symbol.state == SymbolState::kPublic) { 503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski type->symbol_status.state = SymbolState::kPublic; 504cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 505cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 5064488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski if (symbol.allow_new) { 5074488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski // This symbol can be added as a new resource when merging (if it belongs to an overlay). 5084488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski entry->symbol_status.allow_new = true; 5094488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski } 5104488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski 511cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (symbol.state == SymbolState::kUndefined && 512ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski entry->symbol_status.state != SymbolState::kUndefined) { 513cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We can't undefine a symbol (remove its visibility). Ignore. 514769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return true; 515cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 516769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 517cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (symbol.state == SymbolState::kPrivate && 518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski entry->symbol_status.state == SymbolState::kPublic) { 519cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We can't downgrade public to private. Ignore. 520cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 5226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5234488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski // This symbol definition takes precedence, replace. 5244488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski entry->symbol_status.state = symbol.state; 5254488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski entry->symbol_status.source = symbol.source; 5264488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski entry->symbol_status.comment = symbol.comment; 527cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 528cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} 5296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 530b1afa07745280c7a36077beda6293b69c6ba4ea2Adam LesinskiMaybe<ResourceTable::SearchResult> ResourceTable::FindResource(const ResourceNameRef& name) { 531ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTablePackage* package = FindPackage(name.package); 532cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!package) { 533cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 534cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 535cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 536ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTableType* type = package->FindType(name.type); 537cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!type) { 538cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 539cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 540cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 541ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceEntry* entry = type->FindEntry(name.entry); 542cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!entry) { 543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return {}; 544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 545cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return SearchResult{package, type, entry}; 5466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 548cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 549