зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1586977
- Remove MapBasedHuffmanTable. r=Yoric
Differential Revision: https://phabricator.services.mozilla.com/D48652 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a1c0a017c1
Коммит
712cf567f2
|
@ -1958,77 +1958,6 @@ HuffmanEntry<const T*> NaiveHuffmanTable<T, N>::lookup(
|
|||
return HuffmanEntry<const T*>(0, 0, nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
JS::Result<Ok> MapBasedHuffmanTable<T>::initWithSingleValue(JSContext* cx,
|
||||
T&& value) {
|
||||
MOZ_ASSERT(values_.empty()); // Make sure that we're initializing.
|
||||
const HuffmanKey key(0, 0);
|
||||
if (MOZ_UNLIKELY(!values_.put(FlatHuffmanKey(key), std::move(value)) ||
|
||||
!keys_.append(key))) {
|
||||
ReportOutOfMemory(cx);
|
||||
return cx->alreadyReportedError();
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
JS::Result<Ok> MapBasedHuffmanTable<T>::initStart(JSContext* cx,
|
||||
size_t numberOfSymbols,
|
||||
uint8_t) {
|
||||
MOZ_ASSERT(values_.empty()); // Make sure that we're initializing.
|
||||
if (MOZ_UNLIKELY(!values_.reserve(numberOfSymbols) ||
|
||||
!keys_.reserve(numberOfSymbols))) {
|
||||
ReportOutOfMemory(cx);
|
||||
return cx->alreadyReportedError();
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
JS::Result<Ok> MapBasedHuffmanTable<T>::initComplete() {
|
||||
#if DEBUG
|
||||
// Check that there is a bijection between `keys_` and `values_`.
|
||||
// 1. Injection.
|
||||
for (const auto& key : keys_) {
|
||||
MOZ_ALWAYS_TRUE(values_.has(FlatHuffmanKey(key)));
|
||||
}
|
||||
// 2. Cardinality.
|
||||
MOZ_ASSERT(values_.count() == keys_.length());
|
||||
#endif // DEBUG
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
JS::Result<Ok> MapBasedHuffmanTable<T>::addSymbol(uint32_t bits,
|
||||
uint8_t bitLength,
|
||||
T&& value) {
|
||||
MOZ_ASSERT_IF(bitLength != 32 /* >> 32 is UB */, bits >> bitLength == 0);
|
||||
const HuffmanKey key(bits, bitLength);
|
||||
const FlatHuffmanKey flat(key);
|
||||
values_.putNewInfallible(
|
||||
flat, std::move(value)); // Memory was reserved in `init()`.
|
||||
keys_.infallibleAppend(std::move(key));
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HuffmanEntry<const T*> MapBasedHuffmanTable<T>::lookup(
|
||||
HuffmanLookup lookup) const {
|
||||
for (auto bitLength = 0; bitLength < MAX_CODE_BIT_LENGTH; ++bitLength) {
|
||||
const uint32_t bits = lookup.leadingBits(bitLength);
|
||||
const HuffmanKey key(bits, bitLength);
|
||||
const FlatHuffmanKey flat(key);
|
||||
if (auto ptr = values_.lookup(flat)) {
|
||||
// Entry found.
|
||||
return HuffmanEntry<const T*>(bits, bitLength, &ptr->value());
|
||||
}
|
||||
}
|
||||
|
||||
// Error: no entry found.
|
||||
return HuffmanEntry<const T*>(0, 0, nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SingleEntryHuffmanTable<T>::Iterator::Iterator(const T* position)
|
||||
: position_(position) {}
|
||||
|
|
|
@ -262,99 +262,6 @@ class NaiveHuffmanTable {
|
|||
friend class HuffmanPreludeReader;
|
||||
};
|
||||
|
||||
// An implementation of Huffman Tables as a hash map. Space-Efficient,
|
||||
// faster than NaiveHuffmanTable for large tables but not terribly
|
||||
// fast, either.
|
||||
//
|
||||
// Complexity:
|
||||
//
|
||||
// - We assume that hashing is sufficient to guarantee `O(1)` lookups
|
||||
// inside the hashmap.
|
||||
// - On a well-formed file, all lookups are successful and a Huffman
|
||||
// lookup will take exactly `bitLen` Hashmap lookups. This makes it
|
||||
// `O(MAX_CODE_BIT_LENGTH)` worst case. This also makes it
|
||||
// `O(ln(N))` in the best case (perfectly balanced Huffman table)
|
||||
// and `O(N)` in the worst case (perfectly linear Huffman table),
|
||||
// where `N` is the number of entries.
|
||||
// - On an invalid file, the number of lookups is also bounded by
|
||||
// `MAX_CODE_BIT_LENGTH`.
|
||||
template <typename T>
|
||||
class MapBasedHuffmanTable {
|
||||
public:
|
||||
explicit MapBasedHuffmanTable(JSContext* cx) : values_(cx), keys_(cx) {}
|
||||
MapBasedHuffmanTable(MapBasedHuffmanTable&& other) noexcept
|
||||
: values_(std::move(other.values_)), keys_(std::move(other.keys_)) {}
|
||||
|
||||
// Initialize a Huffman table containing a single value.
|
||||
JS::Result<Ok> initWithSingleValue(JSContext* cx, T&& value);
|
||||
|
||||
// Initialize a Huffman table containing `numberOfSymbols`.
|
||||
// Symbols must be added with `addSymbol`.
|
||||
// If you initialize with `initStart`, you MUST call `initComplete()`
|
||||
// at the end of initialization.
|
||||
JS::Result<Ok> initStart(JSContext* cx, size_t numberOfSymbols,
|
||||
uint8_t maxBitLength);
|
||||
|
||||
// Add a `(bit, bitLength) => value` mapping.
|
||||
JS::Result<Ok> addSymbol(uint32_t bits, uint8_t bitLength, T&& value);
|
||||
|
||||
JS::Result<Ok> initComplete();
|
||||
|
||||
MapBasedHuffmanTable() = delete;
|
||||
MapBasedHuffmanTable(MapBasedHuffmanTable&) = delete;
|
||||
|
||||
// Lookup a value in the table.
|
||||
//
|
||||
// Return an entry with a value of `nullptr` if the value is not in the table.
|
||||
//
|
||||
// The lookup may advance `key` by `[0, key.bitLength_]` bits. Typically, in a
|
||||
// table with a single instance, or if the value is not in the table, it
|
||||
// will advance by 0 bits. The caller is responsible for advancing its
|
||||
// bitstream by `result.key_.bitLength_` bits.
|
||||
HuffmanEntry<const T*> lookup(HuffmanLookup key) const;
|
||||
|
||||
// The number of values in the table.
|
||||
size_t length() const { return values_.length(); }
|
||||
|
||||
// Iterating in the order of insertion.
|
||||
struct Iterator {
|
||||
Iterator(const js::HashMap<FlatHuffmanKey, T, FlatHuffmanKey>& values,
|
||||
const HuffmanKey* position)
|
||||
: values_(values), position_(position) {}
|
||||
void operator++() { ++position_; }
|
||||
const T* operator*() const {
|
||||
const FlatHuffmanKey key(position_);
|
||||
if (const auto ptr = values_.lookup(key)) {
|
||||
return &ptr->value();
|
||||
}
|
||||
MOZ_CRASH();
|
||||
}
|
||||
bool operator==(const Iterator& other) const {
|
||||
MOZ_ASSERT(&values_ == &other.values_);
|
||||
return position_ == other.position_;
|
||||
}
|
||||
bool operator!=(const Iterator& other) const {
|
||||
MOZ_ASSERT(&values_ == &other.values_);
|
||||
return position_ != other.position_;
|
||||
}
|
||||
|
||||
private:
|
||||
const js::HashMap<FlatHuffmanKey, T, FlatHuffmanKey>& values_;
|
||||
const HuffmanKey* position_;
|
||||
};
|
||||
Iterator begin() const { return Iterator(values_, keys_.begin()); }
|
||||
Iterator end() const { return Iterator(values_, keys_.end()); }
|
||||
|
||||
private:
|
||||
// The entries in this Huffman table, prepared for lookup.
|
||||
js::HashMap<FlatHuffmanKey, T, FlatHuffmanKey> values_;
|
||||
|
||||
// The entries in this Huffman Table, sorted in the order of insertion.
|
||||
Vector<HuffmanKey> keys_;
|
||||
|
||||
friend class HuffmanPreludeReader;
|
||||
};
|
||||
|
||||
// An implementation of Huffman Tables for single-entry table.
|
||||
template <typename T>
|
||||
class SingleEntryHuffmanTable {
|
||||
|
|
Загрузка…
Ссылка в новой задаче