From d83d751443051e788be05d87b8bee0d5aed83703 Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Fri, 2 Jan 2026 15:30:41 +0100 Subject: [PATCH] Matroska: Fix build with older macOS and 32-bit Android compilers When building for macOS < 10.14, the API for std::optional and std::variant is restricted error: 'value' is unavailable: introduced in macOS 10.14 error: 'get<..>' is unavailable: introduced in macOS 10.14 There was also an issue with Android armeabi-v7a where long is not 64 bit and a static assertion failed. --- taglib/matroska/ebml/ebmlelement.cpp | 2 +- taglib/matroska/ebml/ebmlfloatelement.cpp | 12 +++++--- taglib/matroska/ebml/ebmlutils.cpp | 37 ++++++++--------------- taglib/matroska/ebml/ebmlutils.h | 6 ++-- taglib/matroska/matroskacues.cpp | 20 +++++++----- taglib/matroska/matroskasimpletag.cpp | 6 ++-- 6 files changed, 40 insertions(+), 43 deletions(-) diff --git a/taglib/matroska/ebml/ebmlelement.cpp b/taglib/matroska/ebml/ebmlelement.cpp index 691b6479..351e2870 100644 --- a/taglib/matroska/ebml/ebmlelement.cpp +++ b/taglib/matroska/ebml/ebmlelement.cpp @@ -52,7 +52,7 @@ std::unique_ptr EBML::Element::factory(File &file) } // Get the size length and data length - const auto &[sizeLength, dataSize] = readVINT(file); + const auto &[sizeLength, dataSize] = readVINT(file); if(!sizeLength) return nullptr; diff --git a/taglib/matroska/ebml/ebmlfloatelement.cpp b/taglib/matroska/ebml/ebmlfloatelement.cpp index 1460de8e..00ea199d 100644 --- a/taglib/matroska/ebml/ebmlfloatelement.cpp +++ b/taglib/matroska/ebml/ebmlfloatelement.cpp @@ -52,10 +52,12 @@ EBML::FloatElement::FloatVariantType EBML::FloatElement::getValue() const double EBML::FloatElement::getValueAsDouble(double defaultValue) const { if(std::holds_alternative(value)) { - return std::get(value); + // get_if() used instead of get() to support restricted compilers + return *std::get_if(&value); } if(std::holds_alternative(value)) { - return std::get(value); + // get_if() used instead of get() to support restricted compilers + return *std::get_if(&value); } return defaultValue; } @@ -93,10 +95,12 @@ ByteVector EBML::FloatElement::render() { ByteVector data; if(std::holds_alternative(value)) { - data = ByteVector::fromFloat64BE(std::get(value)); + // get_if() used instead of get() to support restricted compilers + data = ByteVector::fromFloat64BE(*std::get_if(&value)); } else if(std::holds_alternative(value)) { - data = ByteVector::fromFloat32BE(std::get(value)); + // get_if() used instead of get() to support restricted compilers + data = ByteVector::fromFloat32BE(*std::get_if(&value)); } ByteVector buffer = renderId(); buffer.append(renderVINT(data.size(), 0)); diff --git a/taglib/matroska/ebml/ebmlutils.cpp b/taglib/matroska/ebml/ebmlutils.cpp index e3baf7ee..60f05155 100644 --- a/taglib/matroska/ebml/ebmlutils.cpp +++ b/taglib/matroska/ebml/ebmlutils.cpp @@ -71,33 +71,25 @@ namespace TagLib::EBML { template unsigned int VINTSizeLength<8>(uint8_t firstByte); } -template -std::pair EBML::readVINT(File &file) +std::pair EBML::readVINT(File &file) { - static_assert(sizeof(T) == 8); auto buffer = file.readBlock(1); if(buffer.size() != 1) { debug("Failed to read VINT size"); return {0, 0}; } - unsigned int nb_bytes = VINTSizeLength<8>(*buffer.begin()); - if(!nb_bytes) + unsigned int numBytes = VINTSizeLength<8>(*buffer.begin()); + if(!numBytes) return {0, 0}; - if(nb_bytes > 1) - buffer.append(file.readBlock(nb_bytes - 1)); - const int bitsToShift = static_cast(sizeof(T) * 8) - 7 * nb_bytes; - offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift; - return { nb_bytes, static_cast(buffer.toLongLong(true)) & mask }; + if(numBytes > 1) + buffer.append(file.readBlock(numBytes - 1)); + const int bitsToShift = static_cast(sizeof(uint64_t) * 8) - 7 * numBytes; + const uint64_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift; + return { numBytes, buffer.toULongLong(true) & mask }; } -namespace TagLib::EBML { - template std::pair readVINT(File &file); - template std::pair readVINT(File &file); -} - -template -std::pair EBML::parseVINT(const ByteVector &buffer) +std::pair EBML::parseVINT(const ByteVector &buffer) { if(buffer.isEmpty()) return {0, 0}; @@ -106,14 +98,9 @@ std::pair EBML::parseVINT(const ByteVector &buffer) if(!numBytes) return {0, 0}; - const int bitsToShift = static_cast(sizeof(T) * 8) - 7 * numBytes; - offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift; - return { numBytes, static_cast(buffer.toLongLong(true)) & mask }; -} - -namespace TagLib::EBML { - template std::pair parseVINT(const ByteVector &buffer); - template std::pair parseVINT(const ByteVector &buffer); + const int bitsToShift = static_cast(sizeof(uint64_t) * 8) - 7 * numBytes; + const uint64_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift; + return { numBytes, buffer.toULongLong(true) & mask }; } ByteVector EBML::renderVINT(uint64_t number, int minSizeLength) diff --git a/taglib/matroska/ebml/ebmlutils.h b/taglib/matroska/ebml/ebmlutils.h index 7ad23157..4038e5b0 100644 --- a/taglib/matroska/ebml/ebmlutils.h +++ b/taglib/matroska/ebml/ebmlutils.h @@ -37,11 +37,9 @@ namespace TagLib { template unsigned int VINTSizeLength(uint8_t firstByte); - template - std::pair readVINT(File &file); + std::pair readVINT(File &file); - template - std::pair parseVINT(const ByteVector &buffer); + std::pair parseVINT(const ByteVector &buffer); ByteVector renderVINT(uint64_t number, int minSizeLength); diff --git a/taglib/matroska/matroskacues.cpp b/taglib/matroska/matroskacues.cpp index 2c4a4f63..c71f3fe0 100644 --- a/taglib/matroska/matroskacues.cpp +++ b/taglib/matroska/matroskacues.cpp @@ -66,28 +66,32 @@ ByteVector Matroska::Cues::renderInternal() // Relative position, optional if(cueTrack->getRelativePosition().has_value()) { auto relativePosition = EBML::make_unique_element(); - relativePosition->setValue(cueTrack->getRelativePosition().value()); + // operator*() used instead of value() to support restricted compilers + relativePosition->setValue(*cueTrack->getRelativePosition()); cueTrackElement->appendElement(std::move(relativePosition)); } // Duration, optional if(cueTrack->getDuration().has_value()) { auto duration = EBML::make_unique_element(); - duration->setValue(cueTrack->getDuration().value()); + // operator*() used instead of value() to support restricted compilers + duration->setValue(*cueTrack->getDuration()); cueTrackElement->appendElement(std::move(duration)); } // Block number, optional if(cueTrack->getBlockNumber().has_value()) { auto blockNumber = EBML::make_unique_element(); - blockNumber->setValue(cueTrack->getBlockNumber().value()); + // operator*() used instead of value() to support restricted compilers + blockNumber->setValue(*cueTrack->getBlockNumber()); cueTrackElement->appendElement(std::move(blockNumber)); } // Codec state, not in version 1 if(cueTrack->getCodecState().has_value()) { auto codecState = EBML::make_unique_element(); - codecState->setValue(cueTrack->getCodecState().value()); + // operator*() used instead of value() to support restricted compilers + codecState->setValue(*cueTrack->getCodecState()); cueTrackElement->appendElement(std::move(codecState)); } @@ -209,8 +213,9 @@ bool Matroska::CueTrack::isValid(TagLib::File &file, offset_t segmentDataOffset) debug("No cluster found at position"); return false; } - if(codecState.has_value() && codecState.value() != 0) { - file.seek(segmentDataOffset + codecState.value()); + if(codecState.has_value() && *codecState != 0) { + // operator*() used instead of value() to support restricted compilers + file.seek(segmentDataOffset + *codecState); if(EBML::Element::readId(file) != static_cast(EBML::Element::Id::MkCodecState)) { debug("No codec state found at position"); return false; @@ -296,8 +301,9 @@ bool Matroska::CueTrack::adjustOffset(offset_t offset, offset_t delta) clusterPosition += delta; ret = true; } + // operator*() used instead of value() to support restricted compilers if(offset_t codecStateValue; - codecState.has_value() && (codecStateValue = codecState.value()) != 0 && + codecState.has_value() && (codecStateValue = *codecState) != 0 && codecStateValue > offset) { codecState = codecStateValue + delta; ret = true; diff --git a/taglib/matroska/matroskasimpletag.cpp b/taglib/matroska/matroskasimpletag.cpp index 1eb9a381..cd9a57d5 100644 --- a/taglib/matroska/matroskasimpletag.cpp +++ b/taglib/matroska/matroskasimpletag.cpp @@ -126,7 +126,8 @@ Matroska::SimpleTag::ValueType Matroska::SimpleTag::type() const String Matroska::SimpleTag::toString() const { if(std::holds_alternative(d->value)) { - return std::get(d->value); + // get_if() used instead of get() to support restricted compilers + return *std::get_if(&d->value); } return {}; } @@ -134,7 +135,8 @@ String Matroska::SimpleTag::toString() const ByteVector Matroska::SimpleTag::toByteVector() const { if(std::holds_alternative(d->value)) { - return std::get(d->value); + // get_if() used instead of get() to support restricted compilers + return *std::get_if(&d->value); } return {}; }