Browse Source

adaptive: use standard <optional> even on macOS

Using value() potentially throws an exception that is not always
available on macOS.
Since XCode 16 it's considered available in all macOS, iOS, etc.

```
XCode 16.4+
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE
XCode 12.5-15.4
#   define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS                             \
        __attribute__((availability(macos,strict,introduced=10.13)))            \
        __attribute__((availability(ios,strict,introduced=12.0)))               \
        __attribute__((availability(tvos,strict,introduced=12.0)))              \
        __attribute__((availability(watchos,strict,introduced=5.0)))
XCode 11-12.2
#  define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS                             \
     __attribute__((availability(macosx,strict,introduced=10.14)))             \
     __attribute__((availability(ios,strict,introduced=12.0)))                 \
     __attribute__((availability(tvos,strict,introduced=12.0)))                \
     __attribute__((availability(watchos,strict,introduced=5.0)))
XCode 9.2
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
```

We never use the class directly, nor catch the error.
pull/188/head
Steve Lhomme 6 months ago
parent
commit
4b5d41f2c1
  1. 1
      modules/demux/Makefile.am
  2. 7
      modules/demux/adaptive/http/HTTPConnection.cpp
  3. 4
      modules/demux/adaptive/logic/BufferingLogic.hpp
  4. 5
      modules/demux/adaptive/playlist/BaseAdaptationSet.h
  5. 1
      modules/demux/adaptive/playlist/CommonAttributesElements.h
  6. 214
      modules/demux/adaptive/tools/Compatibility.hpp
  7. 4
      modules/demux/hls/playlist/Parser.cpp
  8. 4
      modules/demux/hls/playlist/Tags.cpp
  9. 5
      modules/demux/hls/playlist/Tags.hpp

1
modules/demux/Makefile.am

@ -407,7 +407,6 @@ libvlc_adaptive_la_SOURCES = \
demux/adaptive/Streams.cpp \
demux/adaptive/Streams.hpp \
demux/adaptive/Time.hpp \
demux/adaptive/tools/Compatibility.hpp \
demux/adaptive/tools/Conversions.hpp \
demux/adaptive/tools/Conversions.cpp \
demux/adaptive/tools/Debug.hpp \

7
modules/demux/adaptive/http/HTTPConnection.cpp

@ -26,7 +26,8 @@
#include "AuthStorage.hpp"
#include "../BlockStreamInterface.hpp"
#include "../plumbing/SourceStream.hpp"
#include "../tools/Compatibility.hpp"
#include <optional>
#include <vlc_stream.h>
#include <vlc_keystore.h>
@ -189,8 +190,8 @@ class adaptive::http::LibVLCHTTPSource : public adaptive::BlockStreamInterface
struct vlc_http_mgr *http_mgr;
BytesRange range;
struct vlc_http_resource *http_res;
adaptive::optional<std::string> username;
adaptive::optional<std::string> password;
std::optional<std::string> username;
std::optional<std::string> password;
ConnectionParams lastparams;
public:

4
modules/demux/adaptive/logic/BufferingLogic.hpp

@ -23,7 +23,7 @@
#include <vlc_common.h>
#include <vlc_tick.h>
#include "../tools/Compatibility.hpp"
#include <optional>
namespace adaptive
{
@ -61,7 +61,7 @@ namespace adaptive
vlc_tick_t userMinBuffering;
vlc_tick_t userMaxBuffering;
vlc_tick_t userLiveDelay;
optional<bool> userLowLatency;
std::optional<bool> userLowLatency;
};
class DefaultBufferingLogic : public AbstractBufferingLogic

5
modules/demux/adaptive/playlist/BaseAdaptationSet.h

@ -27,6 +27,7 @@
#include <vector>
#include <string>
#include <optional>
#include "CommonAttributesElements.h"
#include "SegmentInformation.hpp"
@ -68,8 +69,8 @@ namespace adaptive
Role role;
std::vector<BaseRepresentation *> representations;
std::string lang;
optional<bool> segmentAligned;
optional<bool> bitswitchAble;
std::optional<bool> segmentAligned;
std::optional<bool> bitswitchAble;
};
}
}

1
modules/demux/adaptive/playlist/CommonAttributesElements.h

@ -24,7 +24,6 @@
#ifndef COMMONATTRIBUTESELEMENTS_H
#define COMMONATTRIBUTESELEMENTS_H
#include "../tools/Compatibility.hpp"
#include "../tools/Properties.hpp"
#include "../tools/Macros.hpp"
#include <string>

214
modules/demux/adaptive/tools/Compatibility.hpp

