зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1586971 - Add SingleEntryHuffmanTable. r=Yoric
Differential Revision: https://phabricator.services.mozilla.com/D48473 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
be1002620d
Коммит
cce326db03
|
@ -1620,6 +1620,11 @@ FlatHuffmanKey::FlatHuffmanKey(const HuffmanKey* key)
|
|||
|
||||
// ---- Implementation of Huffman Tables
|
||||
|
||||
template <typename T>
|
||||
GenericHuffmanTable<T>::Iterator::Iterator(
|
||||
typename SingleEntryHuffmanTable<T>::Iterator&& iterator)
|
||||
: implementation(std::move(iterator)) {}
|
||||
|
||||
template <typename T>
|
||||
GenericHuffmanTable<T>::Iterator::Iterator(
|
||||
typename SingleLookupHuffmanTable<T>::Iterator&& iterator)
|
||||
|
@ -1638,6 +1643,9 @@ GenericHuffmanTable<T>::Iterator::Iterator(
|
|||
template <typename T>
|
||||
void GenericHuffmanTable<T>::Iterator::operator++() {
|
||||
implementation.match(
|
||||
[](typename SingleEntryHuffmanTable<T>::Iterator& iterator) {
|
||||
iterator.operator++();
|
||||
},
|
||||
[](typename SingleLookupHuffmanTable<T>::Iterator& iterator) {
|
||||
iterator.operator++();
|
||||
},
|
||||
|
@ -1653,6 +1661,10 @@ template <typename T>
|
|||
bool GenericHuffmanTable<T>::Iterator::operator==(
|
||||
const GenericHuffmanTable<T>::Iterator& other) const {
|
||||
return implementation.match(
|
||||
[other](const typename SingleEntryHuffmanTable<T>::Iterator& iterator) {
|
||||
return iterator == other.implementation.template as<
|
||||
typename SingleEntryHuffmanTable<T>::Iterator>();
|
||||
},
|
||||
[other](const typename SingleLookupHuffmanTable<T>::Iterator& iterator) {
|
||||
return iterator ==
|
||||
other.implementation.template as<
|
||||
|
@ -1674,6 +1686,10 @@ template <typename T>
|
|||
bool GenericHuffmanTable<T>::Iterator::operator!=(
|
||||
const GenericHuffmanTable<T>::Iterator& other) const {
|
||||
return implementation.match(
|
||||
[other](const typename SingleEntryHuffmanTable<T>::Iterator& iterator) {
|
||||
return iterator != other.implementation.template as<
|
||||
typename SingleEntryHuffmanTable<T>::Iterator>();
|
||||
},
|
||||
[other](const typename SingleLookupHuffmanTable<T>::Iterator& iterator) {
|
||||
return iterator !=
|
||||
other.implementation.template as<
|
||||
|
@ -1694,6 +1710,9 @@ bool GenericHuffmanTable<T>::Iterator::operator!=(
|
|||
template <typename T>
|
||||
const T* GenericHuffmanTable<T>::Iterator::operator*() const {
|
||||
return implementation.match(
|
||||
[](const typename SingleEntryHuffmanTable<T>::Iterator& iterator) {
|
||||
return iterator.operator*();
|
||||
},
|
||||
[](const typename SingleLookupHuffmanTable<T>::Iterator& iterator) {
|
||||
return iterator.operator*();
|
||||
},
|
||||
|
@ -1712,6 +1731,9 @@ GenericHuffmanTable<T>::GenericHuffmanTable(JSContext*)
|
|||
template <typename T>
|
||||
JS::Result<Ok> GenericHuffmanTable<T>::initComplete() {
|
||||
return this->implementation.match(
|
||||
[](SingleEntryHuffmanTable<T>& implementation) -> JS::Result<Ok> {
|
||||
MOZ_CRASH("SingleEntryHuffmanTable shouldn't have multiple entries!");
|
||||
},
|
||||
[](SingleLookupHuffmanTable<T>& implementation) -> JS::Result<Ok> {
|
||||
return implementation.initComplete();
|
||||
},
|
||||
|
@ -1730,6 +1752,10 @@ template <typename T>
|
|||
typename GenericHuffmanTable<T>::Iterator GenericHuffmanTable<T>::begin()
|
||||
const {
|
||||
return this->implementation.match(
|
||||
[](const SingleEntryHuffmanTable<T>& implementation)
|
||||
-> GenericHuffmanTable<T>::Iterator {
|
||||
return Iterator(implementation.begin());
|
||||
},
|
||||
[](const SingleLookupHuffmanTable<T>& implementation)
|
||||
-> GenericHuffmanTable<T>::Iterator {
|
||||
return Iterator(implementation.begin());
|
||||
|
@ -1750,6 +1776,10 @@ typename GenericHuffmanTable<T>::Iterator GenericHuffmanTable<T>::begin()
|
|||
template <typename T>
|
||||
typename GenericHuffmanTable<T>::Iterator GenericHuffmanTable<T>::end() const {
|
||||
return this->implementation.match(
|
||||
[](const SingleEntryHuffmanTable<T>& implementation)
|
||||
-> GenericHuffmanTable<T>::Iterator {
|
||||
return Iterator(implementation.end());
|
||||
},
|
||||
[](const SingleLookupHuffmanTable<T>& implementation)
|
||||
-> GenericHuffmanTable<T>::Iterator {
|
||||
return Iterator(implementation.end());
|
||||
|
@ -1774,11 +1804,8 @@ JS::Result<Ok> GenericHuffmanTable<T>::initWithSingleValue(JSContext* cx,
|
|||
MOZ_ASSERT(this->implementation.template is<
|
||||
HuffmanTableUnreachable>()); // Make sure that we're initializing.
|
||||
|
||||
this->implementation = {mozilla::VariantType<SingleLookupHuffmanTable<T>>{},
|
||||
cx};
|
||||
|
||||
MOZ_TRY(this->implementation.template as<SingleLookupHuffmanTable<T>>()
|
||||
.initWithSingleValue(cx, std::move(value)));
|
||||
this->implementation = {mozilla::VariantType<SingleEntryHuffmanTable<T>>{},
|
||||
std::move(value)};
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
@ -1823,6 +1850,10 @@ template <typename T>
|
|||
JS::Result<Ok> GenericHuffmanTable<T>::addSymbol(uint32_t bits,
|
||||
uint8_t bitLength, T&& value) {
|
||||
return this->implementation.match(
|
||||
[](SingleEntryHuffmanTable<T>&) -> JS::Result<Ok> {
|
||||
MOZ_CRASH("SingleEntryHuffmanTable shouldn't have multiple entries!");
|
||||
return Ok();
|
||||
},
|
||||
[bits, bitLength, value = std::move(value)](
|
||||
SingleLookupHuffmanTable<T>&
|
||||
implementation) mutable /* discard implicit const */
|
||||
|
@ -1851,6 +1882,8 @@ template <typename T>
|
|||
HuffmanEntry<const T*> GenericHuffmanTable<T>::lookup(
|
||||
HuffmanLookup lookup) const {
|
||||
return this->implementation.match(
|
||||
[lookup](const SingleEntryHuffmanTable<T>& implementation)
|
||||
-> HuffmanEntry<const T*> { return implementation.lookup(lookup); },
|
||||
[lookup](const SingleLookupHuffmanTable<T>& implementation)
|
||||
-> HuffmanEntry<const T*> { return implementation.lookup(lookup); },
|
||||
[lookup](const TwoLookupsHuffmanTable<T>& implementation)
|
||||
|
@ -1999,6 +2032,39 @@ HuffmanEntry<const T*> MapBasedHuffmanTable<T>::lookup(
|
|||
return HuffmanEntry<const T*>(0, 0, nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SingleEntryHuffmanTable<T>::Iterator::Iterator(const T* position)
|
||||
: position(position) {}
|
||||
|
||||
template <typename T>
|
||||
void SingleEntryHuffmanTable<T>::Iterator::operator++() {
|
||||
// There's only one entry, and `nullptr` means `end`.
|
||||
position = nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T* SingleEntryHuffmanTable<T>::Iterator::operator*() const {
|
||||
return position;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool SingleEntryHuffmanTable<T>::Iterator::operator==(
|
||||
const Iterator& other) const {
|
||||
return position == other.position;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool SingleEntryHuffmanTable<T>::Iterator::operator!=(
|
||||
const Iterator& other) const {
|
||||
return position != other.position;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HuffmanEntry<const T*> SingleEntryHuffmanTable<T>::lookup(
|
||||
HuffmanLookup key) const {
|
||||
return HuffmanEntry<const T*>(0, 0, &value_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SingleLookupHuffmanTable<T>::Iterator::Iterator(const HuffmanEntry<T>* position)
|
||||
: position(position) {}
|
||||
|
@ -2025,22 +2091,6 @@ bool SingleLookupHuffmanTable<T>::Iterator::operator!=(
|
|||
return position != other.position;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
JS::Result<Ok> SingleLookupHuffmanTable<T>::initWithSingleValue(JSContext* cx,
|
||||
T&& value) {
|
||||
MOZ_ASSERT(values.empty()); // Make sure that we're initializing.
|
||||
if (MOZ_UNLIKELY(!values.emplaceBack(0, 0, std::move(value)))) {
|
||||
ReportOutOfMemory(cx);
|
||||
return cx->alreadyReportedError();
|
||||
}
|
||||
if (MOZ_UNLIKELY(!saturated.emplaceBack(0))) {
|
||||
ReportOutOfMemory(cx);
|
||||
return cx->alreadyReportedError();
|
||||
}
|
||||
this->largestBitLength = 0;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
JS::Result<Ok> SingleLookupHuffmanTable<T>::initStart(
|
||||
JSContext* cx, size_t numberOfSymbols, uint8_t largestBitLength) {
|
||||
|
|
|
@ -355,6 +355,43 @@ class MapBasedHuffmanTable {
|
|||
friend class HuffmanPreludeReader;
|
||||
};
|
||||
|
||||
// An implementation of Huffman Tables for single-entry table.
|
||||
template <typename T>
|
||||
class SingleEntryHuffmanTable {
|
||||
public:
|
||||
explicit SingleEntryHuffmanTable(T&& value) : value_(std::move(value)) {}
|
||||
SingleEntryHuffmanTable(SingleEntryHuffmanTable&& other) = default;
|
||||
|
||||
SingleEntryHuffmanTable() = delete;
|
||||
SingleEntryHuffmanTable(SingleEntryHuffmanTable&) = delete;
|
||||
|
||||
// Lookup a value in the table.
|
||||
// The key is 0-bit length and this always suceeds.
|
||||
HuffmanEntry<const T*> lookup(HuffmanLookup key) const;
|
||||
|
||||
// The number of values in the table.
|
||||
size_t length() const { return 1; }
|
||||
|
||||
// Iterating in the order of insertion.
|
||||
struct Iterator {
|
||||
explicit Iterator(const T* position);
|
||||
void operator++();
|
||||
const T* operator*() const;
|
||||
bool operator==(const Iterator& other) const;
|
||||
bool operator!=(const Iterator& other) const;
|
||||
|
||||
private:
|
||||
const T* position;
|
||||
};
|
||||
Iterator begin() const { return Iterator(&value_); }
|
||||
Iterator end() const { return Iterator(nullptr); }
|
||||
|
||||
private:
|
||||
T value_;
|
||||
|
||||
friend class HuffmanPreludeReader;
|
||||
};
|
||||
|
||||
// An implementation of Huffman Tables as a vector designed to allow
|
||||
// constant-time lookups at the expense of high space complexity.
|
||||
//
|
||||
|
@ -442,9 +479,6 @@ class SingleLookupHuffmanTable {
|
|||
: values(cx), saturated(cx), largestBitLength(-1) {}
|
||||
SingleLookupHuffmanTable(SingleLookupHuffmanTable&& other) = default;
|
||||
|
||||
// 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()`
|
||||
|
@ -770,6 +804,7 @@ struct GenericHuffmanTable {
|
|||
size_t length() const;
|
||||
|
||||
struct Iterator {
|
||||
explicit Iterator(typename SingleEntryHuffmanTable<T>::Iterator&&);
|
||||
explicit Iterator(typename SingleLookupHuffmanTable<T>::Iterator&&);
|
||||
explicit Iterator(typename TwoLookupsHuffmanTable<T>::Iterator&&);
|
||||
explicit Iterator(typename ThreeLookupsHuffmanTable<T>::Iterator&&);
|
||||
|
@ -781,7 +816,8 @@ struct GenericHuffmanTable {
|
|||
bool operator!=(const Iterator& other) const;
|
||||
|
||||
private:
|
||||
mozilla::Variant<typename SingleLookupHuffmanTable<T>::Iterator,
|
||||
mozilla::Variant<typename SingleEntryHuffmanTable<T>::Iterator,
|
||||
typename SingleLookupHuffmanTable<T>::Iterator,
|
||||
typename TwoLookupsHuffmanTable<T>::Iterator,
|
||||
typename ThreeLookupsHuffmanTable<T>::Iterator>
|
||||
implementation;
|
||||
|
@ -805,8 +841,9 @@ struct GenericHuffmanTable {
|
|||
HuffmanEntry<const T*> lookup(HuffmanLookup key) const;
|
||||
|
||||
private:
|
||||
mozilla::Variant<SingleLookupHuffmanTable<T>, TwoLookupsHuffmanTable<T>,
|
||||
ThreeLookupsHuffmanTable<T>, HuffmanTableUnreachable>
|
||||
mozilla::Variant<SingleEntryHuffmanTable<T>, SingleLookupHuffmanTable<T>,
|
||||
TwoLookupsHuffmanTable<T>, ThreeLookupsHuffmanTable<T>,
|
||||
HuffmanTableUnreachable>
|
||||
implementation;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче