1e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski/* 2e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * Copyright (C) 2016 The Android Open Source Project 3e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * 4e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * you may not use this file except in compliance with the License. 6e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * You may obtain a copy of the License at 7e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * 8e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * 10e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * Unless required by applicable law or agreed to in writing, software 11e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * See the License for the specific language governing permissions and 14e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski * limitations under the License. 15e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski */ 16e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 17e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski#include "link/ProductFilter.h" 18e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 19e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskinamespace aapt { 20e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 21e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiProductFilter::ResourceConfigValueIter 22e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiProductFilter::selectProductToKeep(const ResourceNameRef& name, 23e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ResourceConfigValueIter begin, 24e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski const ResourceConfigValueIter end, 25e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski IDiagnostics* diag) { 26e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValueIter defaultProductIter = end; 27e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValueIter selectedProductIter = end; 28e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 29e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski for (ResourceConfigValueIter iter = begin; iter != end; ++iter) { 30e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* configValue = iter->get(); 31e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (mProducts.find(configValue->product) != mProducts.end()) { 32e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (selectedProductIter != end) { 33e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // We have two possible values for this product! 34e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski diag->error(DiagMessage(configValue->value->getSource()) 35e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski << "selection of product '" << configValue->product 36e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski << "' for resource " << name << " is ambiguous"); 37e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 38e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* previouslySelectedConfigValue = selectedProductIter->get(); 39e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski diag->note(DiagMessage(previouslySelectedConfigValue->value->getSource()) 40e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski << "product '" << previouslySelectedConfigValue->product 41e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski << "' is also a candidate"); 42e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return end; 43e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 44e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 45e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // Select this product. 46e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski selectedProductIter = iter; 47e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 48e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 49e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (configValue->product.empty() || configValue->product == "default") { 50e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (defaultProductIter != end) { 51e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // We have two possible default values. 52e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski diag->error(DiagMessage(configValue->value->getSource()) 53e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski << "multiple default products defined for resource " << name); 54e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 55e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* previouslyDefaultConfigValue = defaultProductIter->get(); 56e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski diag->note(DiagMessage(previouslyDefaultConfigValue->value->getSource()) 57e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski << "default product also defined here"); 58e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return end; 59e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 60e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 61e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // Mark the default. 62e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski defaultProductIter = iter; 63e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 64e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 65e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 66e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (defaultProductIter == end) { 67e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski diag->error(DiagMessage() << "no default product defined for resource " << name); 68e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return end; 69e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 70e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 71e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (selectedProductIter == end) { 72e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski selectedProductIter = defaultProductIter; 73e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 74e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return selectedProductIter; 75e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 76e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 77e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinskibool ProductFilter::consume(IAaptContext* context, ResourceTable* table) { 78e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski bool error = false; 79e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski for (auto& pkg : table->packages) { 80e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski for (auto& type : pkg->types) { 81e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski for (auto& entry : type->entries) { 82e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski std::vector<std::unique_ptr<ResourceConfigValue>> newValues; 83e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 84e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValueIter iter = entry->values.begin(); 85e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValueIter startRangeIter = iter; 86e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski while (iter != entry->values.end()) { 87e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ++iter; 88e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (iter == entry->values.end() || 89e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski (*iter)->config != (*startRangeIter)->config) { 90e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 91e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // End of the array, or we saw a different config, 92e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // so this must be the end of a range of products. 93e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // Select the product to keep from the set of products defined. 94e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceNameRef name(pkg->name, type->type, entry->name); 95e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski auto valueToKeep = selectProductToKeep(name, startRangeIter, iter, 96e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski context->getDiagnostics()); 97e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (valueToKeep == iter) { 98e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // An error occurred, we could not pick a product. 99e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski error = true; 100e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } else { 101e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // We selected a product to keep. Move it to the new array. 102e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski newValues.push_back(std::move(*valueToKeep)); 103e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 104e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 105e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // Start the next range of products. 106e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski startRangeIter = iter; 107e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 108e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 109e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 110e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski // Now move the new values in to place. 111e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski entry->values = std::move(newValues); 112e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 113e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 114e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski } 115e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return !error; 116e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} 117e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski 118e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski} // namespace aapt 119