/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef AAPT_RESOURCE_TABLE_H #define AAPT_RESOURCE_TABLE_H #include "ConfigDescription.h" #include "Resource.h" #include "ResourceValues.h" #include "Source.h" #include "StringPool.h" #include <memory> #include <string> #include <tuple> #include <vector> namespace aapt { /** * The Public status of a resource. */ struct Public { bool isPublic = false; SourceLine source; std::u16string comment; }; /** * The resource value for a specific configuration. */ struct ResourceConfigValue { ConfigDescription config; SourceLine source; std::u16string comment; std::unique_ptr<Value> value; }; /** * Represents a resource entry, which may have * varying values for each defined configuration. */ struct ResourceEntry { enum { kUnsetEntryId = 0xffffffffu }; /** * The name of the resource. Immutable, as * this determines the order of this resource * when doing lookups. */ const std::u16string name; /** * The entry ID for this resource. */ size_t entryId; /** * Whether this resource is public (and must maintain the same * entry ID across builds). */ Public publicStatus; /** * The resource's values for each configuration. */ std::vector<ResourceConfigValue> values; inline ResourceEntry(const StringPiece16& _name); inline ResourceEntry(const ResourceEntry* rhs); }; /** * Represents a resource type, which holds entries defined * for this type. */ struct ResourceTableType { enum { kUnsetTypeId = 0xffffffffu }; /** * The logical type of resource (string, drawable, layout, etc.). */ const ResourceType type; /** * The type ID for this resource. */ size_t typeId; /** * Whether this type is public (and must maintain the same * type ID across builds). */ Public publicStatus; /** * List of resources for this type. */ std::vector<std::unique_ptr<ResourceEntry>> entries; ResourceTableType(const ResourceType _type); ResourceTableType(const ResourceTableType* rhs); }; /** * The container and index for all resources defined for an app. This gets * flattened into a binary resource table (resources.arsc). */ class ResourceTable { public: using iterator = std::vector<std::unique_ptr<ResourceTableType>>::iterator; using const_iterator = std::vector<std::unique_ptr<ResourceTableType>>::const_iterator; enum { kUnsetPackageId = 0xffffffff }; ResourceTable(); size_t getPackageId() const; void setPackageId(size_t packageId); const std::u16string& getPackage() const; void setPackage(const StringPiece16& package); bool addResource(const ResourceNameRef& name, const ConfigDescription& config, const SourceLine& source, std::unique_ptr<Value> value); /** * Same as addResource, but doesn't verify the validity of the name. This is used * when loading resources from an existing binary resource table that may have mangled * names. */ bool addResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config, const SourceLine& source, std::unique_ptr<Value> value); bool addResource(const ResourceNameRef& name, const ResourceId resId, const ConfigDescription& config, const SourceLine& source, std::unique_ptr<Value> value); bool markPublic(const ResourceNameRef& name, const ResourceId resId, const SourceLine& source); bool markPublicAllowMangled(const ResourceNameRef& name, const ResourceId resId, const SourceLine& source); /* * Merges the resources from `other` into this table, mangling the names of the resources * if `other` has a different package name. */ bool merge(ResourceTable&& other); /** * Returns the string pool used by this ResourceTable. * Values that reference strings should use this pool to create * their strings. */ StringPool& getValueStringPool(); const StringPool& getValueStringPool() const; std::tuple<const ResourceTableType*, const ResourceEntry*> findResource(const ResourceNameRef& name) const; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; private: std::unique_ptr<ResourceTableType>& findOrCreateType(ResourceType type); std::unique_ptr<ResourceEntry>& findOrCreateEntry(std::unique_ptr<ResourceTableType>& type, const StringPiece16& name); bool addResourceImpl(const ResourceNameRef& name, const ResourceId resId, const ConfigDescription& config, const SourceLine& source, std::unique_ptr<Value> value, const char16_t* validChars); bool markPublicImpl(const ResourceNameRef& name, const ResourceId resId, const SourceLine& source, const char16_t* validChars); std::u16string mPackage; size_t mPackageId; // StringPool must come before mTypes so that it is destroyed after. // When StringPool references are destroyed (as they will be when mTypes // is destroyed), they decrement a refCount, which would cause invalid // memory access if the pool was already destroyed. StringPool mValuePool; std::vector<std::unique_ptr<ResourceTableType>> mTypes; }; // // ResourceEntry implementation. // inline ResourceEntry::ResourceEntry(const StringPiece16& _name) : name(_name.toString()), entryId(kUnsetEntryId) { } inline ResourceEntry::ResourceEntry(const ResourceEntry* rhs) : name(rhs->name), entryId(rhs->entryId), publicStatus(rhs->publicStatus) { } // // ResourceTableType implementation. // inline ResourceTableType::ResourceTableType(const ResourceType _type) : type(_type), typeId(kUnsetTypeId) { } inline ResourceTableType::ResourceTableType(const ResourceTableType* rhs) : type(rhs->type), typeId(rhs->typeId), publicStatus(rhs->publicStatus) { } // // ResourceTable implementation. // inline StringPool& ResourceTable::getValueStringPool() { return mValuePool; } inline const StringPool& ResourceTable::getValueStringPool() const { return mValuePool; } inline ResourceTable::iterator ResourceTable::begin() { return mTypes.begin(); } inline ResourceTable::iterator ResourceTable::end() { return mTypes.end(); } inline ResourceTable::const_iterator ResourceTable::begin() const { return mTypes.begin(); } inline ResourceTable::const_iterator ResourceTable::end() const { return mTypes.end(); } inline const std::u16string& ResourceTable::getPackage() const { return mPackage; } inline size_t ResourceTable::getPackageId() const { return mPackageId; } inline void ResourceTable::setPackage(const StringPiece16& package) { mPackage = package.toString(); } inline void ResourceTable::setPackageId(size_t packageId) { mPackageId = packageId; } } // namespace aapt #endif // AAPT_RESOURCE_TABLE_H