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