Bug 1581875 - Renaming HuffmanTableImplementationXXXX;r=arai

Depends on D46454

Differential Revision: https://phabricator.services.mozilla.com/D46455

--HG--
extra : moz-landing-system : lando
This commit is contained in:
David Teller 2019-09-27 11:08:39 +00:00
parent 57edd22b24
commit 0c5855b4e3
2 changed files with 155 additions and 169 deletions

View File

@ -1630,147 +1630,139 @@ FlatHuffmanKey::FlatHuffmanKey(const HuffmanKey* key)
// ---- Implementation of Huffman Tables
template <typename T>
HuffmanTableImplementationGeneric<T>::Iterator::Iterator(
typename HuffmanTableImplementationSaturated<T>::Iterator&& iterator)
GenericHuffmanTable<T>::Iterator::Iterator(
typename SingleLookupHuffmanTable<T>::Iterator&& iterator)
: implementation(std::move(iterator)) {}
template <typename T>
HuffmanTableImplementationGeneric<T>::Iterator::Iterator(
typename HuffmanTableImplementationMap<T>::Iterator&& iterator)
GenericHuffmanTable<T>::Iterator::Iterator(
typename MapBasedHuffmanTable<T>::Iterator&& iterator)
: implementation(std::move(iterator)) {}
template <typename T>
void HuffmanTableImplementationGeneric<T>::Iterator::operator++() {
void GenericHuffmanTable<T>::Iterator::operator++() {
implementation.match(
[](typename HuffmanTableImplementationSaturated<T>::Iterator& iterator) {
[](typename SingleLookupHuffmanTable<T>::Iterator& iterator) {
iterator.operator++();
},
[](typename HuffmanTableImplementationMap<T>::Iterator& iterator) {
[](typename MapBasedHuffmanTable<T>::Iterator& iterator) {
iterator.operator++();
});
}
template <typename T>
bool HuffmanTableImplementationGeneric<T>::Iterator::operator==(
const HuffmanTableImplementationGeneric<T>::Iterator& other) const {
bool GenericHuffmanTable<T>::Iterator::operator==(
const GenericHuffmanTable<T>::Iterator& other) const {
return implementation.match(
[other](const typename HuffmanTableImplementationSaturated<T>::Iterator&
iterator) {
[other](const typename SingleLookupHuffmanTable<T>::Iterator& iterator) {
return iterator ==
other.implementation.template as<
typename HuffmanTableImplementationSaturated<T>::Iterator>();
typename SingleLookupHuffmanTable<T>::Iterator>();
},
[other](
const typename HuffmanTableImplementationMap<T>::Iterator& iterator) {
[other](const typename MapBasedHuffmanTable<T>::Iterator& iterator) {
return iterator ==
other.implementation.template as<
typename HuffmanTableImplementationMap<T>::Iterator>();
other.implementation
.template as<typename MapBasedHuffmanTable<T>::Iterator>();
});
}
template <typename T>
bool HuffmanTableImplementationGeneric<T>::Iterator::operator!=(
const HuffmanTableImplementationGeneric<T>::Iterator& other) const {
bool GenericHuffmanTable<T>::Iterator::operator!=(
const GenericHuffmanTable<T>::Iterator& other) const {
return implementation.match(
[other](const typename HuffmanTableImplementationSaturated<T>::Iterator&
iterator) {
[other](const typename SingleLookupHuffmanTable<T>::Iterator& iterator) {
return iterator !=
other.implementation.template as<
typename HuffmanTableImplementationSaturated<T>::Iterator>();
typename SingleLookupHuffmanTable<T>::Iterator>();
},
[other](
const typename HuffmanTableImplementationMap<T>::Iterator& iterator) {
[other](const typename MapBasedHuffmanTable<T>::Iterator& iterator) {
return iterator !=
other.implementation.template as<
typename HuffmanTableImplementationMap<T>::Iterator>();
other.implementation
.template as<typename MapBasedHuffmanTable<T>::Iterator>();
});
}
template <typename T>
const T* HuffmanTableImplementationGeneric<T>::Iterator::operator*() const {
const T* GenericHuffmanTable<T>::Iterator::operator*() const {
return implementation.match(
[](const typename HuffmanTableImplementationSaturated<T>::Iterator&
iterator) { return iterator.operator*(); },
[](const typename HuffmanTableImplementationMap<T>::Iterator& iterator) {
[](const typename SingleLookupHuffmanTable<T>::Iterator& iterator) {
return iterator.operator*();
},
[](const typename MapBasedHuffmanTable<T>::Iterator& iterator) {
return iterator.operator*();
});
}
template <typename T>
HuffmanTableImplementationGeneric<T>::HuffmanTableImplementationGeneric(
JSContext*)
GenericHuffmanTable<T>::GenericHuffmanTable(JSContext*)
: implementation(HuffmanTableUnreachable{}) {}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationGeneric<T>::initComplete() {
JS::Result<Ok> GenericHuffmanTable<T>::initComplete() {
return this->implementation.match(
[](HuffmanTableImplementationSaturated<T>& implementation) -> JS::Result<Ok> {
[](SingleLookupHuffmanTable<T>& implementation) {
return implementation.initComplete();
},
[](HuffmanTableImplementationMap<T>& implementation) -> JS::Result<Ok> {
[](MapBasedHuffmanTable<T>& implementation) {
return implementation.initComplete();
},
[](HuffmanTableUnreachable&) -> JS::Result<Ok> {
MOZ_CRASH("HuffmanTableImplementationGeneric is unitialized!");
return Ok();
[](HuffmanTableUnreachable&) {
MOZ_CRASH("GenericHuffmanTable is unitialized!");
});
}
template <typename T>
typename HuffmanTableImplementationGeneric<T>::Iterator
HuffmanTableImplementationGeneric<T>::begin() const {
typename GenericHuffmanTable<T>::Iterator GenericHuffmanTable<T>::begin()
const {
return this->implementation.match(
[](const HuffmanTableImplementationSaturated<T>& implementation)
-> HuffmanTableImplementationGeneric<T>::Iterator {
[](const SingleLookupHuffmanTable<T>& implementation)
-> GenericHuffmanTable<T>::Iterator {
return Iterator(implementation.begin());
},
[](const HuffmanTableImplementationMap<T>& implementation)
-> HuffmanTableImplementationGeneric<T>::Iterator {
[](const MapBasedHuffmanTable<T>& implementation)
-> GenericHuffmanTable<T>::Iterator {
return Iterator(implementation.begin());
},
[](const HuffmanTableUnreachable&)
-> HuffmanTableImplementationGeneric<T>::Iterator {
MOZ_CRASH("HuffmanTableImplementationGeneric is unitialized!");
[](const HuffmanTableUnreachable&) -> GenericHuffmanTable<T>::Iterator {
MOZ_CRASH("GenericHuffmanTable is unitialized!");
});
}
template <typename T>
typename HuffmanTableImplementationGeneric<T>::Iterator
HuffmanTableImplementationGeneric<T>::end() const {
typename GenericHuffmanTable<T>::Iterator GenericHuffmanTable<T>::end() const {
return this->implementation.match(
[](const HuffmanTableImplementationSaturated<T>& implementation)
-> HuffmanTableImplementationGeneric<T>::Iterator {
[](const SingleLookupHuffmanTable<T>& implementation)
-> GenericHuffmanTable<T>::Iterator {
return Iterator(implementation.end());
},
[](const HuffmanTableImplementationMap<T>& implementation)
-> HuffmanTableImplementationGeneric<T>::Iterator {
[](const MapBasedHuffmanTable<T>& implementation)
-> GenericHuffmanTable<T>::Iterator {
return Iterator(implementation.end());
},
[](const HuffmanTableUnreachable&)
-> HuffmanTableImplementationGeneric<T>::Iterator {
MOZ_CRASH("HuffmanTableImplementationGeneric is unitialized!");
[](const HuffmanTableUnreachable&) -> GenericHuffmanTable<T>::Iterator {
MOZ_CRASH("GenericHuffmanTable is unitialized!");
});
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationGeneric<T>::initWithSingleValue(
JSContext* cx, T&& value) {
JS::Result<Ok> GenericHuffmanTable<T>::initWithSingleValue(JSContext* cx,
T&& value) {
// Only one value: use HuffmanImplementationSaturated
MOZ_ASSERT(this->implementation.template is<
HuffmanTableUnreachable>()); // Make sure that we're initializing.
this->implementation = {
mozilla::VariantType<HuffmanTableImplementationSaturated<T>>{}, cx};
this->implementation = {mozilla::VariantType<SingleLookupHuffmanTable<T>>{},
cx};
MOZ_TRY(
this->implementation.template as<HuffmanTableImplementationSaturated<T>>()
.initWithSingleValue(cx, std::move(value)));
MOZ_TRY(this->implementation.template as<SingleLookupHuffmanTable<T>>()
.initWithSingleValue(cx, std::move(value)));
return Ok();
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationGeneric<T>::initStart(
JSContext* cx, size_t numberOfSymbols, uint8_t maxBitLength) {
JS::Result<Ok> GenericHuffmanTable<T>::initStart(JSContext* cx,
size_t numberOfSymbols,
uint8_t maxBitLength) {
MOZ_ASSERT(this->implementation.template is<
HuffmanTableUnreachable>()); // Make sure that we're initializing.
if (
@ -1780,60 +1772,60 @@ JS::Result<Ok> HuffmanTableImplementationGeneric<T>::initStart(
// If there are too many symbols, don't put it in a saturated table
// as indices wouldn't fit into `InternalIndex` .
numberOfSymbols >
mozilla::MaxValue<typename HuffmanTableImplementationSaturated<
T>::InternalIndex>::value) {
this->implementation = {
mozilla::VariantType<HuffmanTableImplementationMap<T>>{}, cx};
MOZ_TRY(this->implementation.template as<HuffmanTableImplementationMap<T>>()
.initStart(cx, numberOfSymbols, maxBitLength));
mozilla::MaxValue<
typename SingleLookupHuffmanTable<T>::InternalIndex>::value) {
this->implementation = {mozilla::VariantType<MapBasedHuffmanTable<T>>{},
cx};
MOZ_TRY(
this->implementation.template as<MapBasedHuffmanTable<T>>().initStart(
cx, numberOfSymbols, maxBitLength));
} else {
this->implementation = {
mozilla::VariantType<HuffmanTableImplementationSaturated<T>>{}, cx};
MOZ_TRY(this->implementation
.template as<HuffmanTableImplementationSaturated<T>>()
this->implementation = {mozilla::VariantType<SingleLookupHuffmanTable<T>>{},
cx};
MOZ_TRY(this->implementation.template as<SingleLookupHuffmanTable<T>>()
.initStart(cx, numberOfSymbols, maxBitLength));
}
return Ok();
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationGeneric<T>::addSymbol(
uint32_t bits, uint8_t bitLength, T&& value) {
JS::Result<Ok> GenericHuffmanTable<T>::addSymbol(uint32_t bits,
uint8_t bitLength, T&& value) {
return this->implementation.match(
[bits, bitLength, value = std::move(value)](
HuffmanTableImplementationSaturated<T>&
SingleLookupHuffmanTable<T>&
implementation) mutable /* discard implicit const */
-> JS::Result<Ok> {
return implementation.addSymbol(bits, bitLength, std::move(value));
},
[bits, bitLength, value = std::move(value)](
HuffmanTableImplementationMap<T>&
MapBasedHuffmanTable<T>&
implementation) mutable /* discard implicit const */
-> JS::Result<Ok> {
return implementation.addSymbol(bits, bitLength, std::move(value));
},
[](HuffmanTableUnreachable&) -> JS::Result<Ok> {
MOZ_CRASH("HuffmanTableImplementationGeneric is unitialized!");
MOZ_CRASH("GenericHuffmanTable is unitialized!");
return Ok();
});
}
template <typename T>
HuffmanEntry<const T*> HuffmanTableImplementationGeneric<T>::lookup(
HuffmanEntry<const T*> GenericHuffmanTable<T>::lookup(
HuffmanLookup lookup) const {
return this->implementation.match(
[lookup](const HuffmanTableImplementationSaturated<T>& implementation)
[lookup](const SingleLookupHuffmanTable<T>& implementation)
-> HuffmanEntry<const T*> { return implementation.lookup(lookup); },
[lookup](const HuffmanTableImplementationMap<T>& implementation)
[lookup](const MapBasedHuffmanTable<T>& implementation)
-> HuffmanEntry<const T*> { return implementation.lookup(lookup); },
[](const HuffmanTableUnreachable&) -> HuffmanEntry<const T*> {
MOZ_CRASH("HuffmanTableImplementationGeneric is unitialized!");
MOZ_CRASH("GenericHuffmanTable is unitialized!");
});
}
template <typename T, int N>
JS::Result<Ok> HuffmanTableImplementationNaive<T, N>::initWithSingleValue(
JSContext* cx, T&& value) {
JS::Result<Ok> NaiveHuffmanTable<T, N>::initWithSingleValue(JSContext* cx,
T&& value) {
MOZ_ASSERT(values.empty()); // Make sure that we're initializing.
if (!values.append(HuffmanEntry<T>(0, 0, std::move(value)))) {
return cx->alreadyReportedError();
@ -1842,8 +1834,9 @@ JS::Result<Ok> HuffmanTableImplementationNaive<T, N>::initWithSingleValue(
}
template <typename T, int N>
JS::Result<Ok> HuffmanTableImplementationNaive<T, N>::initStart(
JSContext* cx, size_t numberOfSymbols, uint8_t) {
JS::Result<Ok> NaiveHuffmanTable<T, N>::initStart(JSContext* cx,
size_t numberOfSymbols,
uint8_t) {
MOZ_ASSERT(values.empty()); // Make sure that we're initializing.
if (!values.initCapacity(numberOfSymbols)) {
return cx->alreadyReportedError();
@ -1852,14 +1845,15 @@ JS::Result<Ok> HuffmanTableImplementationNaive<T, N>::initStart(
}
template <typename T, int N>
JS::Result<Ok> HuffmanTableImplementationNaive<T, N>::initComplete() {
JS::Result<Ok> NaiveHuffmanTable<T, N>::initComplete() {
MOZ_ASSERT(values.length() <= N);
return Ok();
}
template <typename T, int N>
JS::Result<Ok> HuffmanTableImplementationNaive<T, N>::addSymbol(
uint32_t bits, uint8_t bitLength, T&& value) {
JS::Result<Ok> NaiveHuffmanTable<T, N>::addSymbol(uint32_t bits,
uint8_t bitLength,
T&& value) {
MOZ_ASSERT(bitLength != 0,
"Adding a symbol with a bitLength of 0 doesn't make sense.");
MOZ_ASSERT(values.empty() || values.back().key.bitLength <= bitLength,
@ -1873,7 +1867,7 @@ JS::Result<Ok> HuffmanTableImplementationNaive<T, N>::addSymbol(
}
template <typename T, int N>
HuffmanEntry<const T*> HuffmanTableImplementationNaive<T, N>::lookup(
HuffmanEntry<const T*> NaiveHuffmanTable<T, N>::lookup(
HuffmanLookup key) const {
// This current implementation is O(length) and designed mostly for testing.
// Future versions will presumably adapt the underlying data structure to
@ -1897,8 +1891,8 @@ HuffmanEntry<const T*> HuffmanTableImplementationNaive<T, N>::lookup(
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationMap<T>::initWithSingleValue(
JSContext* cx, T&& value) {
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 (!values.put(FlatHuffmanKey(key), std::move(value)) || !keys.append(key)) {
@ -1909,8 +1903,9 @@ JS::Result<Ok> HuffmanTableImplementationMap<T>::initWithSingleValue(
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationMap<T>::initStart(
JSContext* cx, size_t numberOfSymbols, uint8_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 (!values.reserve(numberOfSymbols) || !keys.reserve(numberOfSymbols)) {
ReportOutOfMemory(cx);
@ -1920,7 +1915,7 @@ JS::Result<Ok> HuffmanTableImplementationMap<T>::initStart(
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationMap<T>::initComplete() {
JS::Result<Ok> MapBasedHuffmanTable<T>::initComplete() {
#if DEBUG
// Check that there is a bijection between `keys` and `values`.
// 1. Injection.
@ -1936,9 +1931,9 @@ JS::Result<Ok> HuffmanTableImplementationMap<T>::initComplete() {
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationMap<T>::addSymbol(uint32_t bits,
uint8_t bitLength,
T&& value) {
JS::Result<Ok> MapBasedHuffmanTable<T>::addSymbol(uint32_t bits,
uint8_t bitLength,
T&& value) {
MOZ_ASSERT(bitLength != 0,
"Adding a symbol with a bitLength of 0 doesn't make sense.");
MOZ_ASSERT_IF(bitLength != 32 /* >> 32 is UB */, bits >> bitLength == 0);
@ -1952,7 +1947,7 @@ JS::Result<Ok> HuffmanTableImplementationMap<T>::addSymbol(uint32_t bits,
}
template <typename T>
HuffmanEntry<const T*> HuffmanTableImplementationMap<T>::lookup(
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);
@ -1969,35 +1964,34 @@ HuffmanEntry<const T*> HuffmanTableImplementationMap<T>::lookup(
}
template <typename T>
HuffmanTableImplementationSaturated<T>::Iterator::Iterator(
const HuffmanEntry<T>* position)
SingleLookupHuffmanTable<T>::Iterator::Iterator(const HuffmanEntry<T>* position)
: position(position) {}
template <typename T>
void HuffmanTableImplementationSaturated<T>::Iterator::operator++() {
void SingleLookupHuffmanTable<T>::Iterator::operator++() {
position++;
}
template <typename T>
const T* HuffmanTableImplementationSaturated<T>::Iterator::operator*() const {
const T* SingleLookupHuffmanTable<T>::Iterator::operator*() const {
return &position->value;
}
template <typename T>
bool HuffmanTableImplementationSaturated<T>::Iterator::operator==(
bool SingleLookupHuffmanTable<T>::Iterator::operator==(
const Iterator& other) const {
return position == other.position;
}
template <typename T>
bool HuffmanTableImplementationSaturated<T>::Iterator::operator!=(
bool SingleLookupHuffmanTable<T>::Iterator::operator!=(
const Iterator& other) const {
return position != other.position;
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationSaturated<T>::initWithSingleValue(
JSContext* cx, T&& value) {
JS::Result<Ok> SingleLookupHuffmanTable<T>::initWithSingleValue(JSContext* cx,
T&& value) {
MOZ_ASSERT(values.empty()); // Make sure that we're initializing.
if (!values.emplaceBack(0, 0, std::move(value))) {
return cx->alreadyReportedError();
@ -2010,8 +2004,9 @@ JS::Result<Ok> HuffmanTableImplementationSaturated<T>::initWithSingleValue(
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationSaturated<T>::initStart(
JSContext* cx, size_t numberOfSymbols, uint8_t maxBitLength) {
JS::Result<Ok> SingleLookupHuffmanTable<T>::initStart(JSContext* cx,
size_t numberOfSymbols,
uint8_t maxBitLength) {
MOZ_ASSERT(maxBitLength <= MAX_BIT_LENGTH_IN_SATURATED_TABLE);
MOZ_ASSERT(values.empty()); // Make sure that we're initializing.
@ -2033,7 +2028,7 @@ JS::Result<Ok> HuffmanTableImplementationSaturated<T>::initStart(
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationSaturated<T>::initComplete() {
JS::Result<Ok> SingleLookupHuffmanTable<T>::initComplete() {
// Double-check that we've initialized properly.
MOZ_ASSERT(this->maxBitLength <= MAX_CODE_BIT_LENGTH);
#ifdef DEBUG
@ -2055,8 +2050,9 @@ JS::Result<Ok> HuffmanTableImplementationSaturated<T>::initComplete() {
}
template <typename T>
JS::Result<Ok> HuffmanTableImplementationSaturated<T>::addSymbol(
uint32_t bits, uint8_t bitLength, T&& value) {
JS::Result<Ok> SingleLookupHuffmanTable<T>::addSymbol(uint32_t bits,
uint8_t bitLength,
T&& value) {
MOZ_ASSERT(bitLength != 0,
"Adding a symbol with a bitLength of 0 doesn't make sense.");
MOZ_ASSERT(values.empty() || values.back().key.bitLength <= bitLength,
@ -2100,7 +2096,7 @@ JS::Result<Ok> HuffmanTableImplementationSaturated<T>::addSymbol(
}
template <typename T>
HuffmanEntry<const T*> HuffmanTableImplementationSaturated<T>::lookup(
HuffmanEntry<const T*> SingleLookupHuffmanTable<T>::lookup(
HuffmanLookup key) const {
// Take the `maxBitLength` highest weight bits of `key`.
// In the documentation of `addSymbol`, this is

View File

@ -182,10 +182,10 @@ enum class Nullable {
// lookup. Performance-wise, this implementation only makes sense for
// very short tables.
template <typename T, int N = HUFFMAN_TABLE_DEFAULT_INLINE_BUFFER_LENGTH>
class HuffmanTableImplementationNaive {
class NaiveHuffmanTable {
public:
explicit HuffmanTableImplementationNaive(JSContext* cx) : values(cx) {}
HuffmanTableImplementationNaive(HuffmanTableImplementationNaive&& other)
explicit NaiveHuffmanTable(JSContext* cx) : values(cx) {}
NaiveHuffmanTable(NaiveHuffmanTable&& other) noexcept
: values(std::move(other.values)) {}
// Initialize a Huffman table containing a single value.
@ -203,8 +203,8 @@ class HuffmanTableImplementationNaive {
// Add a symbol to a value.
JS::Result<Ok> addSymbol(uint32_t bits, uint8_t bits_length, T&& value);
HuffmanTableImplementationNaive() = delete;
HuffmanTableImplementationNaive(HuffmanTableImplementationNaive&) = delete;
NaiveHuffmanTable() = delete;
NaiveHuffmanTable(NaiveHuffmanTable&) = delete;
// Lookup a value in the table.
//
@ -232,7 +232,7 @@ class HuffmanTableImplementationNaive {
};
// An implementation of Huffman Tables as a hash map. Space-Efficient,
// faster than HuffmanTableImplementationNaive for large tables but not terribly
// faster than NaiveHuffmanTable for large tables but not terribly
// fast, either.
//
// Complexity:
@ -248,11 +248,10 @@ class HuffmanTableImplementationNaive {
// - On an invalid file, the number of lookups is also bounded by
// `MAX_CODE_BIT_LENGTH`.
template <typename T>
class HuffmanTableImplementationMap {
class MapBasedHuffmanTable {
public:
explicit HuffmanTableImplementationMap(JSContext* cx)
: values(cx), keys(cx) {}
HuffmanTableImplementationMap(HuffmanTableImplementationMap&& other) noexcept
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.
@ -270,8 +269,8 @@ class HuffmanTableImplementationMap {
JS::Result<Ok> initComplete();
HuffmanTableImplementationMap() = delete;
HuffmanTableImplementationMap(HuffmanTableImplementationMap&) = delete;
MapBasedHuffmanTable() = delete;
MapBasedHuffmanTable(MapBasedHuffmanTable&) = delete;
// Lookup a value in the table.
//
@ -335,7 +334,7 @@ class HuffmanTableImplementationMap {
//
// # Space complexity
//
// After initialization, a `HuffmanTableImplementationSaturated`
// After initialization, a `SingleLookupHuffmanTable`
// requires O(2 ^ max bit length in the table) space:
//
// - A vector `values` containing one entry per symbol.
@ -398,12 +397,11 @@ class HuffmanTableImplementationMap {
// symbols bit length, and one (`saturated`) with indices into that
// array.
template <typename T>
class HuffmanTableImplementationSaturated {
class SingleLookupHuffmanTable {
public:
explicit HuffmanTableImplementationSaturated(JSContext* cx)
explicit SingleLookupHuffmanTable(JSContext* cx)
: values(cx), saturated(cx), maxBitLength(-1) {}
HuffmanTableImplementationSaturated(
HuffmanTableImplementationSaturated&& other) = default;
SingleLookupHuffmanTable(SingleLookupHuffmanTable&& other) noexcept = default;
// Initialize a Huffman table containing a single value.
JS::Result<Ok> initWithSingleValue(JSContext* cx, T&& value);
@ -420,9 +418,8 @@ class HuffmanTableImplementationSaturated {
// Add a `(bit, bits_length) => value` mapping.
JS::Result<Ok> addSymbol(uint32_t bits, uint8_t bits_length, T&& value);
HuffmanTableImplementationSaturated() = delete;
HuffmanTableImplementationSaturated(HuffmanTableImplementationSaturated&) =
delete;
SingleLookupHuffmanTable() = delete;
SingleLookupHuffmanTable(SingleLookupHuffmanTable&) = delete;
// Lookup a value in the table.
//
@ -486,16 +483,16 @@ class HuffmanTableImplementationSaturated {
// states that may not be reached.
//
// Part of variants `HuffmanTableValue`, `HuffmanTableListLength` and
// `HuffmanTableImplementationGeneric::implementation`.
// `GenericHuffmanTable::implementation`.
struct HuffmanTableUnreachable {};
// Generic implementation of Huffman tables.
//
//
template <typename T>
struct HuffmanTableImplementationGeneric {
explicit HuffmanTableImplementationGeneric(JSContext* cx);
explicit HuffmanTableImplementationGeneric() = delete;
struct GenericHuffmanTable {
explicit GenericHuffmanTable(JSContext* cx);
explicit GenericHuffmanTable() = delete;
// Initialize a Huffman table containing a single value.
JS::Result<Ok> initWithSingleValue(JSContext* cx, T&& value);
@ -516,9 +513,8 @@ struct HuffmanTableImplementationGeneric {
size_t length() const;
struct Iterator {
explicit Iterator(
typename HuffmanTableImplementationSaturated<T>::Iterator&&);
explicit Iterator(typename HuffmanTableImplementationMap<T>::Iterator&&);
explicit Iterator(typename SingleLookupHuffmanTable<T>::Iterator&&);
explicit Iterator(typename MapBasedHuffmanTable<T>::Iterator&&);
Iterator(Iterator&&) = default;
Iterator(const Iterator&) = default;
void operator++();
@ -527,8 +523,8 @@ struct HuffmanTableImplementationGeneric {
bool operator!=(const Iterator& other) const;
private:
mozilla::Variant<typename HuffmanTableImplementationSaturated<T>::Iterator,
typename HuffmanTableImplementationMap<T>::Iterator>
mozilla::Variant<typename SingleLookupHuffmanTable<T>::Iterator,
typename MapBasedHuffmanTable<T>::Iterator>
implementation;
};
@ -547,8 +543,8 @@ struct HuffmanTableImplementationGeneric {
HuffmanEntry<const T*> lookup(HuffmanLookup key) const;
private:
mozilla::Variant<HuffmanTableImplementationSaturated<T>,
HuffmanTableImplementationMap<T>, HuffmanTableUnreachable>
mozilla::Variant<SingleLookupHuffmanTable<T>, MapBasedHuffmanTable<T>,
HuffmanTableUnreachable>
implementation;
};
@ -563,41 +559,37 @@ struct HuffmanTableInitializing {};
// These classes are all parts of variant `HuffmanTableValue`.
struct HuffmanTableExplicitSymbolsF64
: HuffmanTableImplementationGeneric<double> {
struct HuffmanTableExplicitSymbolsF64 : GenericHuffmanTable<double> {
using Contents = double;
explicit HuffmanTableExplicitSymbolsF64(JSContext* cx)
: HuffmanTableImplementationGeneric(cx) {}
: GenericHuffmanTable(cx) {}
};
struct HuffmanTableExplicitSymbolsU32
: HuffmanTableImplementationGeneric<uint32_t> {
struct HuffmanTableExplicitSymbolsU32 : GenericHuffmanTable<uint32_t> {
using Contents = uint32_t;
explicit HuffmanTableExplicitSymbolsU32(JSContext* cx)
: HuffmanTableImplementationGeneric(cx) {}
: GenericHuffmanTable(cx) {}
};
struct HuffmanTableIndexedSymbolsSum
: HuffmanTableImplementationGeneric<BinASTKind> {
struct HuffmanTableIndexedSymbolsSum : GenericHuffmanTable<BinASTKind> {
using Contents = BinASTKind;
explicit HuffmanTableIndexedSymbolsSum(JSContext* cx)
: HuffmanTableImplementationGeneric(cx) {}
: GenericHuffmanTable(cx) {}
};
struct HuffmanTableIndexedSymbolsBool
: HuffmanTableImplementationNaive<bool, 2> {
struct HuffmanTableIndexedSymbolsBool : NaiveHuffmanTable<bool, 2> {
using Contents = bool;
explicit HuffmanTableIndexedSymbolsBool(JSContext* cx)
: HuffmanTableImplementationNaive(cx) {}
: NaiveHuffmanTable(cx) {}
};
// A Huffman table that may only ever contain two values:
// `BinASTKind::_Null` and another `BinASTKind`.
struct HuffmanTableIndexedSymbolsMaybeInterface
: HuffmanTableImplementationNaive<BinASTKind, 2> {
: NaiveHuffmanTable<BinASTKind, 2> {
using Contents = BinASTKind;
explicit HuffmanTableIndexedSymbolsMaybeInterface(JSContext* cx)
: HuffmanTableImplementationNaive(cx) {}
: NaiveHuffmanTable(cx) {}
// `true` if this table only contains values for `null`.
bool isAlwaysNull() const {
@ -614,24 +606,23 @@ struct HuffmanTableIndexedSymbolsMaybeInterface
};
struct HuffmanTableIndexedSymbolsStringEnum
: HuffmanTableImplementationGeneric<BinASTVariant> {
: GenericHuffmanTable<BinASTVariant> {
using Contents = BinASTVariant;
explicit HuffmanTableIndexedSymbolsStringEnum(JSContext* cx)
: HuffmanTableImplementationGeneric(cx) {}
: GenericHuffmanTable(cx) {}
};
struct HuffmanTableIndexedSymbolsLiteralString
: HuffmanTableImplementationGeneric<JSAtom*> {
struct HuffmanTableIndexedSymbolsLiteralString : GenericHuffmanTable<JSAtom*> {
using Contents = JSAtom*;
explicit HuffmanTableIndexedSymbolsLiteralString(JSContext* cx)
: HuffmanTableImplementationGeneric(cx) {}
: GenericHuffmanTable(cx) {}
};
struct HuffmanTableIndexedSymbolsOptionalLiteralString
: HuffmanTableImplementationGeneric<JSAtom*> {
: GenericHuffmanTable<JSAtom*> {
using Contents = JSAtom*;
explicit HuffmanTableIndexedSymbolsOptionalLiteralString(JSContext* cx)
: HuffmanTableImplementationGeneric(cx) {}
: GenericHuffmanTable(cx) {}
};
// A single Huffman table, used for values.
@ -644,11 +635,10 @@ using HuffmanTableValue = mozilla::Variant<
HuffmanTableIndexedSymbolsLiteralString,
HuffmanTableIndexedSymbolsOptionalLiteralString>;
struct HuffmanTableExplicitSymbolsListLength
: HuffmanTableImplementationGeneric<uint32_t> {
struct HuffmanTableExplicitSymbolsListLength : GenericHuffmanTable<uint32_t> {
using Contents = uint32_t;
explicit HuffmanTableExplicitSymbolsListLength(JSContext* cx)
: HuffmanTableImplementationGeneric(cx) {}
: GenericHuffmanTable(cx) {}
};
// A single Huffman table, specialized for list lengths.