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 192458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinskistd::vector<ResourceConfigValue*> ResourceEntry::findValuesIf( 193458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski const std::function<bool(ResourceConfigValue*)>& f) { 194458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski std::vector<ResourceConfigValue*> results; 195458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski for (auto& configValue : values) { 196458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski if (f(configValue.get())) { 197458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski results.push_back(configValue.get()); 198458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski } 199458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski } 200458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski return results; 201458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski} 202458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski 2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * The default handler for collisions. A return value of -1 means keep the 2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * existing value, 0 means fail, and +1 means take the incoming value. 2066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 2071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiint ResourceTable::resolveValueCollision(Value* existing, Value* incoming) { 2081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* existingAttr = valueCast<Attribute>(existing); 2091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* incomingAttr = valueCast<Attribute>(incoming); 2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!incomingAttr) { 2121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (incoming->isWeak()) { 2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // We're trying to add a weak resource but a resource 2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // already exists. Keep the existing. 2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return -1; 2161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } else if (existing->isWeak()) { 2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Override the weak resource with the new strong resource. 2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 1; 2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The existing and incoming values are strong, this is an error 2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // if the values are not both attributes. 2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 0; 2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!existingAttr) { 2261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (existing->isWeak()) { 2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The existing value is not an attribute and it is weak, 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // so take the incoming attribute value. 2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 1; 2306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The existing value is not an attribute and it is strong, 2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // so the incoming attribute value is an error. 2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 0; 2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski assert(incomingAttr && existingAttr); 2371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // 2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Attribute specific handling. At this point we know both 2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // values are attributes. Since we can declare and define 2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // attributes all-over, we do special handling to see 2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // which definition sticks. 2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // 2441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (existingAttr->typeMask == incomingAttr->typeMask) { 2456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The two attributes are both DECLs, but they are plain attributes 2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // with the same formats. 2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Keep the strongest one. 2481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return existingAttr->isWeak() ? 1 : -1; 2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (existingAttr->isWeak() && existingAttr->typeMask == android::ResTable_map::TYPE_ANY) { 2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Any incoming attribute is better than this. 2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 1; 2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (incomingAttr->isWeak() && incomingAttr->typeMask == android::ResTable_map::TYPE_ANY) { 2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // The incoming attribute may be a USE instead of a DECL. 2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Keep the existing attribute. 2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return -1; 2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return 0; 2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistatic constexpr const char16_t* kValidNameChars = u"._-"; 265330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinskistatic constexpr const char16_t* kValidNameMangledChars = u"._-$"; 266330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 267e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ResourceTable::addResource(const ResourceNameRef& name, 268e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 269e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 270e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski std::unique_ptr<Value> value, 271e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski IDiagnostics* diag) { 272e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, {}, config, product, std::move(value), kValidNameChars, 273fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski resolveValueCollision, diag); 274330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 2756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 276e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ResourceTable::addResource(const ResourceNameRef& name, 277e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ResourceId resId, 278e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 279e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 280e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski std::unique_ptr<Value> value, 281e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski IDiagnostics* diag) { 282e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, resId, config, product, std::move(value), kValidNameChars, 283fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski resolveValueCollision, diag); 2841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 2851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 286e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ResourceTable::addFileReference(const ResourceNameRef& name, 287e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ConfigDescription& config, 288e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const Source& source, 289e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece16& path, 2901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski IDiagnostics* diag) { 291355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski return addFileReferenceImpl(name, config, source, path, nullptr, kValidNameChars, diag); 292fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski} 293fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski 294355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskibool ResourceTable::addFileReferenceAllowMangled(const ResourceNameRef& name, 295355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const ConfigDescription& config, 296355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const Source& source, 297355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const StringPiece16& path, 298355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski io::IFile* file, 299355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski IDiagnostics* diag) { 300355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski return addFileReferenceImpl(name, config, source, path, file, kValidNameMangledChars, diag); 301355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 302355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 303355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskibool ResourceTable::addFileReferenceImpl(const ResourceNameRef& name, 304355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const ConfigDescription& config, 305355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const Source& source, 306355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const StringPiece16& path, 307355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski io::IFile* file, 308355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const char16_t* validChars, 309355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski IDiagnostics* diag) { 310e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::unique_ptr<FileReference> fileRef = util::make_unique<FileReference>( 311e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski stringPool.makeRef(path)); 312e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski fileRef->setSource(source); 313355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski fileRef->file = file; 314e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, ResourceId{}, config, StringPiece{}, std::move(fileRef), 315355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski kValidNameChars, resolveValueCollision, diag); 316330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 317330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 318330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinskibool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name, 319330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski const ConfigDescription& config, 320e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 3211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<Value> value, 3221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski IDiagnostics* diag) { 323e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, ResourceId{}, config, product, std::move(value), 324e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski kValidNameMangledChars, resolveValueCollision, diag); 325330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 326330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 3279e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinskibool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name, 3289e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski const ResourceId id, 3299e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski const ConfigDescription& config, 330e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 3319e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski std::unique_ptr<Value> value, 3329e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski IDiagnostics* diag) { 333e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return addResourceImpl(name, id, config, product, std::move(value), kValidNameMangledChars, 334fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski resolveValueCollision, diag); 3359e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski} 3369e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 337fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinskibool ResourceTable::addResourceImpl(const ResourceNameRef& name, 338fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski const ResourceId resId, 339fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski const ConfigDescription& config, 340e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const StringPiece& product, 341fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski std::unique_ptr<Value> value, 342fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski const char16_t* validChars, 343fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski std::function<int(Value*,Value*)> conflictResolver, 344fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski IDiagnostics* diag) { 345e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski assert(value && "value can't be nullptr"); 346e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski assert(diag && "diagnostics can't be nullptr"); 347e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 3481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, validChars); 3491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (badCharIter != name.entry.end()) { 350e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "resource '" 3521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 3531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' has invalid entry name '" 3541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name.entry 3551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "'. Invalid character '" 3561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << StringPiece16(badCharIter, 1) 3571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "'"); 3586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTablePackage* package = findOrCreatePackage(name.package); 3621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && package->id && package->id.value() != resId.packageId()) { 363e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 3651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 3661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 3671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 3681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but package '" 3691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << package->name 3701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' already has ID " 3711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << std::hex << (int) package->id.value() << std::dec); 3726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTableType* type = package->findOrCreateType(name.type); 3761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && type->id && type->id.value() != resId.typeId()) { 377e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 3791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 3801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 3811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 3821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but type '" 3831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << type->type 3841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' already has ID " 3851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << std::hex << (int) type->id.value() << std::dec); 3866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 3886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceEntry* entry = type->findOrCreateEntry(name.entry); 3901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && entry->id && entry->id.value() != resId.entryId()) { 391e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 3921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 3931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 3941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 3951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 3961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but resource already has ID " 3971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << ResourceId(package->id.value(), type->id.value(), entry->id.value())); 3986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 3996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 401e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* configValue = entry->findOrCreateValue(config, product); 402e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (!configValue->value) { 403e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // Resource does not exist, add it now. 404e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski configValue->value = std::move(value); 405e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 4066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else { 407e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski int collisionResult = conflictResolver(configValue->value.get(), value.get()); 4086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (collisionResult > 0) { 4096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski // Take the incoming value. 410e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski configValue->value = std::move(value); 4116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } else if (collisionResult == 0) { 412e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(value->getSource()) 4131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "duplicate value for resource '" << name << "' " 414e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski << "with config '" << config << "'"); 415e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski diag->error(DiagMessage(configValue->value->getSource()) 4161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "resource previously defined here"); 4176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski if (resId.isValid()) { 4221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski package->id = resId.packageId(); 4231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski type->id = resId.typeId(); 4241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski entry->id = resId.entryId(); 4256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return true; 4276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4299e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinskibool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId resId, 430e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const Symbol& symbol, IDiagnostics* diag) { 431e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski return setSymbolStateImpl(name, resId, symbol, kValidNameChars, diag); 432330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 433330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 434e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinskibool ResourceTable::setSymbolStateAllowMangled(const ResourceNameRef& name, 435e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const ResourceId resId, 436e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const Symbol& symbol, IDiagnostics* diag) { 437e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski return setSymbolStateImpl(name, resId, symbol, kValidNameMangledChars, diag); 438330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 439330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 4409e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinskibool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId resId, 441e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski const Symbol& symbol, const char16_t* validChars, 442e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski IDiagnostics* diag) { 443e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski assert(diag && "diagnostics can't be nullptr"); 444e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 4451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, validChars); 4461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (badCharIter != name.entry.end()) { 447e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(symbol.source) 4481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "resource '" 4491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 4501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' has invalid entry name '" 4511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name.entry 4521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "'. Invalid character '" 4531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << StringPiece16(badCharIter, 1) 4541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "'"); 4556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTablePackage* package = findOrCreatePackage(name.package); 4591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && package->id && package->id.value() != resId.packageId()) { 460e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(symbol.source) 4611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 4621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 4631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 4641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 4651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but package '" 4661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << package->name 4671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' already has ID " 4681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << std::hex << (int) package->id.value() << std::dec); 4696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTableType* type = package->findOrCreateType(name.type); 4731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && type->id && type->id.value() != resId.typeId()) { 474e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(symbol.source) 4751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 4761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 4771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 4781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 4791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but type '" 4801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << type->type 4811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' already has ID " 4821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << std::hex << (int) type->id.value() << std::dec); 4836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceEntry* entry = type->findOrCreateEntry(name.entry); 4871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (resId.isValid() && entry->id && entry->id.value() != resId.entryId()) { 488e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski diag->error(DiagMessage(symbol.source) 4891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "trying to add resource '" 4901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << name 4911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << "' with ID " 4921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << resId 4931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << " but resource already has ID " 4941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << ResourceId(package->id.value(), type->id.value(), entry->id.value())); 4956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 4966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 498a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski if (resId.isValid()) { 499a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski package->id = resId.packageId(); 500a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski type->id = resId.typeId(); 501a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski entry->id = resId.entryId(); 502a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski } 503a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 5049e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski // Only mark the type state as public, it doesn't care about being private. 505e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski if (symbol.state == SymbolState::kPublic) { 5069e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski type->symbolStatus.state = SymbolState::kPublic; 5079e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski } 5089e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski 509a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski if (symbol.state == SymbolState::kUndefined && 510a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski entry->symbolStatus.state != SymbolState::kUndefined) { 511a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski // We can't undefine a symbol (remove its visibility). Ignore. 512a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski return true; 5139e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski } 5146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 515a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski if (symbol.state == SymbolState::kPrivate && 516a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski entry->symbolStatus.state == SymbolState::kPublic) { 517a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski // We can't downgrade public to private. Ignore. 518a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski return true; 519769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 520a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 521a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski entry->symbolStatus = std::move(symbol); 522769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return true; 523769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 524769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 5251ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiMaybe<ResourceTable::SearchResult> 5261ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiResourceTable::findResource(const ResourceNameRef& name) { 5271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTablePackage* package = findPackage(name.package); 5281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!package) { 529ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski return {}; 5306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 5316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTableType* type = package->findType(name.type); 5331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!type) { 534ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski return {}; 5356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 5366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceEntry* entry = type->findEntry(name.entry); 5381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!entry) { 539ca2fc353c2b07e24e297fdc8426c7abd601d908bAdam Lesinski return {}; 5406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 5411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return SearchResult{ package, type, entry }; 5426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 545