AAPT2: Separate out the various steps

An early refactor. Some ideas became clearer as
development continued. Now the various phases are much
clearer and more easily reusable.

Also added a ton of tests!

Change-Id: Ic8f0a70c8222370352e63533b329c40457c0903e
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 706f56a..a00c142 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -18,6 +18,7 @@
 #define AAPT_RESOURCE_TABLE_H
 
 #include "ConfigDescription.h"
+#include "Diagnostics.h"
 #include "Resource.h"
 #include "ResourceValues.h"
 #include "Source.h"
@@ -35,7 +36,7 @@
  */
 struct Public {
     bool isPublic = false;
-    SourceLine source;
+    Source source;
     std::u16string comment;
 };
 
@@ -44,7 +45,7 @@
  */
 struct ResourceConfigValue {
     ConfigDescription config;
-    SourceLine source;
+    Source source;
     std::u16string comment;
     std::unique_ptr<Value> value;
 };
@@ -54,10 +55,6 @@
  * 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
@@ -68,7 +65,7 @@
     /**
      * The entry ID for this resource.
      */
-    size_t entryId;
+    Maybe<uint16_t> id;
 
     /**
      * Whether this resource is public (and must maintain the same
@@ -81,8 +78,7 @@
      */
     std::vector<ResourceConfigValue> values;
 
-    inline ResourceEntry(const StringPiece16& _name);
-    inline ResourceEntry(const ResourceEntry* rhs);
+    ResourceEntry(const StringPiece16& name) : name(name.toString()) { }
 };
 
 /**
@@ -90,10 +86,6 @@
  * for this type.
  */
 struct ResourceTableType {
-    enum {
-        kUnsetTypeId = 0xffffffffu
-    };
-
     /**
      * The logical type of resource (string, drawable, layout, etc.).
      */
@@ -102,7 +94,7 @@
     /**
      * The type ID for this resource.
      */
-    size_t typeId;
+    Maybe<uint8_t> id;
 
     /**
      * Whether this type is public (and must maintain the same
@@ -115,8 +107,30 @@
      */
     std::vector<std::unique_ptr<ResourceEntry>> entries;
 
-    ResourceTableType(const ResourceType _type);
-    ResourceTableType(const ResourceTableType* rhs);
+    explicit ResourceTableType(const ResourceType type) : type(type) { }
+
+    ResourceEntry* findEntry(const StringPiece16& name);
+
+    ResourceEntry* findOrCreateEntry(const StringPiece16& name);
+};
+
+enum class PackageType {
+    System,
+    Vendor,
+    App,
+    Dynamic
+};
+
+struct ResourceTablePackage {
+    PackageType type = PackageType::App;
+    Maybe<uint8_t> id;
+    std::u16string name;
+
+    std::vector<std::unique_ptr<ResourceTableType>> types;
+
+    ResourceTableType* findType(ResourceType type);
+
+    ResourceTableType* findOrCreateType(const ResourceType type);
 };
 
 /**
@@ -125,23 +139,28 @@
  */
 class ResourceTable {
 public:
-    using iterator = std::vector<std::unique_ptr<ResourceTableType>>::iterator;
-    using const_iterator = std::vector<std::unique_ptr<ResourceTableType>>::const_iterator;
+    ResourceTable() = default;
+    ResourceTable(const ResourceTable&) = delete;
+    ResourceTable& operator=(const ResourceTable&) = delete;
 
-    enum {
-        kUnsetPackageId = 0xffffffff
-    };
-
-    ResourceTable();
-
-    size_t getPackageId() const;
-    void setPackageId(size_t packageId);
-
-    const std::u16string& getPackage() const;
-    void setPackage(const StringPiece16& package);
+    /**
+     * When a collision of resources occurs, this method decides which value to keep.
+     * Returns -1 if the existing value should be chosen.
+     * Returns 0 if the collision can not be resolved (error).
+     * Returns 1 if the incoming value should be chosen.
+     */
+    static int resolveValueCollision(Value* existing, Value* incoming);
 
     bool addResource(const ResourceNameRef& name, const ConfigDescription& config,
-                     const SourceLine& source, std::unique_ptr<Value> value);
+                     const Source& source, std::unique_ptr<Value> value,
+                     IDiagnostics* diag);
+
+    bool addResource(const ResourceNameRef& name, const ResourceId resId,
+                     const ConfigDescription& config, const Source& source,
+                     std::unique_ptr<Value> value, IDiagnostics* diag);
+
+    bool addFileReference(const ResourceNameRef& name, const ConfigDescription& config,
+                          const Source& source, const StringPiece16& path, IDiagnostics* diag);
 
     /**
      * Same as addResource, but doesn't verify the validity of the name. This is used
@@ -149,129 +168,59 @@
      * names.
      */
     bool addResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
-                                 const SourceLine& source, std::unique_ptr<Value> value);
+                                 const Source& source, std::unique_ptr<Value> value,
+                                 IDiagnostics* diag);
 
-    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 markPublic(const ResourceNameRef& name, const ResourceId resId, const Source& source,
+                    IDiagnostics* diag);
     bool markPublicAllowMangled(const ResourceNameRef& name, const ResourceId resId,
-                                const SourceLine& source);
+                                const Source& source, IDiagnostics* diag);
+    struct SearchResult {
+	ResourceTablePackage* package;
+	ResourceTableType* type;
+	ResourceEntry* entry;
+    };
 
-    /*
-     * 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);
+    Maybe<SearchResult> findResource(const ResourceNameRef& name);
 
     /**
-     * Returns the string pool used by this ResourceTable.
-     * Values that reference strings should use this pool to create
-     * their strings.
+     * The string pool used by this resource table. Values that reference strings must use
+     * this pool to create their strings.
+     *
+     * NOTE: `stringPool` must come before `packages` so that it is destroyed after.
+     * When `string pool` references are destroyed (as they will be when `packages`
+     * is destroyed), they decrement a refCount, which would cause invalid
+     * memory access if the pool was already destroyed.
      */
-    StringPool& getValueStringPool();
-    const StringPool& getValueStringPool() const;
+    StringPool stringPool;
 
-    std::tuple<const ResourceTableType*, const ResourceEntry*>
-    findResource(const ResourceNameRef& name) const;
+    /**
+     * The list of packages in this table, sorted alphabetically by package name.
+     */
+    std::vector<std::unique_ptr<ResourceTablePackage>> packages;
 
-    iterator begin();
-    iterator end();
-    const_iterator begin() const;
-    const_iterator end() const;
+    /**
+     * Returns the package struct with the given name, or nullptr if such a package does not
+     * exist. The empty string is a valid package and typically is used to represent the
+     * 'current' package before it is known to the ResourceTable.
+     */
+    ResourceTablePackage* findPackage(const StringPiece16& name);
+
+    ResourceTablePackage* findPackageById(uint8_t id);
+
+    ResourceTablePackage* createPackage(const StringPiece16& name, uint8_t id);
 
 private:
-    std::unique_ptr<ResourceTableType>& findOrCreateType(ResourceType type);
-    std::unique_ptr<ResourceEntry>& findOrCreateEntry(std::unique_ptr<ResourceTableType>& type,
-                                                      const StringPiece16& name);
+    ResourceTablePackage* findOrCreatePackage(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);
+                         const ConfigDescription& config, const Source& source,
+                         std::unique_ptr<Value> value, const char16_t* validChars,
+                         IDiagnostics* diag);
     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;
+                        const Source& source, const char16_t* validChars, IDiagnostics* diag);
 };
 
-//
-// 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