16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/*
26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License.
66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at
76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software
116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and
146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License.
156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#ifndef AAPT_BINARY_RESOURCE_PARSER_H
186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#define AAPT_BINARY_RESOURCE_PARSER_H
196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
20769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include "Resolver.h"
216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceTable.h"
226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceValues.h"
236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "Source.h"
246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <androidfw/ResourceTypes.h>
266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string>
276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt {
296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistruct SymbolTable_entry;
316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/*
336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Parses a binary resource table (resources.arsc) and adds the entries
346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * to a ResourceTable. This is different than the libandroidfw ResTable
356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * in that it scans the table from top to bottom and doesn't require
366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * support for random access. It is also able to parse non-runtime
376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * chunks and types.
386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass BinaryResourceParser {
406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic:
416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /*
426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Creates a parser, which will read `len` bytes from `data`, and
436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * add any resources parsed to `table`. `source` is for logging purposes.
446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
45769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
4624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski                         const std::shared_ptr<IResolver>& resolver,
47769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski                         const Source& source,
486cc479b76e9e2e8858434302e1ef2d514ed1b0ecAdam Lesinski                         const std::u16string& defaultPackage,
496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                         const void* data, size_t len);
506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    BinaryResourceParser(const BinaryResourceParser&) = delete; // No copy.
526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /*
546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Parses the binary resource table and returns true if successful.
556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool parse();
576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate:
596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // Helper method to retrieve the symbol name for a given table offset specified
606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // as a pointer.
616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool getSymbol(const void* data, ResourceNameRef* outSymbol);
626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool parseTable(const android::ResChunk_header* chunk);
646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool parseSymbolTable(const android::ResChunk_header* chunk);
656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // Looks up the resource ID in the reference and converts it to a name if available.
676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool idToName(Reference* reference);
686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool parsePackage(const android::ResChunk_header* chunk);
706ff19664f9279023c96e5a65c3059e1ef4beac0fAdam Lesinski    bool parsePublic(const android::ResChunk_header* chunk);
716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool parseTypeSpec(const android::ResChunk_header* chunk);
726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool parseType(const android::ResChunk_header* chunk);
736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::unique_ptr<Item> parseValue(const ResourceNameRef& name,
756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            const ConfigDescription& config, const android::Res_value* value, uint16_t flags);
766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::unique_ptr<Value> parseMapEntry(const ResourceNameRef& name,
786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            const ConfigDescription& config, const android::ResTable_map_entry* map);
796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::unique_ptr<Style> parseStyle(const ResourceNameRef& name,
816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            const ConfigDescription& config, const android::ResTable_map_entry* map);
826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::unique_ptr<Attribute> parseAttr(const ResourceNameRef& name,
846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            const ConfigDescription& config, const android::ResTable_map_entry* map);
856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::unique_ptr<Array> parseArray(const ResourceNameRef& name,
876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            const ConfigDescription& config, const android::ResTable_map_entry* map);
886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::unique_ptr<Plural> parsePlural(const ResourceNameRef& name,
906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            const ConfigDescription& config, const android::ResTable_map_entry* map);
916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::unique_ptr<Styleable> parseStyleable(const ResourceNameRef& name,
936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            const ConfigDescription& config, const android::ResTable_map_entry* map);
946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::shared_ptr<ResourceTable> mTable;
966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
9724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    std::shared_ptr<IResolver> mResolver;
98769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski
996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const Source mSource;
1006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1016cc479b76e9e2e8858434302e1ef2d514ed1b0ecAdam Lesinski    // The package name of the resource table.
1026cc479b76e9e2e8858434302e1ef2d514ed1b0ecAdam Lesinski    std::u16string mDefaultPackage;
1036cc479b76e9e2e8858434302e1ef2d514ed1b0ecAdam Lesinski
1046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const void* mData;
1056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const size_t mDataLen;
1066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // The array of symbol entries. Each element points to an offset
1086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // in the table and an index into the symbol table string pool.
1096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const SymbolTable_entry* mSymbolEntries = nullptr;
1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // Number of symbol entries.
1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    size_t mSymbolEntryCount = 0;
1136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // The symbol table string pool. Holds the names of symbols
1156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // referenced in this table but not defined nor resolved to an
1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // ID.
1176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    android::ResStringPool mSymbolPool;
1186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // The source string pool. Resource entries may have an extra
1206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // field that points into this string pool, which denotes where
1216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // the resource was parsed from originally.
1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    android::ResStringPool mSourcePool;
1236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // The standard value string pool for resource values.
1256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    android::ResStringPool mValuePool;
1266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // The string pool that holds the names of the types defined
1286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // in this table.
1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    android::ResStringPool mTypePool;
1306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // The string pool that holds the names of the entries defined
1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // in this table.
1336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    android::ResStringPool mKeyPool;
1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // A mapping of resource ID to resource name. When we finish parsing
1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // we use this to convert all resource IDs to symbolic references.
1376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    std::map<ResourceId, ResourceName> mIdIndex;
1386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski};
1396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt
1416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace android {
1436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
1456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Iterator functionality for ResTable_map_entry.
1466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
1476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const ResTable_map* begin(const ResTable_map_entry* map) {
1496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return reinterpret_cast<const ResTable_map*>(
1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            reinterpret_cast<const uint8_t*>(map) + map->size);
1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const ResTable_map* end(const ResTable_map_entry* map) {
1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return reinterpret_cast<const ResTable_map*>(
1556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            reinterpret_cast<const uint8_t*>(map) + map->size) + map->count;
1566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace android
1596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#endif // AAPT_BINARY_RESOURCE_PARSER_H
161