blob: 37a039e9528f6aa0a4cb2f387dc82284b6fea96e [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"
Fabien Sanglard2d34e762019-02-21 15:13:29 -080024#include "trace/TraceBuffer.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070025#include "ValueVisitor.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070026#include "util/Util.h"
27
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070028using ::android::StringPiece;
Adam Lesinskid5083f62017-01-16 15:07:21 -080029
Adam Lesinski1ab598f2015-08-14 14:26:04 -070030namespace aapt {
31
Adam Lesinskice5e56e2016-10-21 17:56:45 -070032TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table,
Adam Lesinskicacb28f2016-10-19 12:18:14 -070033 const TableMergerOptions& options)
Ryan Mitchell4ea90752020-07-31 08:21:43 -070034 : context_(context), main_table_(out_table), options_(options) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070035 // Create the desired package that all tables will be merged into.
Ryan Mitchell9634efb2021-03-19 14:53:17 -070036 main_package_ = main_table_->FindOrCreatePackage(context_->GetCompilationPackage());
Ryan Mitchell4ea90752020-07-31 08:21:43 -070037 CHECK(main_package_ != nullptr) << "package name or ID already taken";
Adam Lesinski1ab598f2015-08-14 14:26:04 -070038}
39
Jeremy Meyer56f36e82022-05-20 20:35:42 +000040bool TableMerger::Merge(const android::Source& src, ResourceTable* table, bool overlay) {
Fabien Sanglard2d34e762019-02-21 15:13:29 -080041 TRACE_CALL();
Adam Lesinski00451162017-10-03 07:44:08 -070042 // We allow adding new resources if this is not an overlay, or if the options allow overlays
43 // to add new resources.
Adam Lesinski8780eb62017-10-31 17:44:39 -070044 return MergeImpl(src, table, overlay, options_.auto_add_overlay || !overlay /*allow_new*/);
Adam Lesinski64587af2016-02-18 18:33:06 -080045}
46
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070047// This will merge packages with the same package name (or no package name).
Jeremy Meyer56f36e82022-05-20 20:35:42 +000048bool TableMerger::MergeImpl(const android::Source& src, ResourceTable* table, bool overlay,
49 bool allow_new) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070050 bool error = false;
51 for (auto& package : table->packages) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070052 // Only merge an empty package or the package we're building.
53 // Other packages may exist, which likely contain attribute definitions.
54 // This is because at compile time it is unknown if the attributes are
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -080055 // simply uses of the attribute or definitions.
56 if (package->name.empty() || context_->GetCompilationPackage() == package->name) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070057 // Merge here. Once the entries are merged and mangled, any references to them are still
58 // valid. This is because un-mangled references are mangled, then looked up at resolution
59 // time. Also, when linking, we convert references with no package name to use the compilation
60 // package name.
Fabien Sanglard2369f542019-03-19 08:32:46 -070061 error |= !DoMerge(src, package.get(), false /*mangle*/, overlay, allow_new);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070062 }
63 }
64 return !error;
Adam Lesinski83f22552015-11-07 11:51:23 -080065}
66
Adam Lesinski8780eb62017-10-31 17:44:39 -070067// This will merge and mangle resources from a static library. It is assumed that all FileReferences
68// have correctly set their io::IFile*.
Yurii Zubrytskyia5775142022-11-02 17:49:49 -070069bool TableMerger::MergeAndMangle(const android::Source& src, StringPiece package_name,
Adam Lesinski8780eb62017-10-31 17:44:39 -070070 ResourceTable* table) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070071 bool error = false;
72 for (auto& package : table->packages) {
73 // Warn of packages with an unrelated ID.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074 if (package_name != package->name) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +000075 context_->GetDiagnostics()->Warn(android::DiagMessage(src)
76 << "ignoring package " << package->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077 continue;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070078 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070079
Adam Lesinskice5e56e2016-10-21 17:56:45 -070080 bool mangle = package_name != context_->GetCompilationPackage();
81 merged_packages_.insert(package->name);
Fabien Sanglard2369f542019-03-19 08:32:46 -070082 error |= !DoMerge(src, package.get(), mangle, false /*overlay*/, true /*allow_new*/);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070083 }
84 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070085}
86
Jeremy Meyer56f36e82022-05-20 20:35:42 +000087static bool MergeType(IAaptContext* context, const android::Source& src,
88 ResourceTableType* dst_type, ResourceTableType* src_type) {
Ryan Mitchell9634efb2021-03-19 14:53:17 -070089 if (src_type->visibility_level >= dst_type->visibility_level) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070090 // The incoming type's visibility is stronger, so we should override the visibility.
Adam Lesinski71be7052017-12-12 16:48:07 -080091 dst_type->visibility_level = src_type->visibility_level;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 }
93 return true;
Adam Lesinski5c3464c2016-08-24 16:03:48 -070094}
95
Jeremy Meyer56f36e82022-05-20 20:35:42 +000096static bool MergeEntry(IAaptContext* context, const android::Source& src, ResourceEntry* dst_entry,
97 ResourceEntry* src_entry, bool strict_visibility) {
Izabela Orlowskad51efe82018-04-24 18:18:29 +010098 if (strict_visibility
99 && dst_entry->visibility.level != Visibility::Level::kUndefined
100 && src_entry->visibility.level != dst_entry->visibility.level) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000101 context->GetDiagnostics()->Error(android::DiagMessage(src)
102 << "cannot merge resource '" << dst_entry->name
103 << "' with conflicting visibilities: "
104 << "public and private");
Izabela Orlowskad51efe82018-04-24 18:18:29 +0100105 return false;
106 }
107
Adam Lesinski71be7052017-12-12 16:48:07 -0800108 // Copy over the strongest visibility.
109 if (src_entry->visibility.level > dst_entry->visibility.level) {
110 // Only copy the ID if the source is public, or else the ID is meaningless.
111 if (src_entry->visibility.level == Visibility::Level::kPublic) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700112 dst_entry->id = src_entry->id;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700113 }
Adam Lesinski71be7052017-12-12 16:48:07 -0800114 dst_entry->visibility = std::move(src_entry->visibility);
115 } else if (src_entry->visibility.level == Visibility::Level::kPublic &&
116 dst_entry->visibility.level == Visibility::Level::kPublic && dst_entry->id &&
117 src_entry->id && src_entry->id != dst_entry->id) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700118 // Both entries are public and have different IDs.
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000119 context->GetDiagnostics()->Error(android::DiagMessage(src)
120 << "cannot merge entry '" << src_entry->name
121 << "': conflicting public IDs");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700122 return false;
123 }
Adam Lesinski71be7052017-12-12 16:48:07 -0800124
125 // Copy over the rest of the properties, if needed.
126 if (src_entry->allow_new) {
127 dst_entry->allow_new = std::move(src_entry->allow_new);
128 }
129
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800130 if (src_entry->overlayable_item) {
131 if (dst_entry->overlayable_item) {
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700132 CHECK(src_entry->overlayable_item.value().overlayable != nullptr);
133 Overlayable* src_overlayable = src_entry->overlayable_item.value().overlayable.get();
134
135 CHECK(dst_entry->overlayable_item.value().overlayable != nullptr);
136 Overlayable* dst_overlayable = dst_entry->overlayable_item.value().overlayable.get();
137
138 if (src_overlayable->name != dst_overlayable->name
139 || src_overlayable->actor != dst_overlayable->actor
140 || src_entry->overlayable_item.value().policies !=
141 dst_entry->overlayable_item.value().policies) {
142
143 // Do not allow a resource with an overlayable declaration to have that overlayable
144 // declaration redefined.
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000145 context->GetDiagnostics()->Error(
146 android::DiagMessage(src_entry->overlayable_item.value().source)
147 << "duplicate overlayable declaration for resource '" << src_entry->name << "'");
148 context->GetDiagnostics()->Error(
149 android::DiagMessage(dst_entry->overlayable_item.value().source)
150 << "previous declaration here");
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700151 return false;
152 }
Adam Lesinski71be7052017-12-12 16:48:07 -0800153 }
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700154
155 dst_entry->overlayable_item = std::move(src_entry->overlayable_item);
Adam Lesinski71be7052017-12-12 16:48:07 -0800156 }
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700157
Ryan Mitchell2fedba92021-04-23 07:47:38 -0700158 if (src_entry->staged_id) {
159 if (dst_entry->staged_id &&
160 dst_entry->staged_id.value().id != src_entry->staged_id.value().id) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000161 context->GetDiagnostics()->Error(android::DiagMessage(src_entry->staged_id.value().source)
Ryan Mitchell2fedba92021-04-23 07:47:38 -0700162 << "conflicting staged id declaration for resource '"
163 << src_entry->name << "'");
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000164 context->GetDiagnostics()->Error(android::DiagMessage(dst_entry->staged_id.value().source)
Ryan Mitchell2fedba92021-04-23 07:47:38 -0700165 << "previous declaration here");
166 }
167 dst_entry->staged_id = std::move(src_entry->staged_id);
168 }
169
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700170 return true;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700171}
172
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700173// Modified CollisionResolver which will merge Styleables and Styles. Used with overlays.
174//
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700175// Styleables are not actual resources, but they are treated as such during the compilation phase.
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700176//
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700177// Styleables and Styles don't simply overlay each other, their definitions merge and accumulate.
178// If both values are Styleables/Styles, we just merge them into the existing value.
Donald Chai121c6e82019-06-12 12:51:57 -0700179static ResourceTable::CollisionResult ResolveMergeCollision(
180 bool override_styles_instead_of_overlaying, Value* existing, Value* incoming,
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000181 android::StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700182 if (Styleable* existing_styleable = ValueCast<Styleable>(existing)) {
183 if (Styleable* incoming_styleable = ValueCast<Styleable>(incoming)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700184 // Styleables get merged.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700185 existing_styleable->MergeWith(incoming_styleable);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700186 return ResourceTable::CollisionResult::kKeepOriginal;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700187 }
Donald Chai121c6e82019-06-12 12:51:57 -0700188 } else if (!override_styles_instead_of_overlaying) {
189 if (Style* existing_style = ValueCast<Style>(existing)) {
190 if (Style* incoming_style = ValueCast<Style>(incoming)) {
191 // Styles get merged.
192 existing_style->MergeWith(incoming_style, pool);
193 return ResourceTable::CollisionResult::kKeepOriginal;
194 }
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700195 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700196 }
197 // Delegate to the default handler.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700198 return ResourceTable::ResolveValueCollision(existing, incoming);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700199}
200
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000201static ResourceTable::CollisionResult MergeConfigValue(
202 IAaptContext* context, const ResourceNameRef& res_name, bool overlay,
203 bool override_styles_instead_of_overlaying, ResourceConfigValue* dst_config_value,
204 ResourceConfigValue* src_config_value, android::StringPool* pool) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700205 using CollisionResult = ResourceTable::CollisionResult;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700206
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700207 Value* dst_value = dst_config_value->value.get();
208 Value* src_value = src_config_value->value.get();
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700209
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700210 CollisionResult collision_result;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700211 if (overlay) {
Donald Chai121c6e82019-06-12 12:51:57 -0700212 collision_result =
213 ResolveMergeCollision(override_styles_instead_of_overlaying, dst_value, src_value, pool);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700214 } else {
Jeremy Meyerd52bd682024-08-14 11:16:58 -0700215 collision_result =
216 ResourceTable::ResolveFlagCollision(dst_value->GetFlagStatus(), src_value->GetFlagStatus());
Jeremy Meyerd7f86e52024-07-24 16:00:44 -0700217 if (collision_result == CollisionResult::kConflict) {
218 collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value);
219 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700220 }
221
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700222 if (collision_result == CollisionResult::kConflict) {
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700223 if (overlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700224 return CollisionResult::kTakeNew;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700225 }
226
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700227 // Error!
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000228 context->GetDiagnostics()->Error(android::DiagMessage(src_value->GetSource())
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700229 << "resource '" << res_name << "' has a conflicting value for "
230 << "configuration (" << src_config_value->config << ")");
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000231 context->GetDiagnostics()->Note(android::DiagMessage(dst_value->GetSource())
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700232 << "originally defined here");
233 return CollisionResult::kConflict;
234 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700235 return collision_result;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700236}
237
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000238bool TableMerger::DoMerge(const android::Source& src, ResourceTablePackage* src_package,
239 bool mangle_package, bool overlay, bool allow_new_resources) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700240 bool error = false;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700241
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700242 for (auto& src_type : src_package->types) {
Iurii Makhnof0c5ff42022-02-22 13:31:02 +0000243 ResourceTableType* dst_type = main_package_->FindOrCreateType(src_type->named_type);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700244 if (!MergeType(context_, src, dst_type, src_type.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700245 error = true;
246 continue;
247 }
248
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700249 for (auto& src_entry : src_type->entries) {
250 std::string entry_name = src_entry->name;
251 if (mangle_package) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700252 entry_name = NameMangler::MangleEntry(src_package->name, src_entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700253 }
254
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700255 ResourceEntry* dst_entry;
Adam Lesinski71be7052017-12-12 16:48:07 -0800256 if (allow_new_resources || src_entry->allow_new) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700257 dst_entry = dst_type->FindOrCreateEntry(entry_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700258 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700259 dst_entry = dst_type->FindEntry(entry_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700260 }
261
Iurii Makhnof0c5ff42022-02-22 13:31:02 +0000262 const ResourceNameRef res_name(src_package->name, src_type->named_type, src_entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700263
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700264 if (!dst_entry) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000265 context_->GetDiagnostics()->Error(android::DiagMessage(src)
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700266 << "resource " << res_name
267 << " does not override an existing resource");
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000268 context_->GetDiagnostics()->Note(android::DiagMessage(src)
269 << "define an <add-resource> tag or use "
270 << "--auto-add-overlay");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700271 error = true;
272 continue;
273 }
274
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700275 if (!MergeEntry(context_, src, dst_entry, src_entry.get(), options_.strict_visibility)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700276 error = true;
277 continue;
278 }
279
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700280 for (auto& src_config_value : src_entry->values) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700281 using CollisionResult = ResourceTable::CollisionResult;
282
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700283 ResourceConfigValue* dst_config_value = dst_entry->FindValue(
284 src_config_value->config, src_config_value->product);
285 if (dst_config_value) {
Donald Chai121c6e82019-06-12 12:51:57 -0700286 CollisionResult collision_result = MergeConfigValue(
287 context_, res_name, overlay, options_.override_styles_instead_of_overlaying,
Ryan Mitchell4ea90752020-07-31 08:21:43 -0700288 dst_config_value, src_config_value.get(), &main_table_->string_pool);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700289 if (collision_result == CollisionResult::kConflict) {
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700290 error = true;
291 continue;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700292 } else if (collision_result == CollisionResult::kKeepOriginal) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700293 continue;
294 }
295 } else {
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700296 dst_config_value =
297 dst_entry->FindOrCreateValue(src_config_value->config, src_config_value->product);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700298 }
299
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700300 // Continue if we're taking the new resource.
Ryan Mitchellefcdb952021-04-14 17:31:37 -0700301 CloningValueTransformer cloner(&main_table_->string_pool);
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700302 if (FileReference* f = ValueCast<FileReference>(src_config_value->value.get())) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700303 std::unique_ptr<FileReference> new_file_ref;
304 if (mangle_package) {
305 new_file_ref = CloneAndMangleFile(src_package->name, *f);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700306 } else {
Ryan Mitchellefcdb952021-04-14 17:31:37 -0700307 new_file_ref = std::unique_ptr<FileReference>(f->Transform(cloner));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700308 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700309 dst_config_value->value = std::move(new_file_ref);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800310
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700311 } else {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700312 auto original_comment = (dst_config_value->value)
313 ? dst_config_value->value->GetComment() : std::optional<std::string>();
Ryan Mitchella9e31602018-06-28 16:41:38 -0700314
Ryan Mitchellefcdb952021-04-14 17:31:37 -0700315 dst_config_value->value = src_config_value->value->Transform(cloner);
Ryan Mitchella9e31602018-06-28 16:41:38 -0700316
317 // Keep the comment from the original resource and ignore all comments from overlaying
318 // resources
319 if (overlay && original_comment) {
320 dst_config_value->value->SetComment(original_comment.value());
321 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700322 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700323 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700324 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700325 }
326 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700327}
328
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700329std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile(
330 const std::string& package, const FileReference& file_ref) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700331 StringPiece prefix, entry, suffix;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700332 if (util::ExtractResFilePathParts(*file_ref.path, &prefix, &entry, &suffix)) {
Yurii Zubrytskyia5775142022-11-02 17:49:49 -0700333 std::string mangled_entry = NameMangler::MangleEntry(package, entry);
334 std::string newPath = (std::string(prefix) += mangled_entry) += suffix;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700335 std::unique_ptr<FileReference> new_file_ref =
Ryan Mitchell4ea90752020-07-31 08:21:43 -0700336 util::make_unique<FileReference>(main_table_->string_pool.MakeRef(newPath));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700337 new_file_ref->SetComment(file_ref.GetComment());
338 new_file_ref->SetSource(file_ref.GetSource());
Adam Lesinski00451162017-10-03 07:44:08 -0700339 new_file_ref->type = file_ref.type;
340 new_file_ref->file = file_ref.file;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700341 return new_file_ref;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700342 }
Ryan Mitchellefcdb952021-04-14 17:31:37 -0700343
344 CloningValueTransformer cloner(&main_table_->string_pool);
345 return std::unique_ptr<FileReference>(file_ref.Transform(cloner));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700346}
347
Adam Lesinski00451162017-10-03 07:44:08 -0700348bool TableMerger::MergeFile(const ResourceFile& file_desc, bool overlay, io::IFile* file) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700349 ResourceTable table;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700350 std::string path = ResourceUtils::BuildResourceFileName(file_desc);
351 std::unique_ptr<FileReference> file_ref =
352 util::make_unique<FileReference>(table.string_pool.MakeRef(path));
353 file_ref->SetSource(file_desc.source);
Adam Lesinski00451162017-10-03 07:44:08 -0700354 file_ref->type = file_desc.type;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700355 file_ref->file = file;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800356
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700357 ResourceTablePackage* pkg = table.FindOrCreatePackage(file_desc.name.package);
Iurii Makhnof0c5ff42022-02-22 13:31:02 +0000358 pkg->FindOrCreateType(file_desc.name.type)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700359 ->FindOrCreateEntry(file_desc.name.entry)
360 ->FindOrCreateValue(file_desc.config, {})
361 ->value = std::move(file_ref);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800362
Fabien Sanglard2369f542019-03-19 08:32:46 -0700363 return DoMerge(file->GetSource(), pkg, false /*mangle*/, overlay /*overlay*/, true /*allow_new*/);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700364}
365
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700366} // namespace aapt