diff options
Diffstat (limited to 'tools/aapt2/ResourceTable.cpp')
-rw-r--r-- | tools/aapt2/ResourceTable.cpp | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 794090d..02be651 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -16,6 +16,7 @@ #include "ConfigDescription.h" #include "Logger.h" +#include "NameMangler.h" #include "ResourceTable.h" #include "ResourceValues.h" #include "Util.h" @@ -311,6 +312,71 @@ bool ResourceTable::markPublic(const ResourceNameRef& name, const ResourceId res return true; } +bool ResourceTable::merge(ResourceTable&& other) { + const bool mangleNames = mPackage != other.getPackage(); + std::u16string mangledName; + + for (auto& otherType : other) { + std::unique_ptr<ResourceTableType>& type = findOrCreateType(otherType->type); + if (type->publicStatus.isPublic && otherType->publicStatus.isPublic && + type->typeId != otherType->typeId) { + Logger::error() << "can not merge type '" << type->type << "': conflicting public IDs " + << "(" << type->typeId << " vs " << otherType->typeId << ")." + << std::endl; + return false; + } + + for (auto& otherEntry : otherType->entries) { + const std::u16string* nameToAdd = &otherEntry->name; + if (mangleNames) { + mangledName = otherEntry->name; + NameMangler::mangle(other.getPackage(), &mangledName); + nameToAdd = &mangledName; + } + + std::unique_ptr<ResourceEntry>& entry = findOrCreateEntry(type, *nameToAdd); + if (entry->publicStatus.isPublic && otherEntry->publicStatus.isPublic && + entry->entryId != otherEntry->entryId) { + Logger::error() << "can not merge entry '" << type->type << "/" << entry->name + << "': conflicting public IDs " + << "(" << entry->entryId << " vs " << entry->entryId << ")." + << std::endl; + return false; + } + + for (ResourceConfigValue& otherValue : otherEntry->values) { + auto iter = std::lower_bound(entry->values.begin(), entry->values.end(), + otherValue.config, compareConfigs); + if (iter != entry->values.end() && iter->config == otherValue.config) { + int collisionResult = defaultCollisionHandler(*iter->value, *otherValue.value); + if (collisionResult > 0) { + // Take the incoming value. + iter->source = std::move(otherValue.source); + iter->comment = std::move(otherValue.comment); + iter->value = std::unique_ptr<Value>(otherValue.value->clone(&mValuePool)); + } else if (collisionResult == 0) { + ResourceNameRef resourceName = { mPackage, type->type, entry->name }; + Logger::error(otherValue.source) + << "resource '" << resourceName << "' has a conflicting value for " + << "configuration (" << otherValue.config << ")." + << std::endl; + Logger::note(iter->source) << "originally defined here." << std::endl; + return false; + } + } else { + entry->values.insert(iter, ResourceConfigValue{ + otherValue.config, + std::move(otherValue.source), + std::move(otherValue.comment), + std::unique_ptr<Value>(otherValue.value->clone(&mValuePool)), + }); + } + } + } + } + return true; +} + std::tuple<const ResourceTableType*, const ResourceEntry*> ResourceTable::findResource(const ResourceNameRef& name) const { if (name.package != mPackage) { |