@ -1,214 +0,0 @@
/*
* Compatibility.hpp
*****************************************************************************
* Copyright (C) 2025 - VideoLabs, VideoLAN and VLC Authors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef COMPATIBILITY_HPP
#define COMPATIBILITY_HPP
/* Provide std::optional compatibility for builds with c++17 or
incomplete/bogus c++17 with MacOS <= 10.13 and iOS < 12 */
#ifdef __APPLE__
# include <TargetConditionals.h>
# if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < 120000) || \
(TARGET_OS_MAC && __MAC_OS_X_VERSION_MIN_REQUIRED < 101400)
# define IOS_INCOMPLETE_CPP17
# endif
#endif
#if __cplusplus >= 201703L && !defined(IOS_INCOMPLETE_CPP17)
# include <optional>
#else
# include <utility>
# include <type_traits>
# include <stdexcept>
#endif
namespace adaptive
{
#if __cplusplus >= 201703L && !defined(IOS_INCOMPLETE_CPP17)
template <typename T>
using optional = std::optional<T>;
using nullopt_t = std::nullopt_t;
constexpr auto nullopt = std::nullopt;
using in_place_t = std::in_place_t;
constexpr auto in_place = std::in_place;
using bad_optional_access = std::bad_optional_access;
#else
struct nullopt_t {
explicit nullopt_t() = default;
};
constexpr nullopt_t nullopt{};
struct in_place_t {
explicit in_place_t() = default;
};
constexpr in_place_t in_place{};
class bad_optional_access : public std::exception {
public:
const char* what() const noexcept override {
return "Bad optional access";
}
};
template <typename T>
class optional
{
private:
alignas(T) unsigned char storage[sizeof(T)];
bool has_value_ = false;
T* ptr() noexcept
{
return reinterpret_cast<T*>(storage);
}
const T* ptr() const noexcept
{
return reinterpret_cast<const T*>(storage);
}
void destroy() noexcept(std::is_nothrow_destructible<T>::value)
{
if (has_value_)
{
ptr()->~T();
has_value_ = false;
}
}
public:
optional() noexcept = default;
optional(nullopt_t) noexcept : optional() {}
optional(const T& value) : has_value_(true)
{
new (storage) T(value);
}
optional(T&& value) : has_value_(true)
{
new (storage) T(std::move(value));
}
optional(optional&& other) noexcept(std::is_nothrow_move_constructible<T>::value)
: has_value_(other.has_value_) {
if (has_value_) { new (storage) T(std::move(*other.ptr())); other.destroy(); }
}
~optional() {destroy();}
optional& operator=(const optional& other)
{
if (this != &other)
{
destroy();
has_value_ = other.has_value_;
if (has_value_)
new (storage) T(*other.ptr());
}
return *this;
}
optional& operator=(optional&& other) noexcept(
std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_move_assignable<T>::value)
{
if (this != &other)
{
destroy();
has_value_ = other.has_value_;
if (has_value_)
{
new (storage) T(std::move(*other.ptr()));
other.destroy();
}
}
return *this;
}
optional& operator=(nullopt_t) noexcept
{
destroy();
return *this;
}
optional& operator=(const T& value)
{
destroy();
has_value_ = true;
new (storage) T(value);
return *this;
}
optional& operator=(T&& value)
{
destroy();
has_value_ = true;
new (storage) T(std::move(value));
return *this;
}
template <typename... Args>
void emplace(Args&&... args)
{
destroy();
has_value_ = true;
new (storage) T(std::forward<Args>(args)...);
}
explicit operator bool() const noexcept { return has_value_; }
bool has_value() const noexcept { return has_value_; }
T& value()
{
if (!has_value_) throw bad_optional_access{};
return *ptr();
}
const T& value() const
{
if (!has_value_) throw bad_optional_access{};
return *ptr();
}
T* operator->() { return ptr(); }
const T* operator->() const { return ptr(); }
T& operator*() { return *ptr(); }
const T& operator*() const { return *ptr(); }
template <typename U>
T value_or(U&& default_value) const& {
return has_value_ ? *ptr() : static_cast<T>(std::forward<U>(default_value));
}
template <typename U>
T value_or(U&& default_value) && {
return has_value_ ? std::move(*ptr()) : static_cast<T>(std::forward<U>(default_value));
}
void reset() noexcept
{
destroy();
}
};
#endif // #if __cplusplus < 201703L
}
#endif // COMPATIBILITY_HPP

4
modules/demux/hls/playlist/Parser.cpp

@ -365,8 +365,8 @@ void M3U8Parser::parseSegments(vlc_object_t *, HLSRepresentation *rep, const std
ByteRange range = ctx_byterange->getValue().getByteRange();
if(!range.first.has_value()) /* first == offset, second = length */
range.first = prevbyterangeoffset;
prevbyterangeoffset = range.first.value() + range.second;
segment->setByteRange(range.first.value(), prevbyterangeoffset - 1);
prevbyterangeoffset = *range.first + range.second;
segment->setByteRange(*range.first, prevbyterangeoffset - 1);
ctx_byterange = nullptr;
}
segment->setDiscontinuitySequenceNumber(discontinuitySequence);

4
modules/demux/hls/playlist/Tags.cpp

@ -70,7 +70,7 @@ std::vector<uint8_t> Attribute::hexSequence() const
return ret;
}
static inline std::istream& operator>>(std::istream& is, adaptive::optional<std::size_t>& data)
static inline std::istream& operator>>(std::istream& is, std::optional<std::size_t>& data)
{
size_t val;
if(is >> val)
@ -81,7 +81,7 @@ static inline std::istream& operator>>(std::istream& is, adaptive::optional<std:
ByteRange Attribute::getByteRange() const
{
std::size_t length;
adaptive::optional<std::size_t> offset;
std::optional<std::size_t> offset;
std::istringstream is(value);
is.imbue(std::locale("C"));

5
modules/demux/hls/playlist/Tags.hpp

@ -20,21 +20,20 @@
#ifndef TAGS_HPP
#define TAGS_HPP
#include "../../adaptive/tools/Compatibility.hpp"
#include <stdint.h>
#include <string>
#include <vector>
#include <list>
#include <utility>
#include <optional>
namespace hls
{
namespace playlist
{
using ByteRange = std::pair<adaptive::optional<std::size_t>,std::size_t>;
using ByteRange = std::pair<std::optional<std::size_t>,std::size_t>;
class Attribute
{

Loading…
Cancel
Save