This CL introduces DeduplicateItemsResEntryWriter which stores unique pairs of entry and value and deduplicates a new pair based of this data before writing it into the buffer. Bug: b/249793372 Test: ResEntriesWriter_test, TableFlattener_test Change-Id: I938a3425a87bfad9853e59193680de2050a95bd2
135 lines
4.3 KiB
C++
135 lines
4.3 KiB
C++
/*
|
|
* Copyright (C) 2022 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_FORMAT_BINARY_RESENTRY_SERIALIZER_H
|
|
#define AAPT_FORMAT_BINARY_RESENTRY_SERIALIZER_H
|
|
|
|
#include <unordered_map>
|
|
|
|
#include "ResourceTable.h"
|
|
#include "ValueVisitor.h"
|
|
#include "android-base/macros.h"
|
|
#include "androidfw/BigBuffer.h"
|
|
#include "androidfw/ResourceTypes.h"
|
|
|
|
namespace aapt {
|
|
|
|
struct FlatEntry {
|
|
const ResourceTableEntryView* entry;
|
|
const Value* value;
|
|
|
|
// The entry string pool index to the entry's name.
|
|
uint32_t entry_key;
|
|
};
|
|
|
|
// Pair of ResTable_entry and Res_value. These pairs are stored sequentially in values buffer.
|
|
// We introduce this structure for ResEntryWriter to a have single allocation using
|
|
// BigBuffer::NextBlock which allows to return it back with BigBuffer::Backup.
|
|
struct ResEntryValuePair {
|
|
android::ResTable_entry entry;
|
|
android::Res_value value;
|
|
};
|
|
|
|
// References ResEntryValuePair object stored in BigBuffer used as a key in std::unordered_map.
|
|
// Allows access to memory address where ResEntryValuePair is stored.
|
|
union ResEntryValuePairRef {
|
|
const std::reference_wrapper<const ResEntryValuePair> pair;
|
|
const u_char* ptr;
|
|
|
|
explicit ResEntryValuePairRef(const ResEntryValuePair& ref) : pair(ref) {
|
|
}
|
|
};
|
|
|
|
// Hasher which computes hash of ResEntryValuePair using its bytes representation in memory.
|
|
struct ResEntryValuePairContentHasher {
|
|
std::size_t operator()(const ResEntryValuePairRef& ref) const;
|
|
};
|
|
|
|
// Equaler which compares ResEntryValuePairs using theirs bytes representation in memory.
|
|
struct ResEntryValuePairContentEqualTo {
|
|
bool operator()(const ResEntryValuePairRef& a, const ResEntryValuePairRef& b) const;
|
|
};
|
|
|
|
// Base class that allows to write FlatEntries into entries_buffer.
|
|
class ResEntryWriter {
|
|
public:
|
|
virtual ~ResEntryWriter() = default;
|
|
|
|
// Writes resource table entry and its value into 'entries_buffer_' and returns offset
|
|
// in the buffer where entry was written.
|
|
int32_t Write(const FlatEntry* entry) {
|
|
if (ValueCast<Item>(entry->value) != nullptr) {
|
|
return WriteItem(entry);
|
|
} else {
|
|
return WriteMap(entry);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
ResEntryWriter(android::BigBuffer* entries_buffer) : entries_buffer_(entries_buffer) {
|
|
}
|
|
android::BigBuffer* entries_buffer_;
|
|
|
|
virtual int32_t WriteItem(const FlatEntry* entry) = 0;
|
|
|
|
virtual int32_t WriteMap(const FlatEntry* entry) = 0;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ResEntryWriter);
|
|
};
|
|
|
|
// ResEntryWriter which writes FlatEntries sequentially into entries_buffer.
|
|
// Next entry is always written right after previous one in the buffer.
|
|
class SequentialResEntryWriter : public ResEntryWriter {
|
|
public:
|
|
explicit SequentialResEntryWriter(android::BigBuffer* entries_buffer)
|
|
: ResEntryWriter(entries_buffer) {
|
|
}
|
|
~SequentialResEntryWriter() override = default;
|
|
|
|
int32_t WriteItem(const FlatEntry* entry) override;
|
|
|
|
int32_t WriteMap(const FlatEntry* entry) override;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(SequentialResEntryWriter);
|
|
};
|
|
|
|
// ResEntryWriter that writes only unique entry and value pairs into entries_buffer.
|
|
// Next entry is written into buffer only if there is no entry with the same bytes representation
|
|
// in memory written before. Otherwise returns offset of already written entry.
|
|
class DeduplicateItemsResEntryWriter : public ResEntryWriter {
|
|
public:
|
|
explicit DeduplicateItemsResEntryWriter(android::BigBuffer* entries_buffer)
|
|
: ResEntryWriter(entries_buffer) {
|
|
}
|
|
~DeduplicateItemsResEntryWriter() override = default;
|
|
|
|
int32_t WriteItem(const FlatEntry* entry) override;
|
|
|
|
int32_t WriteMap(const FlatEntry* entry) override;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(DeduplicateItemsResEntryWriter);
|
|
|
|
std::unordered_map<ResEntryValuePairRef, int32_t, ResEntryValuePairContentHasher,
|
|
ResEntryValuePairContentEqualTo>
|
|
entry_offsets;
|
|
};
|
|
|
|
} // namespace aapt
|
|
|
|
#endif |