blob: 93c904f1a743206811b7c5786b9a32a4b5de1829 [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
2 * Copyright (C) 2015 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 Lesinskicacb28f2016-10-19 12:18:14 -070017#include "link/TableMerger.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070018
19#include "android-base/logging.h"
20
Adam Lesinski1ab598f2015-08-14 14:26:04 -070021#include "ResourceTable.h"
Adam Lesinskia6fe3452015-12-09 15:20:52 -080022#include "ResourceUtils.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070023#include "ResourceValues.h"
24#include "ValueVisitor.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070025#include "util/Util.h"
26
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070027using ::android::StringPiece;
Adam Lesinskid5083f62017-01-16 15:07:21 -080028
Adam Lesinski1ab598f2015-08-14 14:26:04 -070029namespace aapt {
30
Adam Lesinskice5e56e2016-10-21 17:56:45 -070031TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table,
Adam Lesinskicacb28f2016-10-19 12:18:14 -070032 const TableMergerOptions& options)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070033 : context_(context), master_table_(out_table), options_(options) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070034 // Create the desired package that all tables will be merged into.
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070035 master_package_ =
36 master_table_->CreatePackage(context_->GetCompilationPackage(), context_->GetPackageId());
Adam Lesinskice5e56e2016-10-21 17:56:45 -070037 CHECK(master_package_ != nullptr) << "package name or ID already taken";
Adam Lesinski1ab598f2015-08-14 14:26:04 -070038}
39
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070040bool TableMerger::Merge(const Source& src, ResourceTable* table, io::IFileCollection* collection) {
41 return MergeImpl(src, table, collection, false /*overlay*/, true /*allow_new*/);
Adam Lesinski64587af2016-02-18 18:33:06 -080042}
43
Adam Lesinskice5e56e2016-10-21 17:56:45 -070044bool TableMerger::MergeOverlay(const Source& src, ResourceTable* table,
Adam Lesinski64587af2016-02-18 18:33:06 -080045 io::IFileCollection* collection) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070046 return MergeImpl(src, table, collection, true /*overlay*/, options_.auto_add_overlay);
Adam Lesinski64587af2016-02-18 18:33:06 -080047}
48
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070049// This will merge packages with the same package name (or no package name).
Adam Lesinskice5e56e2016-10-21 17:56:45 -070050bool TableMerger::MergeImpl(const Source& src, ResourceTable* table,
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070051 io::IFileCollection* collection, bool overlay, bool allow_new) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070052 bool error = false;
53 for (auto& package : table->packages) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070054 // Only merge an empty package or the package we're building.
55 // Other packages may exist, which likely contain attribute definitions.
56 // This is because at compile time it is unknown if the attributes are
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -080057 // simply uses of the attribute or definitions.
58 if (package->name.empty() || context_->GetCompilationPackage() == package->name) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070059 FileMergeCallback callback;
60 if (collection) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070061 callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
62 FileReference* new_file, FileReference* old_file) -> bool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070063 // The old file's path points inside the APK, so we can use it as is.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070064 io::IFile* f = collection->FindFile(*old_file->path);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 if (!f) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070066 context_->GetDiagnostics()->Error(DiagMessage(src)
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -080067 << "file '" << *old_file->path << "' not found");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070068 return false;
69 }
70
Adam Lesinskice5e56e2016-10-21 17:56:45 -070071 new_file->file = f;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 return true;
73 };
74 }
75
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070076 // Merge here. Once the entries are merged and mangled, any references to them are still
77 // valid. This is because un-mangled references are mangled, then looked up at resolution
78 // time. Also, when linking, we convert references with no package name to use the compilation
79 // package name.
80 error |=
81 !DoMerge(src, table, package.get(), false /* mangle */, overlay, allow_new, callback);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 }
83 }
84 return !error;
Adam Lesinski83f22552015-11-07 11:51:23 -080085}
86
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070087// This will merge and mangle resources from a static library.
88bool TableMerger::MergeAndMangle(const Source& src, const StringPiece& package_name,
89 ResourceTable* table, io::IFileCollection* collection) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 bool error = false;
91 for (auto& package : table->packages) {
92 // Warn of packages with an unrelated ID.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093 if (package_name != package->name) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070094 context_->GetDiagnostics()->Warn(DiagMessage(src) << "ignoring package " << package->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070095 continue;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070096 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097
Adam Lesinskice5e56e2016-10-21 17:56:45 -070098 bool mangle = package_name != context_->GetCompilationPackage();
99 merged_packages_.insert(package->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700101 auto callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
102 FileReference* new_file, FileReference* old_file) -> bool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103 // The old file's path points inside the APK, so we can use it as is.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104 io::IFile* f = collection->FindFile(*old_file->path);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700105 if (!f) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700106 context_->GetDiagnostics()->Error(DiagMessage(src)
107 << "file '" << *old_file->path << "' not found");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700108 return false;
109 }
110
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700111 new_file->file = f;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700112 return true;
113 };
114
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700115 error |= !DoMerge(src, table, package.get(), mangle, false /*overlay*/, true /*allow_new*/,
116 callback);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 }
118 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700119}
120
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700121static bool MergeType(IAaptContext* context, const Source& src, ResourceTableType* dst_type,
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700122 ResourceTableType* src_type) {
123 if (dst_type->symbol_status.state < src_type->symbol_status.state) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700124 // The incoming type's visibility is stronger, so we should override the visibility.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700125 if (src_type->symbol_status.state == SymbolState::kPublic) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700126 // Only copy the ID if the source is public, or else the ID is meaningless.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700127 dst_type->id = src_type->id;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700128 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700129 dst_type->symbol_status = std::move(src_type->symbol_status);
130 } else if (dst_type->symbol_status.state == SymbolState::kPublic &&
131 src_type->symbol_status.state == SymbolState::kPublic &&
132 dst_type->id && src_type->id &&
133 dst_type->id.value() != src_type->id.value()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700134 // Both types are public and have different IDs.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700135 context->GetDiagnostics()->Error(DiagMessage(src)
136 << "cannot merge type '" << src_type->type
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700137 << "': conflicting public IDs");
138 return false;
139 }
140 return true;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700141}
142
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700143static bool MergeEntry(IAaptContext* context, const Source& src, ResourceEntry* dst_entry,
144 ResourceEntry* src_entry) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700145 if (dst_entry->symbol_status.state < src_entry->symbol_status.state) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700146 // The incoming type's visibility is stronger, so we should override the visibility.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700147 if (src_entry->symbol_status.state == SymbolState::kPublic) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700148 // Only copy the ID if the source is public, or else the ID is meaningless.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700149 dst_entry->id = src_entry->id;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700150 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700151 dst_entry->symbol_status = std::move(src_entry->symbol_status);
152 } else if (src_entry->symbol_status.state == SymbolState::kPublic &&
153 dst_entry->symbol_status.state == SymbolState::kPublic &&
154 dst_entry->id && src_entry->id &&
155 dst_entry->id.value() != src_entry->id.value()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700156 // Both entries are public and have different IDs.
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700157 context->GetDiagnostics()->Error(DiagMessage(src) << "cannot merge entry '" << src_entry->name
158 << "': conflicting public IDs");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700159 return false;
160 }
161 return true;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700162}
163
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700164// Modified CollisionResolver which will merge Styleables and Styles. Used with overlays.
165//
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700166// Styleables are not actual resources, but they are treated as such during the compilation phase.
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700167//
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700168// Styleables and Styles don't simply overlay each other, their definitions merge and accumulate.
169// If both values are Styleables/Styles, we just merge them into the existing value.
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700170static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, Value* incoming,
171 StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700172 if (Styleable* existing_styleable = ValueCast<Styleable>(existing)) {
173 if (Styleable* incoming_styleable = ValueCast<Styleable>(incoming)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700174 // Styleables get merged.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700175 existing_styleable->MergeWith(incoming_styleable);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700176 return ResourceTable::CollisionResult::kKeepOriginal;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700177 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700178 } else if (Style* existing_style = ValueCast<Style>(existing)) {
179 if (Style* incoming_style = ValueCast<Style>(incoming)) {
180 // Styles get merged.
181 existing_style->MergeWith(incoming_style, pool);
182 return ResourceTable::CollisionResult::kKeepOriginal;
183 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700184 }
185 // Delegate to the default handler.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700186 return ResourceTable::ResolveValueCollision(existing, incoming);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700187}
188
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700189static ResourceTable::CollisionResult MergeConfigValue(IAaptContext* context,
190 const ResourceNameRef& res_name,
191 const bool overlay,
192 ResourceConfigValue* dst_config_value,
193 ResourceConfigValue* src_config_value,
194 StringPool* pool) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700195 using CollisionResult = ResourceTable::CollisionResult;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700196
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700197 Value* dst_value = dst_config_value->value.get();
198 Value* src_value = src_config_value->value.get();
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700199
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700200 CollisionResult collision_result;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700201 if (overlay) {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700202 collision_result = ResolveMergeCollision(dst_value, src_value, pool);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700203 } else {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700204 collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700205 }
206
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700207 if (collision_result == CollisionResult::kConflict) {
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700208 if (overlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700209 return CollisionResult::kTakeNew;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700210 }
211
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700212 // Error!
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700213 context->GetDiagnostics()->Error(DiagMessage(src_value->GetSource())
214 << "resource '" << res_name << "' has a conflicting value for "
215 << "configuration (" << src_config_value->config << ")");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700216 context->GetDiagnostics()->Note(DiagMessage(dst_value->GetSource())
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700217 << "originally defined here");
218 return CollisionResult::kConflict;
219 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700220 return collision_result;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700221}
222
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700223bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table,
224 ResourceTablePackage* src_package,
225 const bool mangle_package, const bool overlay,
226 const bool allow_new_resources,
Chih-Hung Hsieh9b8528f2016-08-10 14:15:30 -0700227 const FileMergeCallback& callback) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700228 bool error = false;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700229
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700230 for (auto& src_type : src_package->types) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700231 ResourceTableType* dst_type = master_package_->FindOrCreateType(src_type->type);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700232 if (!MergeType(context_, src, dst_type, src_type.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700233 error = true;
234 continue;
235 }
236
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700237 for (auto& src_entry : src_type->entries) {
238 std::string entry_name = src_entry->name;
239 if (mangle_package) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700240 entry_name = NameMangler::MangleEntry(src_package->name, src_entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241 }
242
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700243 ResourceEntry* dst_entry;
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700244 if (allow_new_resources || src_entry->symbol_status.allow_new) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700245 dst_entry = dst_type->FindOrCreateEntry(entry_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700246 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700247 dst_entry = dst_type->FindEntry(entry_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700248 }
249
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700250 const ResourceNameRef res_name(src_package->name, src_type->type, src_entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700251
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700252 if (!dst_entry) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700253 context_->GetDiagnostics()->Error(DiagMessage(src)
254 << "resource " << res_name
255 << " does not override an existing resource");
256 context_->GetDiagnostics()->Note(DiagMessage(src) << "define an <add-resource> tag or use "
257 << "--auto-add-overlay");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700258 error = true;
259 continue;
260 }
261
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700262 if (!MergeEntry(context_, src, dst_entry, src_entry.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700263 error = true;
264 continue;
265 }
266
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700267 for (auto& src_config_value : src_entry->values) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700268 using CollisionResult = ResourceTable::CollisionResult;
269
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700270 ResourceConfigValue* dst_config_value = dst_entry->FindValue(
271 src_config_value->config, src_config_value->product);
272 if (dst_config_value) {
273 CollisionResult collision_result =
274 MergeConfigValue(context_, res_name, overlay, dst_config_value,
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700275 src_config_value.get(), &master_table_->string_pool);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700276 if (collision_result == CollisionResult::kConflict) {
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700277 error = true;
278 continue;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700279 } else if (collision_result == CollisionResult::kKeepOriginal) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700280 continue;
281 }
282 } else {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700283 dst_config_value =
284 dst_entry->FindOrCreateValue(src_config_value->config, src_config_value->product);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700285 }
286
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700287 // Continue if we're taking the new resource.
288
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700289 if (FileReference* f = ValueCast<FileReference>(src_config_value->value.get())) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700290 std::unique_ptr<FileReference> new_file_ref;
291 if (mangle_package) {
292 new_file_ref = CloneAndMangleFile(src_package->name, *f);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700293 } else {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700294 new_file_ref = std::unique_ptr<FileReference>(f->Clone(&master_table_->string_pool));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700295 }
296
297 if (callback) {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700298 if (!callback(res_name, src_config_value->config, new_file_ref.get(), f)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700299 error = true;
300 continue;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800301 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700303 dst_config_value->value = std::move(new_file_ref);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800304
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700305 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700306 dst_config_value->value = std::unique_ptr<Value>(
307 src_config_value->value->Clone(&master_table_->string_pool));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700308 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700309 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700310 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700311 }
312 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700313}
314
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700315std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile(
316 const std::string& package, const FileReference& file_ref) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700317 StringPiece prefix, entry, suffix;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700318 if (util::ExtractResFilePathParts(*file_ref.path, &prefix, &entry, &suffix)) {
Adam Lesinskid5083f62017-01-16 15:07:21 -0800319 std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string());
320 std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700321 std::unique_ptr<FileReference> new_file_ref =
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700322 util::make_unique<FileReference>(master_table_->string_pool.MakeRef(newPath));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700323 new_file_ref->SetComment(file_ref.GetComment());
324 new_file_ref->SetSource(file_ref.GetSource());
325 return new_file_ref;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700326 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700327 return std::unique_ptr<FileReference>(file_ref.Clone(&master_table_->string_pool));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700328}
329
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700330bool TableMerger::MergeFileImpl(const ResourceFile& file_desc, io::IFile* file, bool overlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700331 ResourceTable table;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700332 std::string path = ResourceUtils::BuildResourceFileName(file_desc);
333 std::unique_ptr<FileReference> file_ref =
334 util::make_unique<FileReference>(table.string_pool.MakeRef(path));
335 file_ref->SetSource(file_desc.source);
336 file_ref->file = file;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800337
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700338 ResourceTablePackage* pkg = table.CreatePackage(file_desc.name.package, 0x0);
339 pkg->FindOrCreateType(file_desc.name.type)
340 ->FindOrCreateEntry(file_desc.name.entry)
341 ->FindOrCreateValue(file_desc.config, {})
342 ->value = std::move(file_ref);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800343
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700344 return DoMerge(file->GetSource(), &table, pkg, false /* mangle */,
345 overlay /* overlay */, true /* allow_new */, {});
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800346}
347
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700348bool TableMerger::MergeFile(const ResourceFile& file_desc, io::IFile* file) {
349 return MergeFileImpl(file_desc, file, false /* overlay */);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800350}
351
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700352bool TableMerger::MergeFileOverlay(const ResourceFile& file_desc,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700353 io::IFile* file) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700354 return MergeFileImpl(file_desc, file, true /* overlay */);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700355}
356
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700357} // namespace aapt