1330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski/* 2330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * Copyright (C) 2015 The Android Open Source Project 3330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * 4330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * you may not use this file except in compliance with the License. 6330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * You may obtain a copy of the License at 7330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * 8330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * 10330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * See the License for the specific language governing permissions and 14330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski * limitations under the License. 15330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski */ 16330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 17330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include "Debug.h" 18330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include "ResourceTable.h" 19330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include "ResourceValues.h" 20330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include "Util.h" 21330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 22330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include <algorithm> 23330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include <iostream> 24330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include <map> 25330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include <memory> 26d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski#include <queue> 27330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include <set> 28330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski#include <vector> 29330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 30330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinskinamespace aapt { 31330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 32330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinskistruct PrintVisitor : ConstValueVisitor { 33330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski void visit(const Attribute& attr, ValueVisitorArgs&) override { 34330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "(attr) type="; 35330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski attr.printMask(std::cout); 36330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski static constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM | 37330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski android::ResTable_map::TYPE_FLAGS; 38330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (attr.typeMask & kMask) { 39330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const auto& symbol : attr.symbols) { 40330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "\n " 41330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski << symbol.symbol.name.entry << " (" << symbol.symbol.id << ") = " 42330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski << symbol.value; 43330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 44330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 45330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 46330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 47330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski void visit(const Style& style, ValueVisitorArgs&) override { 48330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "(style)"; 49330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (style.parent.name.isValid() || style.parent.id.isValid()) { 50330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " parent="; 51330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (style.parent.name.isValid()) { 52330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << style.parent.name << " "; 53330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 54330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 55330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (style.parent.id.isValid()) { 56330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << style.parent.id; 57330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 58330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 59330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 60330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const auto& entry : style.entries) { 61330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "\n "; 62330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (entry.key.name.isValid()) { 63330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << entry.key.name.package << ":" << entry.key.name.entry; 64330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 65330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 66330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (entry.key.id.isValid()) { 67330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "(" << entry.key.id << ")"; 68330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 69330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 70330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "=" << *entry.value; 71330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 72330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 73330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 74330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski void visit(const Array& array, ValueVisitorArgs&) override { 75330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski array.print(std::cout); 76330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 77330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 78330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski void visit(const Plural& plural, ValueVisitorArgs&) override { 79330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski plural.print(std::cout); 80330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 81330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 82330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski void visit(const Styleable& styleable, ValueVisitorArgs&) override { 83330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski styleable.print(std::cout); 84330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 85330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 86330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski void visitItem(const Item& item, ValueVisitorArgs& args) override { 87330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski item.print(std::cout); 88330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 89330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski}; 90330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 91330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinskivoid Debug::printTable(const std::shared_ptr<ResourceTable>& table) { 92330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "Package name=" << table->getPackage(); 93330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (table->getPackageId() != ResourceTable::kUnsetPackageId) { 94330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " id=" << std::hex << table->getPackageId() << std::dec; 95330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 96330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << std::endl; 97330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 98330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const auto& type : *table) { 99330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " type " << type->type; 100330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (type->typeId != ResourceTableType::kUnsetTypeId) { 101330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " id=" << std::hex << type->typeId << std::dec; 102330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 103330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " entryCount=" << type->entries.size() << std::endl; 104330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 105330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::vector<const ResourceEntry*> sortedEntries; 106330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const auto& entry : type->entries) { 107330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski auto iter = std::lower_bound(sortedEntries.begin(), sortedEntries.end(), entry.get(), 108330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski [](const ResourceEntry* a, const ResourceEntry* b) -> bool { 109330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski return a->entryId < b->entryId; 110330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski }); 111330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski sortedEntries.insert(iter, entry.get()); 112330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 113330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 114330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const ResourceEntry* entry : sortedEntries) { 115330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski ResourceId id = { table->getPackageId(), type->typeId, entry->entryId }; 116330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski ResourceName name = { table->getPackage(), type->type, entry->name }; 117330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " spec resource " << id << " " << name; 118330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (entry->publicStatus.isPublic) { 119330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " PUBLIC"; 120330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 121330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << std::endl; 122330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 123330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski PrintVisitor visitor; 124330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const auto& value : entry->values) { 125330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " (" << value.config << ") "; 126330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski value.value->accept(visitor, {}); 127330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << std::endl; 128330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 129330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 130330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 131330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 132330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 133330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinskistatic size_t getNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) { 134330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski auto iter = std::lower_bound(names.begin(), names.end(), name); 135330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski assert(iter != names.end() && *iter == name); 136330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski return std::distance(names.begin(), iter); 137330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 138330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 139d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinskivoid Debug::printStyleGraph(const std::shared_ptr<ResourceTable>& table, 140d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski const ResourceName& targetStyle) { 141330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::map<ResourceName, std::set<ResourceName>> graph; 142330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 143d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski std::queue<ResourceName> stylesToVisit; 144d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski stylesToVisit.push(targetStyle); 145d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski for (; !stylesToVisit.empty(); stylesToVisit.pop()) { 146d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski const ResourceName& styleName = stylesToVisit.front(); 147d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski std::set<ResourceName>& parents = graph[styleName]; 148d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski if (!parents.empty()) { 149d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski // We've already visited this style. 150d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski continue; 151d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski } 152d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski 153d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski const ResourceTableType* type; 154d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski const ResourceEntry* entry; 155d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski std::tie(type, entry) = table->findResource(styleName); 156d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski if (entry) { 157330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const auto& value : entry->values) { 158330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski visitFunc<Style>(*value.value, [&](const Style& style) { 159330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski if (style.parent.name.isValid()) { 160d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski parents.insert(style.parent.name); 161d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski stylesToVisit.push(style.parent.name); 162330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 163330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski }); 164330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 165330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 166330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 167330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 168d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski std::vector<ResourceName> names; 169d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski for (const auto& entry : graph) { 170d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski names.push_back(entry.first); 171d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski } 172330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 173330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "digraph styles {\n"; 174330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const auto& name : names) { 175330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << " node_" << getNodeIndex(names, name) 176d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski << " [label=\"" << name << "\"];\n"; 177330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 178330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 179330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski for (const auto& entry : graph) { 180d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski const ResourceName& styleName = entry.first; 181d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski size_t styleNodeIndex = getNodeIndex(names, styleName); 182330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 183d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski for (const auto& parentName : entry.second) { 184d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski std::cout << " node_" << styleNodeIndex << " -> " 185d13fb249865703901b77f48c5fed1864f06e1c63Adam Lesinski << "node_" << getNodeIndex(names, parentName) << ";\n"; 186330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 187330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski } 188330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 189330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski std::cout << "}" << std::endl; 190330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} 191330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski 192330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski} // namespace aapt 193