blob: cc9fed55435068e16fc60c0b96a53e7ab827269b [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 Lesinski8780eb62017-10-31 17:44:39 -070040bool TableMerger::Merge(const Source& src, ResourceTable* table, bool overlay) {
Adam Lesinski00451162017-10-03 07:44:08 -070041 // We allow adding new resources if this is not an overlay, or if the options allow overlays
42 // to add new resources.
Adam Lesinski8780eb62017-10-31 17:44:39 -070043 return MergeImpl(src, table, overlay, options_.auto_add_overlay || !overlay /*allow_new*/);
Adam Lesinski64587af2016-02-18 18:33:06 -080044}
45
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070046// This will merge packages with the same package name (or no package name).
Adam Lesinski8780eb62017-10-31 17:44:39 -070047bool TableMerger::MergeImpl(const Source& src, ResourceTable* table, bool overlay, bool allow_new) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070048 bool error = false;
49 for (auto& package : table->packages) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070050 // Only merge an empty package or the package we're building.
51 // Other packages may exist, which likely contain attribute definitions.
52 // This is because at compile time it is unknown if the attributes are
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -080053 // simply uses of the attribute or definitions.
54 if (package->name.empty() || context_->GetCompilationPackage() == package->name) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070055 // Merge here. Once the entries are merged and mangled, any references to them are still
56 // valid. This is because un-mangled references are mangled, then looked up at resolution
57 // time. Also, when linking, we convert references with no package name to use the compilation
58 // package name.
Adam Lesinski8780eb62017-10-31 17:44:39 -070059 error |= !DoMerge(src, table, package.get(), false /*mangle*/, overlay, allow_new);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070060 }
61 }
62 return !error;
Adam Lesinski83f22552015-11-07 11:51:23 -080063}
64
Adam Lesinski8780eb62017-10-31 17:44:39 -070065// This will merge and mangle resources from a static library. It is assumed that all FileReferences
66// have correctly set their io::IFile*.
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070067bool TableMerger::MergeAndMangle(const Source& src, const StringPiece& package_name,
Adam Lesinski8780eb62017-10-31 17:44:39 -070068 ResourceTable* table) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070069 bool error = false;
70 for (auto& package : table->packages) {
71 // Warn of packages with an unrelated ID.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070072 if (package_name != package->name) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070073 context_->GetDiagnostics()->Warn(DiagMessage(src) << "ignoring package " << package->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070074 continue;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070075 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070076
Adam Lesinskice5e56e2016-10-21 17:56:45 -070077 bool mangle = package_name != context_->GetCompilationPackage();
78 merged_packages_.insert(package->name);
Adam Lesinski8780eb62017-10-31 17:44:39 -070079 error |= !DoMerge(src, table, package.get(), mangle, false /*overlay*/, true /*allow_new*/);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070080 }
81 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070082}
83
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070084static bool MergeType(IAaptContext* context, const Source& src, ResourceTableType* dst_type,
Adam Lesinskice5e56e2016-10-21 17:56:45 -070085 ResourceTableType* src_type) {
Adam Lesinski71be7052017-12-12 16:48:07 -080086 if (src_type->visibility_level > dst_type->visibility_level) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070087 // The incoming type's visibility is stronger, so we should override the visibility.
Adam Lesinski71be7052017-12-12 16:48:07 -080088 if (src_type->visibility_level == Visibility::Level::kPublic) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070089 // Only copy the ID if the source is public, or else the ID is meaningless.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070090 dst_type->id = src_type->id;
Adam Lesinski5c3464c2016-08-24 16:03:48 -070091 }
Adam Lesinski71be7052017-12-12 16:48:07 -080092 dst_type->visibility_level = src_type->visibility_level;
93 } else if (dst_type->visibility_level == Visibility::Level::kPublic &&
94 src_type->visibility_level == Visibility::Level::kPublic && dst_type->id &&
95 src_type->id && dst_type->id.value() != src_type->id.value()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070096 // Both types are public and have different IDs.
Adam Lesinski71be7052017-12-12 16:48:07 -080097 context->GetDiagnostics()->Error(DiagMessage(src) << "cannot merge type '" << src_type->type
98 << "': conflicting public IDs");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070099 return false;
100 }
101 return true;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700102}
103
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700104static bool MergeEntry(IAaptContext* context, const Source& src,
Izabela Orlowskad51efe82018-04-24 18:18:29 +0100105 ResourceEntry* dst_entry, ResourceEntry* src_entry,
106 bool strict_visibility) {
107 if (strict_visibility
108 && dst_entry->visibility.level != Visibility::Level::kUndefined
109 && src_entry->visibility.level != dst_entry->visibility.level) {
110 context->GetDiagnostics()->Error(
111 DiagMessage(src) << "cannot merge resource '" << dst_entry->name << "' with conflicting visibilities: "
112 << "public and private");
113 return false;
114 }
115
Adam Lesinski71be7052017-12-12 16:48:07 -0800116 // Copy over the strongest visibility.
117 if (src_entry->visibility.level > dst_entry->visibility.level) {
118 // Only copy the ID if the source is public, or else the ID is meaningless.
119 if (src_entry->visibility.level == Visibility::Level::kPublic) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700120 dst_entry->id = src_entry->id;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700121 }
Adam Lesinski71be7052017-12-12 16:48:07 -0800122 dst_entry->visibility = std::move(src_entry->visibility);
123 } else if (src_entry->visibility.level == Visibility::Level::kPublic &&
124 dst_entry->visibility.level == Visibility::Level::kPublic && dst_entry->id &&
125 src_entry->id && src_entry->id != dst_entry->id) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700126 // Both entries are public and have different IDs.
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700127 context->GetDiagnostics()->Error(DiagMessage(src) << "cannot merge entry '" << src_entry->name
128 << "': conflicting public IDs");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700129 return false;
130 }
Adam Lesinski71be7052017-12-12 16:48:07 -0800131
132 // Copy over the rest of the properties, if needed.
133 if (src_entry->allow_new) {
134 dst_entry->allow_new = std::move(src_entry->allow_new);
135 }
136
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800137 if (src_entry->overlayable_item) {
138 if (dst_entry->overlayable_item) {
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800139 // Do not allow a resource with an overlayable declaration to have that overlayable
140 // declaration redefined
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800141 context->GetDiagnostics()->Error(DiagMessage(src_entry->overlayable_item.value().source)
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800142 << "duplicate overlayable declaration for resource '"
143 << src_entry->name << "'");
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800144 context->GetDiagnostics()->Error(DiagMessage(dst_entry->overlayable_item.value().source)
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800145 << "previous declaration here");
146 return false;
147 } else {
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800148 dst_entry->overlayable_item = std::move(src_entry->overlayable_item);
Adam Lesinski71be7052017-12-12 16:48:07 -0800149 }
Adam Lesinski71be7052017-12-12 16:48:07 -0800150 }
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700151
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700152 return true;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700153}
154
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700155// Modified CollisionResolver which will merge Styleables and Styles. Used with overlays.
156//
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700157// Styleables are not actual resources, but they are treated as such during the compilation phase.
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700158//
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700159// Styleables and Styles don't simply overlay each other, their definitions merge and accumulate.
160// If both values are Styleables/Styles, we just merge them into the existing value.
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700161static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, Value* incoming,
162 StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 if (Styleable* existing_styleable = ValueCast<Styleable>(existing)) {
164 if (Styleable* incoming_styleable = ValueCast<Styleable>(incoming)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165 // Styleables get merged.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700166 existing_styleable->MergeWith(incoming_styleable);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167 return ResourceTable::CollisionResult::kKeepOriginal;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700168 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700169 } else if (Style* existing_style = ValueCast<Style>(existing)) {
170 if (Style* incoming_style = ValueCast<Style>(incoming)) {
171 // Styles get merged.
172 existing_style->MergeWith(incoming_style, pool);
173 return ResourceTable::CollisionResult::kKeepOriginal;
174 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700175 }
176 // Delegate to the default handler.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700177 return ResourceTable::ResolveValueCollision(existing, incoming);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700178}
179
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700180static ResourceTable::CollisionResult MergeConfigValue(IAaptContext* context,
181 const ResourceNameRef& res_name,
Adam Lesinski8780eb62017-10-31 17:44:39 -0700182 bool overlay,
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700183 ResourceConfigValue* dst_config_value,
184 ResourceConfigValue* src_config_value,
185 StringPool* pool) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700186 using CollisionResult = ResourceTable::CollisionResult;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700187
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700188 Value* dst_value = dst_config_value->value.get();
189 Value* src_value = src_config_value->value.get();
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700190
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700191 CollisionResult collision_result;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700192 if (overlay) {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700193 collision_result = ResolveMergeCollision(dst_value, src_value, pool);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700194 } else {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700195 collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700196 }
197
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700198 if (collision_result == CollisionResult::kConflict) {
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700199 if (overlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700200 return CollisionResult::kTakeNew;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700201 }
202
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700203 // Error!
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700204 context->GetDiagnostics()->Error(DiagMessage(src_value->GetSource())
205 << "resource '" << res_name << "' has a conflicting value for "
206 << "configuration (" << src_config_value->config << ")");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700207 context->GetDiagnostics()->Note(DiagMessage(dst_value->GetSource())
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700208 << "originally defined here");
209 return CollisionResult::kConflict;
210 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700211 return collision_result;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700212}
213
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700214bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table,
Adam Lesinski8780eb62017-10-31 17:44:39 -0700215 ResourceTablePackage* src_package, bool mangle_package, bool overlay,
216 bool allow_new_resources) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700217 bool error = false;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700218
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700219 for (auto& src_type : src_package->types) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700220 ResourceTableType* dst_type = master_package_->FindOrCreateType(src_type->type);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700221 if (!MergeType(context_, src, dst_type, src_type.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700222 error = true;
223 continue;
224 }
225
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700226 for (auto& src_entry : src_type->entries) {
227 std::string entry_name = src_entry->name;
228 if (mangle_package) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700229 entry_name = NameMangler::MangleEntry(src_package->name, src_entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700230 }
231
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700232 ResourceEntry* dst_entry;
Adam Lesinski71be7052017-12-12 16:48:07 -0800233 if (allow_new_resources || src_entry->allow_new) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700234 dst_entry = dst_type->FindOrCreateEntry(entry_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700235 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700236 dst_entry = dst_type->FindEntry(entry_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700237 }
238
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700239 const ResourceNameRef res_name(src_package->name, src_type->type, src_entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700240
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700241 if (!dst_entry) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700242 context_->GetDiagnostics()->Error(DiagMessage(src)
243 << "resource " << res_name
244 << " does not override an existing resource");
245 context_->GetDiagnostics()->Note(DiagMessage(src) << "define an <add-resource> tag or use "
246 << "--auto-add-overlay");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700247 error = true;
248 continue;
249 }
250
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700251 if (!MergeEntry(context_, src, dst_entry, src_entry.get(), options_.strict_visibility)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700252 error = true;
253 continue;
254 }
255
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700256 for (auto& src_config_value : src_entry->values) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700257 using CollisionResult = ResourceTable::CollisionResult;
258
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700259 ResourceConfigValue* dst_config_value = dst_entry->FindValue(
260 src_config_value->config, src_config_value->product);
261 if (dst_config_value) {
262 CollisionResult collision_result =
263 MergeConfigValue(context_, res_name, overlay, dst_config_value,
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700264 src_config_value.get(), &master_table_->string_pool);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700265 if (collision_result == CollisionResult::kConflict) {
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700266 error = true;
267 continue;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700268 } else if (collision_result == CollisionResult::kKeepOriginal) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700269 continue;
270 }
271 } else {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700272 dst_config_value =
273 dst_entry->FindOrCreateValue(src_config_value->config, src_config_value->product);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700274 }
275
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700276 // Continue if we're taking the new resource.
277
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700278 if (FileReference* f = ValueCast<FileReference>(src_config_value->value.get())) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700279 std::unique_ptr<FileReference> new_file_ref;
280 if (mangle_package) {
281 new_file_ref = CloneAndMangleFile(src_package->name, *f);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700282 } else {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700283 new_file_ref = std::unique_ptr<FileReference>(f->Clone(&master_table_->string_pool));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700284 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700285 dst_config_value->value = std::move(new_file_ref);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800286
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700287 } else {
Ryan Mitchella9e31602018-06-28 16:41:38 -0700288 Maybe<std::string> original_comment = (dst_config_value->value)
289 ? dst_config_value->value->GetComment() : Maybe<std::string>();
290
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700291 dst_config_value->value = std::unique_ptr<Value>(
292 src_config_value->value->Clone(&master_table_->string_pool));
Ryan Mitchella9e31602018-06-28 16:41:38 -0700293
294 // Keep the comment from the original resource and ignore all comments from overlaying
295 // resources
296 if (overlay && original_comment) {
297 dst_config_value->value->SetComment(original_comment.value());
298 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700299 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700300 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700301 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302 }
303 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700304}
305
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700306std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile(
307 const std::string& package, const FileReference& file_ref) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700308 StringPiece prefix, entry, suffix;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700309 if (util::ExtractResFilePathParts(*file_ref.path, &prefix, &entry, &suffix)) {
Adam Lesinskid5083f62017-01-16 15:07:21 -0800310 std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string());
311 std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700312 std::unique_ptr<FileReference> new_file_ref =
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700313 util::make_unique<FileReference>(master_table_->string_pool.MakeRef(newPath));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700314 new_file_ref->SetComment(file_ref.GetComment());
315 new_file_ref->SetSource(file_ref.GetSource());
Adam Lesinski00451162017-10-03 07:44:08 -0700316 new_file_ref->type = file_ref.type;
317 new_file_ref->file = file_ref.file;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700318 return new_file_ref;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700319 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700320 return std::unique_ptr<FileReference>(file_ref.Clone(&master_table_->string_pool));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700321}
322
Adam Lesinski00451162017-10-03 07:44:08 -0700323bool TableMerger::MergeFile(const ResourceFile& file_desc, bool overlay, io::IFile* file) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700324 ResourceTable table;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700325 std::string path = ResourceUtils::BuildResourceFileName(file_desc);
326 std::unique_ptr<FileReference> file_ref =
327 util::make_unique<FileReference>(table.string_pool.MakeRef(path));
328 file_ref->SetSource(file_desc.source);
Adam Lesinski00451162017-10-03 07:44:08 -0700329 file_ref->type = file_desc.type;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330 file_ref->file = file;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800331
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700332 ResourceTablePackage* pkg = table.CreatePackage(file_desc.name.package, 0x0);
333 pkg->FindOrCreateType(file_desc.name.type)
334 ->FindOrCreateEntry(file_desc.name.entry)
335 ->FindOrCreateValue(file_desc.config, {})
336 ->value = std::move(file_ref);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800337
Adam Lesinski8780eb62017-10-31 17:44:39 -0700338 return DoMerge(file->GetSource(), &table, pkg, false /*mangle*/, overlay /*overlay*/,
339 true /*allow_new*/);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700340}
341
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700342} // namespace aapt