blob: 7e7b9fb869489edf97c882bcc54998d1a93759dd [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 Lesinskid5083f62017-01-16 15:07:21 -080027using android::StringPiece;
28
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 Lesinskice5e56e2016-10-21 17:56:45 -070035 master_package_ = master_table_->CreatePackage(
36 context_->GetCompilationPackage(), context_->GetPackageId());
37 CHECK(master_package_ != nullptr) << "package name or ID already taken";
Adam Lesinski1ab598f2015-08-14 14:26:04 -070038}
39
Adam Lesinskice5e56e2016-10-21 17:56:45 -070040bool TableMerger::Merge(const Source& src, ResourceTable* table,
Adam Lesinski64587af2016-02-18 18:33:06 -080041 io::IFileCollection* collection) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070042 return MergeImpl(src, table, collection, false /* overlay */,
Adam Lesinskicacb28f2016-10-19 12:18:14 -070043 true /* allow new */);
Adam Lesinski64587af2016-02-18 18:33:06 -080044}
45
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046bool TableMerger::MergeOverlay(const Source& src, ResourceTable* table,
Adam Lesinski64587af2016-02-18 18:33:06 -080047 io::IFileCollection* collection) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070048 return MergeImpl(src, table, collection, true /* overlay */,
49 options_.auto_add_overlay);
Adam Lesinski64587af2016-02-18 18:33:06 -080050}
51
Adam Lesinski83f22552015-11-07 11:51:23 -080052/**
53 * This will merge packages with the same package name (or no package name).
54 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -070055bool TableMerger::MergeImpl(const Source& src, ResourceTable* table,
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 io::IFileCollection* collection, bool overlay,
Adam Lesinskice5e56e2016-10-21 17:56:45 -070057 bool allow_new) {
58 const uint8_t desired_package_id = context_->GetPackageId();
Adam Lesinski085f4952016-08-30 14:25:51 -070059
Adam Lesinskicacb28f2016-10-19 12:18:14 -070060 bool error = false;
61 for (auto& package : table->packages) {
62 // Warn of packages with an unrelated ID.
63 const Maybe<ResourceId>& id = package->id;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070064 if (id && id.value() != 0x0 && id.value() != desired_package_id) {
65 context_->GetDiagnostics()->Warn(DiagMessage(src) << "ignoring package "
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 << package->name);
67 continue;
Adam Lesinski83f22552015-11-07 11:51:23 -080068 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070069
70 // Only merge an empty package or the package we're building.
71 // Other packages may exist, which likely contain attribute definitions.
72 // This is because at compile time it is unknown if the attributes are
73 // simply
74 // uses of the attribute or definitions.
75 if (package->name.empty() ||
Adam Lesinskice5e56e2016-10-21 17:56:45 -070076 context_->GetCompilationPackage() == package->name) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077 FileMergeCallback callback;
78 if (collection) {
79 callback = [&](const ResourceNameRef& name,
Adam Lesinskice5e56e2016-10-21 17:56:45 -070080 const ConfigDescription& config, FileReference* new_file,
81 FileReference* old_file) -> bool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 // The old file's path points inside the APK, so we can use it as is.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070083 io::IFile* f = collection->FindFile(*old_file->path);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070084 if (!f) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070085 context_->GetDiagnostics()->Error(DiagMessage(src)
86 << "file '" << *old_file->path
Adam Lesinskicacb28f2016-10-19 12:18:14 -070087 << "' not found");
88 return false;
89 }
90
Adam Lesinskice5e56e2016-10-21 17:56:45 -070091 new_file->file = f;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 return true;
93 };
94 }
95
96 // Merge here. Once the entries are merged and mangled, any references to
97 // them are still valid. This is because un-mangled references are
98 // mangled, then looked up at resolution time.
99 // Also, when linking, we convert references with no package name to use
100 // the compilation package name.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700101 error |= !DoMerge(src, table, package.get(), false /* mangle */, overlay,
102 allow_new, callback);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103 }
104 }
105 return !error;
Adam Lesinski83f22552015-11-07 11:51:23 -0800106}
107
108/**
109 * This will merge and mangle resources from a static library.
110 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700111bool TableMerger::MergeAndMangle(const Source& src,
112 const StringPiece& package_name,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113 ResourceTable* table,
114 io::IFileCollection* collection) {
115 bool error = false;
116 for (auto& package : table->packages) {
117 // Warn of packages with an unrelated ID.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700118 if (package_name != package->name) {
119 context_->GetDiagnostics()->Warn(DiagMessage(src) << "ignoring package "
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700120 << package->name);
121 continue;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700122 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700123
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700124 bool mangle = package_name != context_->GetCompilationPackage();
125 merged_packages_.insert(package->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700126
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700127 auto callback = [&](
128 const ResourceNameRef& name, const ConfigDescription& config,
129 FileReference* new_file, FileReference* old_file) -> bool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700130 // The old file's path points inside the APK, so we can use it as is.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700131 io::IFile* f = collection->FindFile(*old_file->path);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700132 if (!f) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700133 context_->GetDiagnostics()->Error(
134 DiagMessage(src) << "file '" << *old_file->path << "' not found");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700135 return false;
136 }
137
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700138 new_file->file = f;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 return true;
140 };
141
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700142 error |= !DoMerge(src, table, package.get(), mangle, false /* overlay */,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700143 true /* allow new */, callback);
144 }
145 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700146}
147
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700148static bool MergeType(IAaptContext* context, const Source& src,
149 ResourceTableType* dst_type,
150 ResourceTableType* src_type) {
151 if (dst_type->symbol_status.state < src_type->symbol_status.state) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700152 // The incoming type's visibility is stronger, so we should override
153 // the visibility.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700154 if (src_type->symbol_status.state == SymbolState::kPublic) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 // Only copy the ID if the source is public, or else the ID is
156 // meaningless.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700157 dst_type->id = src_type->id;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700158 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700159 dst_type->symbol_status = std::move(src_type->symbol_status);
160 } else if (dst_type->symbol_status.state == SymbolState::kPublic &&
161 src_type->symbol_status.state == SymbolState::kPublic &&
162 dst_type->id && src_type->id &&
163 dst_type->id.value() != src_type->id.value()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700164 // Both types are public and have different IDs.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700165 context->GetDiagnostics()->Error(DiagMessage(src)
166 << "cannot merge type '" << src_type->type
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167 << "': conflicting public IDs");
168 return false;
169 }
170 return true;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700171}
172
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700173static bool MergeEntry(IAaptContext* context, const Source& src,
174 ResourceEntry* dst_entry, ResourceEntry* src_entry) {
175 if (dst_entry->symbol_status.state < src_entry->symbol_status.state) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700176 // The incoming type's visibility is stronger, so we should override
177 // the visibility.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700178 if (src_entry->symbol_status.state == SymbolState::kPublic) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 // Only copy the ID if the source is public, or else the ID is
180 // meaningless.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700181 dst_entry->id = src_entry->id;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700182 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700183 dst_entry->symbol_status = std::move(src_entry->symbol_status);
184 } else if (src_entry->symbol_status.state == SymbolState::kPublic &&
185 dst_entry->symbol_status.state == SymbolState::kPublic &&
186 dst_entry->id && src_entry->id &&
187 dst_entry->id.value() != src_entry->id.value()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700188 // Both entries are public and have different IDs.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700189 context->GetDiagnostics()->Error(
190 DiagMessage(src) << "cannot merge entry '" << src_entry->name
191 << "': conflicting public IDs");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700192 return false;
193 }
194 return true;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700195}
196
197/**
198 * Modified CollisionResolver which will merge Styleables. Used with overlays.
199 *
200 * Styleables are not actual resources, but they are treated as such during the
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700201 * compilation phase. Styleables don't simply overlay each other, their
202 * definitions merge
203 * and accumulate. If both values are Styleables, we just merge them into the
204 * existing value.
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700205 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700206static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700207 Value* incoming) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700208 if (Styleable* existing_styleable = ValueCast<Styleable>(existing)) {
209 if (Styleable* incoming_styleable = ValueCast<Styleable>(incoming)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700210 // Styleables get merged.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700211 existing_styleable->MergeWith(incoming_styleable);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700212 return ResourceTable::CollisionResult::kKeepOriginal;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700213 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700214 }
215 // Delegate to the default handler.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700216 return ResourceTable::ResolveValueCollision(existing, incoming);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700217}
218
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700219static ResourceTable::CollisionResult MergeConfigValue(
220 IAaptContext* context, const ResourceNameRef& res_name, const bool overlay,
221 ResourceConfigValue* dst_config_value,
222 ResourceConfigValue* src_config_value) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700223 using CollisionResult = ResourceTable::CollisionResult;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700224
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700225 Value* dst_value = dst_config_value->value.get();
226 Value* src_value = src_config_value->value.get();
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700227
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700228 CollisionResult collision_result;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700229 if (overlay) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700230 collision_result = ResolveMergeCollision(dst_value, src_value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700231 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700232 collision_result =
233 ResourceTable::ResolveValueCollision(dst_value, src_value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700234 }
235
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700236 if (collision_result == CollisionResult::kConflict) {
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700237 if (overlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700238 return CollisionResult::kTakeNew;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700239 }
240
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241 // Error!
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700242 context->GetDiagnostics()->Error(
243 DiagMessage(src_value->GetSource())
244 << "resource '" << res_name << "' has a conflicting value for "
245 << "configuration (" << src_config_value->config << ")");
246 context->GetDiagnostics()->Note(DiagMessage(dst_value->GetSource())
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700247 << "originally defined here");
248 return CollisionResult::kConflict;
249 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700250 return collision_result;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700251}
252
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700253bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table,
254 ResourceTablePackage* src_package,
255 const bool mangle_package, const bool overlay,
256 const bool allow_new_resources,
Chih-Hung Hsieh9b8528f2016-08-10 14:15:30 -0700257 const FileMergeCallback& callback) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700258 bool error = false;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700259
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700260 for (auto& src_type : src_package->types) {
261 ResourceTableType* dst_type =
262 master_package_->FindOrCreateType(src_type->type);
263 if (!MergeType(context_, src, dst_type, src_type.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700264 error = true;
265 continue;
266 }
267
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700268 for (auto& src_entry : src_type->entries) {
269 std::string entry_name = src_entry->name;
270 if (mangle_package) {
271 entry_name =
272 NameMangler::MangleEntry(src_package->name, src_entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700273 }
274
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700275 ResourceEntry* dst_entry;
276 if (allow_new_resources) {
277 dst_entry = dst_type->FindOrCreateEntry(entry_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700278 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700279 dst_entry = dst_type->FindEntry(entry_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700280 }
281
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700282 const ResourceNameRef res_name(src_package->name, src_type->type,
283 src_entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700284
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700285 if (!dst_entry) {
286 context_->GetDiagnostics()->Error(
287 DiagMessage(src) << "resource " << res_name
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700288 << " does not override an existing resource");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700289 context_->GetDiagnostics()->Note(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700290 DiagMessage(src) << "define an <add-resource> tag or use "
291 << "--auto-add-overlay");
292 error = true;
293 continue;
294 }
295
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700296 if (!MergeEntry(context_, src, dst_entry, src_entry.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700297 error = true;
298 continue;
299 }
300
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700301 for (auto& src_config_value : src_entry->values) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302 using CollisionResult = ResourceTable::CollisionResult;
303
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700304 ResourceConfigValue* dst_config_value = dst_entry->FindValue(
305 src_config_value->config, src_config_value->product);
306 if (dst_config_value) {
307 CollisionResult collision_result =
308 MergeConfigValue(context_, res_name, overlay, dst_config_value,
309 src_config_value.get());
310 if (collision_result == CollisionResult::kConflict) {
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700311 error = true;
312 continue;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700313 } else if (collision_result == CollisionResult::kKeepOriginal) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700314 continue;
315 }
316 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700317 dst_config_value = dst_entry->FindOrCreateValue(
318 src_config_value->config, src_config_value->product);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700319 }
320
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700321 // Continue if we're taking the new resource.
322
323 if (FileReference* f =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700324 ValueCast<FileReference>(src_config_value->value.get())) {
325 std::unique_ptr<FileReference> new_file_ref;
326 if (mangle_package) {
327 new_file_ref = CloneAndMangleFile(src_package->name, *f);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700328 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700329 new_file_ref = std::unique_ptr<FileReference>(
330 f->Clone(&master_table_->string_pool));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700331 }
332
333 if (callback) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700334 if (!callback(res_name, src_config_value->config,
335 new_file_ref.get(), f)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700336 error = true;
337 continue;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800338 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700339 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700340 dst_config_value->value = std::move(new_file_ref);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800341
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700342 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700343 dst_config_value->value = std::unique_ptr<Value>(
344 src_config_value->value->Clone(&master_table_->string_pool));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700345 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700346 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700347 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700348 }
349 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700350}
351
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700352std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile(
353 const std::string& package, const FileReference& file_ref) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700354 StringPiece prefix, entry, suffix;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700355 if (util::ExtractResFilePathParts(*file_ref.path, &prefix, &entry, &suffix)) {
Adam Lesinskid5083f62017-01-16 15:07:21 -0800356 std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string());
357 std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700358 std::unique_ptr<FileReference> new_file_ref =
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700359 util::make_unique<FileReference>(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700360 master_table_->string_pool.MakeRef(newPath));
361 new_file_ref->SetComment(file_ref.GetComment());
362 new_file_ref->SetSource(file_ref.GetSource());
363 return new_file_ref;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700364 }
365 return std::unique_ptr<FileReference>(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700366 file_ref.Clone(&master_table_->string_pool));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700367}
368
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700369bool TableMerger::MergeFileImpl(const ResourceFile& file_desc, io::IFile* file,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700370 bool overlay) {
371 ResourceTable table;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700372 std::string path = ResourceUtils::BuildResourceFileName(file_desc);
373 std::unique_ptr<FileReference> file_ref =
374 util::make_unique<FileReference>(table.string_pool.MakeRef(path));
375 file_ref->SetSource(file_desc.source);
376 file_ref->file = file;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800377
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700378 ResourceTablePackage* pkg = table.CreatePackage(file_desc.name.package, 0x0);
379 pkg->FindOrCreateType(file_desc.name.type)
380 ->FindOrCreateEntry(file_desc.name.entry)
381 ->FindOrCreateValue(file_desc.config, {})
382 ->value = std::move(file_ref);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800383
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700384 return DoMerge(file->GetSource(), &table, pkg, false /* mangle */,
385 overlay /* overlay */, true /* allow_new */, {});
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800386}
387
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700388bool TableMerger::MergeFile(const ResourceFile& file_desc, io::IFile* file) {
389 return MergeFileImpl(file_desc, file, false /* overlay */);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800390}
391
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700392bool TableMerger::MergeFileOverlay(const ResourceFile& file_desc,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700393 io::IFile* file) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700394 return MergeFileImpl(file_desc, file, true /* overlay */);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700395}
396
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700397} // namespace aapt