ResourceTable.cpp revision e4bb9eb5af5b0899dc0921d5580220b20e15bd5a
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 176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ConfigDescription.h" 18769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include "NameMangler.h" 196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceTable.h" 206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceValues.h" 211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ValueVisitor.h" 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h" 236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <algorithm> 256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <androidfw/ResourceTypes.h> 266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <memory> 276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string> 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <tuple> 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistatic bool lessThanType(const std::unique_ptr<ResourceTableType>& lhs, ResourceType rhs) { 336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return lhs->type < rhs; 346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T> 371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistatic bool lessThanStructWithName(const std::unique_ptr<T>& lhs, 381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const StringPiece16& rhs) { 396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return lhs->name.compare(0, lhs->name.size(), rhs.data(), rhs.size()) < 0; 406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 421ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceTablePackage* ResourceTable::findPackage(const StringPiece16& name) { 431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const auto last = packages.end(); 441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto iter = std::lower_bound(packages.begin(), last, name, 451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski lessThanStructWithName<ResourceTablePackage>); 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (iter != last && name == (*iter)->name) { 471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return iter->get(); 481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return nullptr; 506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 521ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceTablePackage* ResourceTable::findPackageById(uint8_t id) { 531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (auto& package : packages) { 541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (package->id && package->id.value() == id) { 551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return package.get(); 566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return nullptr; 596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 619ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiResourceTablePackage* ResourceTable::createPackage(const StringPiece16& name, Maybe<uint8_t> id) { 621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTablePackage* package = findOrCreatePackage(name); 639ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski if (id && !package->id) { 641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski package->id = id; 651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return package; 666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 689ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski if (id && package->id && package->id.value() != id.value()) { 699ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski return nullptr; 701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 719ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski return package; 726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 741ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceTablePackage* ResourceTable::findOrCreatePackage(const StringPiece16& name) { 751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const auto last = packages.end(); 761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto iter = std::lower_bound(packages.begin(), last, name, 771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski lessThanStructWithName<ResourceTablePackage>); 781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (iter != last && name == (*iter)->name) { 791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return iter->get(); 801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<ResourceTablePackage> newPackage = util::make_unique<ResourceTablePackage>(); 831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski newPackage->name = name.toString(); 841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return packages.emplace(iter, std::move(newPackage))->get(); 851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 871ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceTableType* ResourceTablePackage::findType(ResourceType type) { 881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const auto last = types.end(); 891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto iter = std::lower_bound(types.begin(), last, type, lessThanType); 901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (iter != last && (*iter)->type == type) { 911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return iter->get(); 926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return nullptr; 941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 961ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceTableType* ResourceTablePackage::findOrCreateType(ResourceType type) { 971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const auto last = types.end(); 981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto iter = std::lower_bound(types.begin(), last, type, lessThanType); 991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (iter != last && (*iter)->type == type) { 1001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return iter->get(); 1016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 102a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski return types.emplace(iter, new ResourceTableType(type))->get(); 1031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1051ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceEntry* ResourceTableType::findEntry(const StringPiece16& name) { 1061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const auto last = entries.end(); 1071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto iter = std::lower_bound(entries.begin(), last, name, 1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski lessThanStructWithName<ResourceEntry>); 1091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (iter != last && name == (*iter)->name) { 1101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return iter->get(); 1111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return nullptr; 1131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1151ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceEntry* ResourceTableType::findOrCreateEntry(const StringPiece16& name) { 1161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto last = entries.end(); 1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto iter = std::lower_bound(entries.begin(), last, name, 1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski lessThanStructWithName<ResourceEntry>); 1191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (iter != last && name == (*iter)->name) { 1201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return iter->get(); 1211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 122a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski return entries.emplace(iter, new ResourceEntry(name))->get(); 1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 125e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiResourceConfigValue* ResourceEntry::findValue(const ConfigDescription& config) { 126e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return findValue(config, StringPiece()); 127e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 128e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 129e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskistruct ConfigKey { 130e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription* config; 131e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product; 132e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski}; 133e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 134e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ltConfigKeyRef(const std::unique_ptr<ResourceConfigValue>& lhs, const ConfigKey& rhs) { 135e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski int cmp = lhs->config.compare(*rhs.config); 136e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (cmp == 0) { 137e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski cmp = StringPiece(lhs->product).compare(rhs.product); 138e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 139e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return cmp < 0; 140e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 141e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 142e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiResourceConfigValue* ResourceEntry::findValue(const ConfigDescription& config, 143e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product) { 144e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski auto iter = std::lower_bound(values.begin(), values.end(), 145e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ConfigKey{ &config, product }, ltConfigKeyRef); 146e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (iter != values.end()) { 147e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* value = iter->get(); 148e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (value->config == config && StringPiece(value->product) == product) { 149e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return value; 150e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 151e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 152e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return nullptr; 153e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 154e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 155e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiResourceConfigValue* ResourceEntry::findOrCreateValue(const ConfigDescription& config, 156e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product) { 157e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski auto iter = std::lower_bound(values.begin(), values.end(), 158e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ConfigKey{ &config, product }, ltConfigKeyRef); 159e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (iter != values.end()) { 160e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* value = iter->get(); 161e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (value->config == config && StringPiece(value->product) == product) { 162e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return value; 163e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 164e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 165e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* newValue = values.insert( 166e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski iter, util::make_unique<ResourceConfigValue>(config, product))->get(); 167e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return newValue; 168e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 169e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 170e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskistd::vector<ResourceConfigValue*> ResourceEntry::findAllValues(const ConfigDescription& config) { 171e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski std::vector<ResourceConfigValue*> results; 172e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 173e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski auto iter = values.begin(); 174e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski for (; iter != values.end(); ++iter) { 175e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* value = iter->get(); 176e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (value->config == config) { 177e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski results.push_back(value); 178e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ++iter; 179e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski break; 180e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 181e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 182e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 183e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski for (; iter != values.end(); ++iter) { 184e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* value = iter->get(); 185e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (value->config == config) { 186e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski results.push_back(value); 187e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 188e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 189e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return results; 190e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 191e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * The default handler for collisions. A return value of -1 means keep the 1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * existing value, 0 means fail, and +1 means take the incoming value. 1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 1961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiint ResourceTable::resolveValueCollision(Value* existing, Value* incoming) { 1971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* existingAttr = valueCast<Attribute>(existing); 1981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* incomingAttr = valueCast<Attribute>(incoming); 1996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!incomingAttr) { 2011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (incoming->isWeak()) { 2026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We're trying to add a weak resource but a resource 2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // already exists. Keep the existing. 2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return -1; 2051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } else if (existing->isWeak()) { 2066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Override the weak resource with the new strong resource. 2076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 1; 2086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The existing and incoming values are strong, this is an error 2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // if the values are not both attributes. 2116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 0; 2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!existingAttr) { 2151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (existing->isWeak()) { 2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The existing value is not an attribute and it is weak, 2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // so take the incoming attribute value. 2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 1; 2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The existing value is not an attribute and it is strong, 2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // so the incoming attribute value is an error. 2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 0; 2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski assert(incomingAttr && existingAttr); 2261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Attribute specific handling. At this point we know both 2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // values are attributes. Since we can declare and define 2306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // attributes all-over, we do special handling to see 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // which definition sticks. 2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // 2331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (existingAttr->typeMask == incomingAttr->typeMask) { 2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The two attributes are both DECLs, but they are plain attributes 2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // with the same formats. 2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Keep the strongest one. 2371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return existingAttr->isWeak() ? 1 : -1; 2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (existingAttr->isWeak() && existingAttr->typeMask == android::ResTable_map::TYPE_ANY) { 2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Any incoming attribute is better than this. 2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 1; 2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (incomingAttr->isWeak() && incomingAttr->typeMask == android::ResTable_map::TYPE_ANY) { 2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The incoming attribute may be a USE instead of a DECL. 2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Keep the existing attribute. 2486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return -1; 2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 0; 2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistatic constexpr const char16_t* kValidNameChars = u"._-"; 254330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinskistatic constexpr const char16_t* kValidNameMangledChars = u"._-$"; 255330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 256e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ResourceTable::addResource(const ResourceNameRef& name, 257e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 258e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 259e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski std::unique_ptr<Value> value, 260e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski IDiagnostics* diag) { 261e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, {}, config, product, std::move(value), kValidNameChars, 262fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski resolveValueCollision, diag); 263330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 265e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ResourceTable::addResource(const ResourceNameRef& name, 266e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ResourceId resId, 267e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 268e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 269e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski std::unique_ptr<Value> value, 270e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski IDiagnostics* diag) { 271e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, resId, config, product, std::move(value), kValidNameChars, 272fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski resolveValueCollision, diag); 2731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 2741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 275e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ResourceTable::addFileReference(const ResourceNameRef& name, 276e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 277e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const Source& source, 278e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece16& path, 2791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski IDiagnostics* diag) { 280fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski return addFileReference(name, config, source, path, resolveValueCollision, diag); 281fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski} 282fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 283e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ResourceTable::addFileReference(const ResourceNameRef& name, 284e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 285e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const Source& source, 286e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece16& path, 287fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski std::function<int(Value*,Value*)> conflictResolver, 288fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski IDiagnostics* diag) { 289e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::unique_ptr<FileReference> fileRef = util::make_unique<FileReference>( 290e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski stringPool.makeRef(path)); 291e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski fileRef->setSource(source); 292e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, ResourceId{}, config, StringPiece{}, std::move(fileRef), 293e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski kValidNameChars, conflictResolver, diag); 294330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 295330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 296330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinskibool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name, 297330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski const ConfigDescription& config, 298e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 2991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<Value> value, 3001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski IDiagnostics* diag) { 301e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, ResourceId{}, config, product, std::move(value), 302e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski kValidNameMangledChars, resolveValueCollision, diag); 303330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 304330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 3059e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinskibool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name, 3069e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski const ResourceId id, 3079e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski const ConfigDescription& config, 308e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 3099e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski std::unique_ptr<Value> value, 3109e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski IDiagnostics* diag) { 311e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, id, config, product, std::move(value), kValidNameMangledChars, 312fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski resolveValueCollision, diag); 3139e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski} 3149e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 315fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinskibool ResourceTable::addResourceImpl(const ResourceNameRef& name, 316fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski const ResourceId resId, 317fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski const ConfigDescription& config, 318e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 319fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski std::unique_ptr<Value> value, 320fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski const char16_t* validChars, 321fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski std::function<int(Value*,Value*)> conflictResolver, 322fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski IDiagnostics* diag) { 323e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski assert(value && "value can't be nullptr"); 324e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski assert(diag && "diagnostics can't be nullptr"); 325e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 3261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, validChars); 3271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (badCharIter != name.entry.end()) { 328e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "resource '" 3301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 3311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' has invalid entry name '" 3321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name.entry 3331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "'. Invalid character '" 3341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << StringPiece16(badCharIter, 1) 3351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "'"); 3366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTablePackage* package = findOrCreatePackage(name.package); 3401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && package->id && package->id.value() != resId.packageId()) { 341e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 3431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 3441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 3451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 3461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but package '" 3471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << package->name 3481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' already has ID " 3491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << std::hex << (int) package->id.value() << std::dec); 3506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTableType* type = package->findOrCreateType(name.type); 3541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && type->id && type->id.value() != resId.typeId()) { 355e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 3571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 3581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 3591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 3601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but type '" 3611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << type->type 3621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' already has ID " 3631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << std::hex << (int) type->id.value() << std::dec); 3646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceEntry* entry = type->findOrCreateEntry(name.entry); 3681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && entry->id && entry->id.value() != resId.entryId()) { 369e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 3711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 3721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 3731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 3741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but resource already has ID " 3751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << ResourceId(package->id.value(), type->id.value(), entry->id.value())); 3766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 379e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* configValue = entry->findOrCreateValue(config, product); 380e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (!configValue->value) { 381e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // Resource does not exist, add it now. 382e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski configValue->value = std::move(value); 383e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 3846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else { 385e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski int collisionResult = conflictResolver(configValue->value.get(), value.get()); 3866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (collisionResult > 0) { 3876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Take the incoming value. 388e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski configValue->value = std::move(value); 3896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (collisionResult == 0) { 390e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "duplicate value for resource '" << name << "' " 392e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski << "with config '" << config << "'"); 393e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski diag->error(DiagMessage(configValue->value->getSource()) 3941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "resource previously defined here"); 3956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (resId.isValid()) { 4001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski package->id = resId.packageId(); 4011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski type->id = resId.typeId(); 4021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski entry->id = resId.entryId(); 4036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return true; 4056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4079e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinskibool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId resId, 408e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const Symbol& symbol, IDiagnostics* diag) { 409e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski return setSymbolStateImpl(name, resId, symbol, kValidNameChars, diag); 410330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 411330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 412e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinskibool ResourceTable::setSymbolStateAllowMangled(const ResourceNameRef& name, 413e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const ResourceId resId, 414e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const Symbol& symbol, IDiagnostics* diag) { 415e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski return setSymbolStateImpl(name, resId, symbol, kValidNameMangledChars, diag); 416330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 417330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 4189e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinskibool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId resId, 419e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const Symbol& symbol, const char16_t* validChars, 420e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski IDiagnostics* diag) { 421e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski assert(diag && "diagnostics can't be nullptr"); 422e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 4231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, validChars); 4241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (badCharIter != name.entry.end()) { 425e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(symbol.source) 4261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "resource '" 4271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 4281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' has invalid entry name '" 4291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name.entry 4301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "'. Invalid character '" 4311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << StringPiece16(badCharIter, 1) 4321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "'"); 4336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTablePackage* package = findOrCreatePackage(name.package); 4371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && package->id && package->id.value() != resId.packageId()) { 438e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(symbol.source) 4391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 4401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 4411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 4421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 4431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but package '" 4441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << package->name 4451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' already has ID " 4461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << std::hex << (int) package->id.value() << std::dec); 4476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTableType* type = package->findOrCreateType(name.type); 4511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && type->id && type->id.value() != resId.typeId()) { 452e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(symbol.source) 4531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 4541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 4551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 4561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 4571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but type '" 4581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << type->type 4591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' already has ID " 4601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << std::hex << (int) type->id.value() << std::dec); 4616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceEntry* entry = type->findOrCreateEntry(name.entry); 4651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && entry->id && entry->id.value() != resId.entryId()) { 466e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(symbol.source) 4671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 4681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 4691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 4701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 4711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but resource already has ID " 4721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << ResourceId(package->id.value(), type->id.value(), entry->id.value())); 4736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 476a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski if (resId.isValid()) { 477a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski package->id = resId.packageId(); 478a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski type->id = resId.typeId(); 479a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski entry->id = resId.entryId(); 480a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski } 481a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 4829e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski // Only mark the type state as public, it doesn't care about being private. 483e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski if (symbol.state == SymbolState::kPublic) { 4849e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski type->symbolStatus.state = SymbolState::kPublic; 4859e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski } 4869e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 487a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski if (symbol.state == SymbolState::kUndefined && 488a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski entry->symbolStatus.state != SymbolState::kUndefined) { 489a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski // We can't undefine a symbol (remove its visibility). Ignore. 490a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski return true; 4919e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski } 4926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 493a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski if (symbol.state == SymbolState::kPrivate && 494a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski entry->symbolStatus.state == SymbolState::kPublic) { 495a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski // We can't downgrade public to private. Ignore. 496a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski return true; 497769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 498a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 499a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski entry->symbolStatus = std::move(symbol); 500769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return true; 501769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 502769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 5031ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiMaybe<ResourceTable::SearchResult> 5041ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceTable::findResource(const ResourceNameRef& name) { 5051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTablePackage* package = findPackage(name.package); 5061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!package) { 507ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski return {}; 5086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 5096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTableType* type = package->findType(name.type); 5111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!type) { 512ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski return {}; 5136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 5146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceEntry* entry = type->findEntry(name.entry); 5161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!entry) { 517ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski return {}; 5186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 5191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return SearchResult{ package, type, entry }; 5206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 523