bool ResourceTable::markPublicImpl(const ResourceNameRef& name, const ResourceId& resId, const SourceLine& source, const char16_t* validChars) { if (!name.package.empty() && name.package != mPackage) { Logger::error(source) << "resource '" << name << "' has incompatible package. Must be '" << mPackage << "'." << std::endl; return false; } auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, validChars); if (badCharIter != name.entry.end()) { Logger::error(source) << "resource '" << name << "' has invalid entry name '" << name.entry << "'. Invalid character '" << StringPiece16(badCharIter, 1) << "'." << std::endl; return false; } std::unique_ptr<ResourceTableType>& type = findOrCreateType(name.type); if (resId.isValid() && type->typeId != ResourceTableType::kUnsetTypeId && type->typeId != resId.typeId()) { Logger::error(source) << "trying to make resource '" << name << "' public with ID " << resId << " but type '" << type->type << "' already has ID " << std::hex << type->typeId << std::dec << "." << std::endl; return false; } std::unique_ptr<ResourceEntry>& entry = findOrCreateEntry(type, name.entry); if (resId.isValid() && entry->entryId != ResourceEntry::kUnsetEntryId && entry->entryId != resId.entryId()) { Logger::error(source) << "trying to make resource '" << name << "' public with ID " << resId << " but resource already has ID " << ResourceId(mPackageId, type->typeId, entry->entryId) << "." << std::endl; return false; } type->publicStatus.isPublic = true; entry->publicStatus.isPublic = true; entry->publicStatus.source = source; if (resId.isValid()) { type->typeId = resId.typeId(); entry->entryId = resId.entryId(); } return true; }
bool ResourceTable::addResourceImpl(const ResourceNameRef& name, const ResourceId& resId, const ConfigDescription& config, const SourceLine& source, std::unique_ptr<Value> value, const char16_t* validChars) { if (!name.package.empty() && name.package != mPackage) { Logger::error(source) << "resource '" << name << "' has incompatible package. Must be '" << mPackage << "'." << std::endl; return false; } auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, validChars); if (badCharIter != name.entry.end()) { Logger::error(source) << "resource '" << name << "' has invalid entry name '" << name.entry << "'. Invalid character '" << StringPiece16(badCharIter, 1) << "'." << std::endl; return false; } std::unique_ptr<ResourceTableType>& type = findOrCreateType(name.type); if (resId.isValid() && type->typeId != ResourceTableType::kUnsetTypeId && type->typeId != resId.typeId()) { Logger::error(source) << "trying to add resource '" << name << "' with ID " << resId << " but type '" << type->type << "' already has ID " << std::hex << type->typeId << std::dec << "." << std::endl; return false; } std::unique_ptr<ResourceEntry>& entry = findOrCreateEntry(type, name.entry); if (resId.isValid() && entry->entryId != ResourceEntry::kUnsetEntryId && entry->entryId != resId.entryId()) { Logger::error(source) << "trying to add resource '" << name << "' with ID " << resId << " but resource already has ID " << ResourceId(mPackageId, type->typeId, entry->entryId) << "." << std::endl; return false; } const auto endIter = std::end(entry->values); auto iter = std::lower_bound(std::begin(entry->values), endIter, config, compareConfigs); if (iter == endIter || iter->config != config) { // This resource did not exist before, add it. entry->values.insert(iter, ResourceConfigValue{ config, source, {}, std::move(value) }); } else { int collisionResult = defaultCollisionHandler(*iter->value, *value); if (collisionResult > 0) { // Take the incoming value. *iter = ResourceConfigValue{ config, source, {}, std::move(value) }; } else if (collisionResult == 0) { Logger::error(source) << "duplicate value for resource '" << name << "' " << "with config '" << iter->config << "'." << std::endl; Logger::error(iter->source) << "resource previously defined here." << std::endl; return false; } } if (resId.isValid()) { type->typeId = resId.typeId(); entry->entryId = resId.entryId(); } return true; }