Implement Cast Streaming mirroring, DLNA casting, daemon+GUI, and breadd integration
Some checks failed
dev release / build (push) Failing after 12s
Some checks failed
dev release / build (push) Failing after 12s
Builds out the full v1 scope: a vendored+patched openscreen subset for low-latency Cast Streaming (Mirroring receiver 0F5096E8) alongside the existing Cast V2/HLS and new DLNA/AVTransport casting paths, breadcastd's Idle/Casting state machine with a private IPC socket, the breadcast GTK4 popup as a thin IPC client, and bread.cast.*/bread.command.cast.* breadd integration (device discovery, start/stop, mirroring lifecycle events). Also adds bakery/systemd/Forgejo CI packaging. Validated end-to-end against a real Chromecast/Google TV: negotiated Cast Streaming session, live pipeline playback, and daemon+GUI click-to-cast/ stop through the actual popup.
This commit is contained in:
parent
887c29002f
commit
8c745d18e0
283 changed files with 36788 additions and 0 deletions
131
breadcast-caststream-sys/vendor/openscreen/util/alarm.cc
vendored
Normal file
131
breadcast-caststream-sys/vendor/openscreen/util/alarm.cc
vendored
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/alarm.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
class Alarm::CancelableFunctor {
|
||||
public:
|
||||
explicit CancelableFunctor(Alarm* alarm) : alarm_(alarm) {
|
||||
OSP_CHECK(alarm_);
|
||||
OSP_CHECK(!alarm_->queued_fire_);
|
||||
alarm_->queued_fire_ = this;
|
||||
}
|
||||
|
||||
~CancelableFunctor() { Cancel(); }
|
||||
|
||||
CancelableFunctor(CancelableFunctor&& other) : alarm_(other.alarm_) {
|
||||
other.alarm_ = nullptr;
|
||||
if (alarm_) {
|
||||
OSP_CHECK_EQ(alarm_->queued_fire_, &other);
|
||||
alarm_->queued_fire_ = this;
|
||||
}
|
||||
}
|
||||
|
||||
CancelableFunctor& operator=(CancelableFunctor&& other) {
|
||||
Cancel();
|
||||
alarm_ = other.alarm_;
|
||||
other.alarm_ = nullptr;
|
||||
if (alarm_) {
|
||||
OSP_CHECK_EQ(alarm_->queued_fire_, &other);
|
||||
alarm_->queued_fire_ = this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator()() noexcept {
|
||||
if (alarm_) {
|
||||
Alarm* alarm = alarm_;
|
||||
OSP_CHECK_EQ(alarm->queued_fire_, this);
|
||||
alarm->queued_fire_ = nullptr;
|
||||
alarm_ = nullptr;
|
||||
alarm->TryInvoke();
|
||||
}
|
||||
}
|
||||
|
||||
void Cancel() {
|
||||
if (alarm_) {
|
||||
OSP_CHECK_EQ(alarm_->queued_fire_, this);
|
||||
alarm_->queued_fire_ = nullptr;
|
||||
alarm_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ptr<Alarm> alarm_;
|
||||
};
|
||||
|
||||
Alarm::Alarm(ClockNowFunctionPtr now_function, TaskRunner& task_runner)
|
||||
: now_function_(now_function), task_runner_(task_runner) {
|
||||
OSP_CHECK(now_function_);
|
||||
}
|
||||
|
||||
Alarm::~Alarm() {
|
||||
if (queued_fire_) {
|
||||
queued_fire_->Cancel();
|
||||
OSP_CHECK(!queued_fire_);
|
||||
}
|
||||
}
|
||||
|
||||
void Alarm::Cancel() {
|
||||
scheduled_task_ = TaskRunner::Task();
|
||||
}
|
||||
|
||||
void Alarm::ScheduleWithTask(TaskRunner::Task task,
|
||||
Clock::time_point desired_alarm_time) {
|
||||
OSP_CHECK(task.valid());
|
||||
|
||||
scheduled_task_ = std::move(task);
|
||||
|
||||
const Clock::time_point now = now_function_();
|
||||
alarm_time_ = std::max(now, desired_alarm_time);
|
||||
|
||||
// Ensure that a later firing will occur, and not too late.
|
||||
if (queued_fire_) {
|
||||
if (next_fire_time_ <= alarm_time_) {
|
||||
return;
|
||||
}
|
||||
queued_fire_->Cancel();
|
||||
OSP_CHECK(!queued_fire_);
|
||||
}
|
||||
InvokeLater(now, alarm_time_);
|
||||
}
|
||||
|
||||
void Alarm::InvokeLater(Clock::time_point now, Clock::time_point fire_time) {
|
||||
OSP_CHECK(!queued_fire_);
|
||||
next_fire_time_ = fire_time;
|
||||
// Note: Instantiating the CancelableFunctor below sets |this->queued_fire_|.
|
||||
task_runner_->PostTaskWithDelay(CancelableFunctor(this), fire_time - now);
|
||||
}
|
||||
|
||||
void Alarm::TryInvoke() {
|
||||
if (!scheduled_task_.valid()) {
|
||||
return; // This Alarm was canceled in the meantime.
|
||||
}
|
||||
|
||||
// If this is an early firing, re-schedule for later. This happens if
|
||||
// Schedule() was called again before this firing had occurred.
|
||||
const Clock::time_point now = now_function_();
|
||||
if (now < alarm_time_) {
|
||||
InvokeLater(now, alarm_time_);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move the client Task to the stack before executing, just in case the task
|
||||
// itself: a) calls any Alarm methods re-entrantly, or b) causes the
|
||||
// destruction of this Alarm instance.
|
||||
// WARNING: `this` is not valid after here!
|
||||
TaskRunner::Task task = std::move(scheduled_task_);
|
||||
task();
|
||||
}
|
||||
|
||||
// static
|
||||
constexpr Clock::time_point Alarm::kImmediately;
|
||||
|
||||
} // namespace openscreen
|
||||
109
breadcast-caststream-sys/vendor/openscreen/util/alarm.h
vendored
Normal file
109
breadcast-caststream-sys/vendor/openscreen/util/alarm.h
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_ALARM_H_
|
||||
#define UTIL_ALARM_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "platform/api/task_runner.h"
|
||||
#include "platform/api/time.h"
|
||||
#include "util/raw_ptr.h"
|
||||
#include "util/raw_ref.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// A simple mechanism for running one Task in the future, but also allow for
|
||||
// canceling the Task before it runs and/or re-scheduling a replacement Task to
|
||||
// run at a different time. This mechanism is also scoped to its lifetime: if an
|
||||
// Alarm is destroyed while it is scheduled, the Task is automatically canceled.
|
||||
// It is safe for the client's Task to make re-entrant calls into all Alarm
|
||||
// methods.
|
||||
//
|
||||
// Example use case: When using a TaskRunner, an object can safely schedule a
|
||||
// callback into one of its instance methods (without the possibility of the
|
||||
// Task executing after the object is destroyed).
|
||||
//
|
||||
// Design: In order to support efficient, arbitrary canceling and re-scheduling
|
||||
// by the client, the Alarm posts a cancelable functor to the TaskRunner which,
|
||||
// when invoked, then checks to see whether the Alarm instance still exists and,
|
||||
// if so, calls its TryInvoke() method. The TryInvoke() method then determines:
|
||||
// a) whether the invocation time of the client's Task has changed; and b)
|
||||
// whether the Alarm was canceled in the meantime. From this, it either: a) does
|
||||
// nothing; b) re-posts a new cancelable functor to the TaskRunner, to try
|
||||
// running the client's Task later; or c) runs the client's Task.
|
||||
class Alarm {
|
||||
public:
|
||||
Alarm(ClockNowFunctionPtr now_function, TaskRunner& task_runner);
|
||||
~Alarm();
|
||||
|
||||
// The design requires that Alarm instances not be copied or moved.
|
||||
Alarm(const Alarm&) = delete;
|
||||
Alarm& operator=(const Alarm&) = delete;
|
||||
Alarm(Alarm&&) noexcept = delete;
|
||||
Alarm& operator=(Alarm&&) noexcept = delete;
|
||||
|
||||
// Schedule the `functor` to be invoked at `alarm_time`. If this Alarm was
|
||||
// already scheduled, the prior scheduling is canceled. The Functor can be any
|
||||
// callable target (e.g., function, lambda-expression, std::bind result,
|
||||
// etc.). If `alarm_time` is on or before "now," such as kImmediately, it is
|
||||
// scheduled to run as soon as possible.
|
||||
template <typename Functor>
|
||||
inline void Schedule(Functor functor, Clock::time_point alarm_time) {
|
||||
ScheduleWithTask(TaskRunner::Task(std::move(functor)), alarm_time);
|
||||
}
|
||||
|
||||
// Same as Schedule(), but invoke the functor at the given `delay` after right
|
||||
// now.
|
||||
template <typename Functor>
|
||||
inline void ScheduleFromNow(Functor functor, Clock::duration delay) {
|
||||
ScheduleWithTask(TaskRunner::Task(std::move(functor)),
|
||||
now_function_() + delay);
|
||||
}
|
||||
|
||||
// Cancels an already-scheduled task from running, or no-op.
|
||||
void Cancel();
|
||||
|
||||
// See comments for Schedule(). Generally, callers will want to call
|
||||
// Schedule() instead of this, for more-convenient caller-side syntax, unless
|
||||
// they already have a Task to pass-in.
|
||||
void ScheduleWithTask(TaskRunner::Task task, Clock::time_point alarm_time);
|
||||
|
||||
// A special time_point value representing "as soon as possible."
|
||||
static constexpr Clock::time_point kImmediately = Clock::time_point::min();
|
||||
|
||||
private:
|
||||
// A move-only functor that holds a raw pointer back to `this` and can be
|
||||
// canceled before its call operator is invoked. When canceled, its call
|
||||
// operator becomes a no-op.
|
||||
class CancelableFunctor;
|
||||
|
||||
// Posts a delayed call to TryInvoke() to the TaskRunner.
|
||||
void InvokeLater(Clock::time_point now, Clock::time_point fire_time);
|
||||
|
||||
// Examines whether to invoke the client's Task now; or try again later; or
|
||||
// just do nothing. See class-level design comments.
|
||||
void TryInvoke();
|
||||
|
||||
const ClockNowFunctionPtr now_function_;
|
||||
const raw_ref<TaskRunner> task_runner_;
|
||||
|
||||
// This is the task the client wants to have run at a specific point-in-time.
|
||||
// This is NOT the task that Alarm provides to the TaskRunner.
|
||||
TaskRunner::Task scheduled_task_;
|
||||
Clock::time_point alarm_time_{};
|
||||
|
||||
// When non-null, there is a task in the TaskRunner's queue that will call
|
||||
// TryInvoke() some time in the future. This member is exclusively maintained
|
||||
// by the CancelableFunctor class methods.
|
||||
raw_ptr<CancelableFunctor> queued_fire_;
|
||||
|
||||
// When the CancelableFunctor is scheduled to run. It may possibly execute
|
||||
// later than this, if the TaskRunner is falling behind.
|
||||
Clock::time_point next_fire_time_{};
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_ALARM_H_
|
||||
65
breadcast-caststream-sys/vendor/openscreen/util/base64.cc
vendored
Normal file
65
breadcast-caststream-sys/vendor/openscreen/util/base64.cc
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
// LOCAL PATCH (breadcast): upstream implements this on top of
|
||||
// third_party/modp_b64, which isn't fetched by a plain shallow clone of
|
||||
// openscreen (it's pulled in separately via gclient/DEPS). This is a
|
||||
// same-interface reimplementation on top of OpenSSL's EVP_Encode/DecodeBlock
|
||||
// instead, since system OpenSSL is already a build dependency here. See
|
||||
// vendor/openscreen/PATCHES.md.
|
||||
#include "util/base64.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace openscreen::base64 {
|
||||
|
||||
std::string Encode(ByteView input) {
|
||||
return Encode(std::string_view(reinterpret_cast<const char*>(input.data()),
|
||||
input.size()));
|
||||
}
|
||||
|
||||
std::string Encode(std::string_view input) {
|
||||
const auto* data = reinterpret_cast<const unsigned char*>(input.data());
|
||||
// EVP_EncodeBlock's output is 4*ceil(n/3) bytes plus a NUL terminator it
|
||||
// writes but doesn't count in the returned length.
|
||||
std::string out((4 * ((input.size() + 2) / 3)) + 1, '\0');
|
||||
const int output_size = EVP_EncodeBlock(
|
||||
reinterpret_cast<unsigned char*>(out.data()), data,
|
||||
static_cast<int>(input.size()));
|
||||
out.resize(static_cast<size_t>(output_size));
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Decode(std::string_view input, std::vector<uint8_t>* output) {
|
||||
if (input.size() % 4 != 0) {
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> out((input.size() / 4) * 3);
|
||||
if (!out.empty()) {
|
||||
const int decoded_size = EVP_DecodeBlock(
|
||||
out.data(), reinterpret_cast<const unsigned char*>(input.data()),
|
||||
static_cast<int>(input.size()));
|
||||
if (decoded_size < 0) {
|
||||
return false;
|
||||
}
|
||||
// EVP_DecodeBlock doesn't strip padding from the output size -- trim the
|
||||
// 1-2 bytes corresponding to trailing '=' padding characters, matching
|
||||
// the caller-visible behavior of a normal base64 decoder.
|
||||
size_t padding = 0;
|
||||
if (input.size() >= 2) {
|
||||
if (input[input.size() - 1] == '=') {
|
||||
++padding;
|
||||
}
|
||||
if (input[input.size() - 2] == '=') {
|
||||
++padding;
|
||||
}
|
||||
}
|
||||
out.resize(static_cast<size_t>(decoded_size) - padding);
|
||||
}
|
||||
*output = std::move(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace openscreen::base64
|
||||
32
breadcast-caststream-sys/vendor/openscreen/util/base64.h
vendored
Normal file
32
breadcast-caststream-sys/vendor/openscreen/util/base64.h
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_BASE64_H_
|
||||
#define UTIL_BASE64_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "platform/base/error.h"
|
||||
#include "platform/base/span.h"
|
||||
|
||||
namespace openscreen::base64 {
|
||||
|
||||
// Encodes the input binary data in base64.
|
||||
std::string Encode(ByteView input);
|
||||
|
||||
// Encodes the input string in base64.
|
||||
std::string Encode(std::string_view input);
|
||||
|
||||
// Decodes the base64 input string. Returns true if successful and false
|
||||
// otherwise. The output string is only modified if successful. The decoding can
|
||||
// be done in-place.
|
||||
bool Decode(std::string_view input, std::vector<uint8_t>* output);
|
||||
|
||||
} // namespace openscreen::base64
|
||||
|
||||
#endif // UTIL_BASE64_H_
|
||||
47
breadcast-caststream-sys/vendor/openscreen/util/big_endian.cc
vendored
Normal file
47
breadcast-caststream-sys/vendor/openscreen/util/big_endian.cc
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/big_endian.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
BigEndianReader::BigEndianReader(ByteView buffer) : BigEndianBuffer(buffer) {}
|
||||
|
||||
BigEndianReader::BigEndianReader(const uint8_t* buffer, size_t length)
|
||||
: BigEndianBuffer(buffer, length) {}
|
||||
|
||||
bool BigEndianReader::Read(size_t length, void* out) {
|
||||
return Read(ByteBuffer(static_cast<uint8_t*>(out), length));
|
||||
}
|
||||
|
||||
bool BigEndianReader::Read(ByteBuffer out) {
|
||||
ByteView view = remaining_span();
|
||||
if (view.size() >= out.size()) {
|
||||
std::copy(view.begin(), view.begin() + out.size(), out.begin());
|
||||
Skip(out.size());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BigEndianWriter::BigEndianWriter(ByteBuffer buffer) : BigEndianBuffer(buffer) {}
|
||||
|
||||
BigEndianWriter::BigEndianWriter(uint8_t* buffer, size_t length)
|
||||
: BigEndianBuffer(buffer, length) {}
|
||||
|
||||
bool BigEndianWriter::Write(const void* buffer, size_t length) {
|
||||
return Write(ByteView(static_cast<const uint8_t*>(buffer), length));
|
||||
}
|
||||
|
||||
bool BigEndianWriter::Write(ByteView buffer) {
|
||||
ByteBuffer view = remaining_span();
|
||||
if (view.size() >= buffer.size()) {
|
||||
std::copy(buffer.begin(), buffer.end(), view.begin());
|
||||
Skip(buffer.size());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
255
breadcast-caststream-sys/vendor/openscreen/util/big_endian.h
vendored
Normal file
255
breadcast-caststream-sys/vendor/openscreen/util/big_endian.h
vendored
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_BIG_ENDIAN_H_
|
||||
#define UTIL_BIG_ENDIAN_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "platform/base/span.h"
|
||||
#include "util/raw_ptr.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Note: All of the functions here are defined inline, as any half-decent
|
||||
// compiler will optimize them to a single integer constant or single
|
||||
// instruction on most architectures.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Returns true if this code is running on a big-endian architecture.
|
||||
inline bool IsBigEndianArchitecture() {
|
||||
const uint16_t kTestWord = 0x0100;
|
||||
uint8_t bytes[sizeof(kTestWord)];
|
||||
memcpy(bytes, &kTestWord, sizeof(bytes));
|
||||
return !!bytes[0];
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <int size>
|
||||
struct MakeSizedUnsignedInteger;
|
||||
|
||||
template <>
|
||||
struct MakeSizedUnsignedInteger<1> {
|
||||
using type = uint8_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MakeSizedUnsignedInteger<2> {
|
||||
using type = uint16_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MakeSizedUnsignedInteger<4> {
|
||||
using type = uint32_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MakeSizedUnsignedInteger<8> {
|
||||
using type = uint64_t;
|
||||
};
|
||||
|
||||
template <int size>
|
||||
inline typename MakeSizedUnsignedInteger<size>::type ByteSwap(
|
||||
typename MakeSizedUnsignedInteger<size>::type x) {
|
||||
static_assert(size <= 8,
|
||||
"ByteSwap() specialization missing in " __FILE__
|
||||
". "
|
||||
"Are you trying to use an integer larger than 64 bits?");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint8_t ByteSwap<1>(uint8_t x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
|
||||
template <>
|
||||
inline uint64_t ByteSwap<8>(uint64_t x) {
|
||||
return __builtin_bswap64(x);
|
||||
}
|
||||
template <>
|
||||
inline uint32_t ByteSwap<4>(uint32_t x) {
|
||||
return __builtin_bswap32(x);
|
||||
}
|
||||
template <>
|
||||
inline uint16_t ByteSwap<2>(uint16_t x) {
|
||||
return __builtin_bswap16(x);
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
template <>
|
||||
inline uint64_t ByteSwap<8>(uint64_t x) {
|
||||
return _byteswap_uint64(x);
|
||||
}
|
||||
template <>
|
||||
inline uint32_t ByteSwap<4>(uint32_t x) {
|
||||
return _byteswap_ulong(x);
|
||||
}
|
||||
template <>
|
||||
inline uint16_t ByteSwap<2>(uint16_t x) {
|
||||
return _byteswap_ushort(x);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <byteswap.h>
|
||||
|
||||
template <>
|
||||
inline uint64_t ByteSwap<8>(uint64_t x) {
|
||||
return bswap_64(x);
|
||||
}
|
||||
template <>
|
||||
inline uint32_t ByteSwap<4>(uint32_t x) {
|
||||
return bswap_32(x);
|
||||
}
|
||||
template <>
|
||||
inline uint16_t ByteSwap<2>(uint16_t x) {
|
||||
return bswap_16(x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Returns the bytes of `x` in reverse order. This is only defined for 16-, 32-,
|
||||
// and 64-bit unsigned integers.
|
||||
template <typename Integer>
|
||||
inline std::enable_if_t<std::is_unsigned<Integer>::value, Integer> ByteSwap(
|
||||
Integer x) {
|
||||
return internal::ByteSwap<sizeof(Integer)>(x);
|
||||
}
|
||||
|
||||
// Read a POD integer from `src` in big-endian byte order, returning the integer
|
||||
// in native byte order.
|
||||
template <typename Integer>
|
||||
inline Integer ReadBigEndian(const void* src) {
|
||||
Integer result;
|
||||
memcpy(&result, src, sizeof(result));
|
||||
if (!IsBigEndianArchitecture()) {
|
||||
result = ByteSwap<typename std::make_unsigned<Integer>::type>(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Write a POD integer `val` to `dest` in big-endian byte order.
|
||||
template <typename Integer>
|
||||
inline void WriteBigEndian(Integer val, void* dest) {
|
||||
if (!IsBigEndianArchitecture()) {
|
||||
val = ByteSwap<typename std::make_unsigned<Integer>::type>(val);
|
||||
}
|
||||
memcpy(dest, &val, sizeof(val));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class BigEndianBuffer {
|
||||
public:
|
||||
class Cursor {
|
||||
public:
|
||||
explicit Cursor(BigEndianBuffer* buffer)
|
||||
: buffer_(buffer), origin_offset_(buffer_->offset()) {}
|
||||
Cursor(const Cursor& other) = delete;
|
||||
Cursor(Cursor&& other) noexcept = delete;
|
||||
~Cursor() { buffer_->set_offset(origin_offset_); }
|
||||
|
||||
Cursor& operator=(const Cursor& other) = delete;
|
||||
Cursor& operator=(Cursor&& other) noexcept = delete;
|
||||
|
||||
void Commit() { origin_offset_ = buffer_->offset(); }
|
||||
|
||||
size_t origin_offset() const { return origin_offset_; }
|
||||
T* origin() const { return buffer_->begin() + origin_offset_; }
|
||||
size_t delta() const { return buffer_->offset() - origin_offset_; }
|
||||
|
||||
private:
|
||||
raw_ptr<BigEndianBuffer<T>> buffer_;
|
||||
size_t origin_offset_;
|
||||
};
|
||||
|
||||
bool Skip(size_t length) {
|
||||
if (length > remaining()) {
|
||||
return false;
|
||||
}
|
||||
offset_ += length;
|
||||
return true;
|
||||
}
|
||||
|
||||
Span<T> buffer() const { return buffer_; }
|
||||
Span<T> remaining_span() const { return buffer_.subspan(offset_); }
|
||||
// TODO(crbug.com/520101123): Remove unsafe raw pointer and length methods.
|
||||
T* begin() const { return buffer_.data(); }
|
||||
T* current() const { return buffer_.data() + offset_; }
|
||||
T* end() const { return buffer_.data() + buffer_.size(); }
|
||||
size_t length() const { return buffer_.size(); }
|
||||
size_t remaining() const { return buffer_.size() - offset_; }
|
||||
size_t offset() const { return offset_; }
|
||||
|
||||
explicit BigEndianBuffer(Span<T> buffer) : buffer_(buffer) {}
|
||||
// TODO(crbug.com/520101123): Remove unsafe raw pointer and length methods.
|
||||
BigEndianBuffer(T* buffer, size_t length) : buffer_(buffer, length) {}
|
||||
BigEndianBuffer(const BigEndianBuffer&) = delete;
|
||||
BigEndianBuffer& operator=(const BigEndianBuffer&) = delete;
|
||||
|
||||
protected:
|
||||
void set_offset(size_t offset) { offset_ = offset; }
|
||||
|
||||
private:
|
||||
Span<T> buffer_;
|
||||
size_t offset_ = 0;
|
||||
};
|
||||
|
||||
class BigEndianReader : public BigEndianBuffer<const uint8_t> {
|
||||
public:
|
||||
explicit BigEndianReader(ByteView buffer);
|
||||
// TODO(crbug.com/520101123): Remove unsafe raw pointer and length methods.
|
||||
BigEndianReader(const uint8_t* buffer, size_t length);
|
||||
|
||||
template <typename T>
|
||||
bool Read(T* out) {
|
||||
ByteView view = remaining_span();
|
||||
if (view.size() >= sizeof(T)) {
|
||||
*out = ReadBigEndian<T>(view.data());
|
||||
Skip(sizeof(T));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(crbug.com/520101123): Remove unsafe raw pointer and length methods.
|
||||
bool Read(size_t length, void* out);
|
||||
bool Read(ByteBuffer out);
|
||||
};
|
||||
|
||||
class BigEndianWriter : public BigEndianBuffer<uint8_t> {
|
||||
public:
|
||||
explicit BigEndianWriter(ByteBuffer buffer);
|
||||
// TODO(crbug.com/520101123): Remove unsafe raw pointer and length methods.
|
||||
BigEndianWriter(uint8_t* buffer, size_t length);
|
||||
|
||||
template <typename T>
|
||||
bool Write(T value) {
|
||||
ByteBuffer view = remaining_span();
|
||||
if (view.size() >= sizeof(T)) {
|
||||
WriteBigEndian<T>(value, view.data());
|
||||
Skip(sizeof(T));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(crbug.com/520101123): Remove unsafe raw pointer and length methods.
|
||||
bool Write(const void* buffer, size_t length);
|
||||
bool Write(ByteView buffer);
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_BIG_ENDIAN_H_
|
||||
34
breadcast-caststream-sys/vendor/openscreen/util/bit_vector.cc
vendored
Normal file
34
breadcast-caststream-sys/vendor/openscreen/util/bit_vector.cc
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2026 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/bit_vector.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
BitVector::BitVector(size_t size, Fill fill) {
|
||||
Resize(size, fill);
|
||||
}
|
||||
|
||||
void BitVector::Resize(size_t size, Fill fill) {
|
||||
size_ = size;
|
||||
v_.assign((size + kBitsPerWord - 1) / kBitsPerWord,
|
||||
fill ? ~uint64_t{0} : uint64_t{0});
|
||||
if (fill && size % kBitsPerWord != 0) {
|
||||
v_.back() &= (uint64_t{1} << (size % kBitsPerWord)) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t BitVector::FindFirstSet() const {
|
||||
for (size_t i = 0; i < v_.size(); ++i) {
|
||||
if (v_[i] != 0) {
|
||||
size_t pos = i * kBitsPerWord + std::countr_zero(v_[i]);
|
||||
return (pos < size_) ? pos : size_;
|
||||
}
|
||||
}
|
||||
return size_;
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
66
breadcast-caststream-sys/vendor/openscreen/util/bit_vector.h
vendored
Normal file
66
breadcast-caststream-sys/vendor/openscreen/util/bit_vector.h
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright 2026 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_BIT_VECTOR_H_
|
||||
#define UTIL_BIT_VECTOR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <bit>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// A simple dynamic bit vector implementation using C++20 <bit> and std::vector.
|
||||
// This is used for tracking packet transmission flags in the Sender.
|
||||
class BitVector {
|
||||
public:
|
||||
enum Fill : bool { SET = true, CLEARED = false };
|
||||
|
||||
BitVector() noexcept = default;
|
||||
BitVector(size_t size, Fill fill);
|
||||
|
||||
~BitVector() = default;
|
||||
|
||||
BitVector(BitVector&& other) noexcept = default;
|
||||
BitVector& operator=(BitVector&& other) noexcept = default;
|
||||
|
||||
BitVector(const BitVector& other) = default;
|
||||
BitVector& operator=(const BitVector& other) = default;
|
||||
|
||||
[[nodiscard]] size_t size() const noexcept { return size_; }
|
||||
|
||||
void Resize(size_t size, Fill fill);
|
||||
|
||||
void Set(size_t pos) {
|
||||
OSP_CHECK_LT(pos, size_);
|
||||
v_[pos / kBitsPerWord] |= (uint64_t{1} << (pos % kBitsPerWord));
|
||||
}
|
||||
|
||||
void Clear(size_t pos) {
|
||||
OSP_CHECK_LT(pos, size_);
|
||||
v_[pos / kBitsPerWord] &= ~(uint64_t{1} << (pos % kBitsPerWord));
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsSet(size_t pos) const {
|
||||
OSP_CHECK_LT(pos, size_);
|
||||
return (v_[pos / kBitsPerWord] >> (pos % kBitsPerWord)) & 1;
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t FindFirstSet() const;
|
||||
|
||||
private:
|
||||
static constexpr size_t kBitsPerWord = std::numeric_limits<uint64_t>::digits;
|
||||
|
||||
std::vector<uint64_t> v_;
|
||||
size_t size_ = 0;
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_BIT_VECTOR_H_
|
||||
50
breadcast-caststream-sys/vendor/openscreen/util/chrono_helpers.h
vendored
Normal file
50
breadcast-caststream-sys/vendor/openscreen/util/chrono_helpers.h
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_CHRONO_HELPERS_H_
|
||||
#define UTIL_CHRONO_HELPERS_H_
|
||||
|
||||
#include <chrono>
|
||||
|
||||
// This file is a collection of helpful utilities and using statement for
|
||||
// working with std::chrono. In practice we previously defined these frequently,
|
||||
// this header allows for a single set of convenience statements.
|
||||
namespace openscreen {
|
||||
|
||||
using hours = std::chrono::hours;
|
||||
using microseconds = std::chrono::microseconds;
|
||||
using milliseconds = std::chrono::milliseconds;
|
||||
using nanoseconds = std::chrono::nanoseconds;
|
||||
using seconds = std::chrono::seconds;
|
||||
|
||||
// Casting statements. Note that duration_cast is not a type, it's a function,
|
||||
// so its behavior is different than the using statements above.
|
||||
template <typename D>
|
||||
static constexpr hours to_hours(D d) {
|
||||
return std::chrono::duration_cast<hours>(d);
|
||||
}
|
||||
|
||||
template <typename D>
|
||||
static constexpr microseconds to_microseconds(D d) {
|
||||
return std::chrono::duration_cast<microseconds>(d);
|
||||
}
|
||||
|
||||
template <typename D>
|
||||
static constexpr milliseconds to_milliseconds(D d) {
|
||||
return std::chrono::duration_cast<milliseconds>(d);
|
||||
}
|
||||
|
||||
template <typename D>
|
||||
static constexpr nanoseconds to_nanoseconds(D d) {
|
||||
return std::chrono::duration_cast<nanoseconds>(d);
|
||||
}
|
||||
|
||||
template <typename D>
|
||||
static constexpr seconds to_seconds(D d) {
|
||||
return std::chrono::duration_cast<seconds>(d);
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_CHRONO_HELPERS_H_
|
||||
62
breadcast-caststream-sys/vendor/openscreen/util/crypto/openssl_util.cc
vendored
Normal file
62
breadcast-caststream-sys/vendor/openscreen/util/crypto/openssl_util.cc
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/crypto/openssl_util.h"
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
namespace {
|
||||
|
||||
// Callback routine for OpenSSL to print error messages. `str` is a
|
||||
// nullptr-terminated string of length `len` containing diagnostic information
|
||||
// such as the library, function and reason for the error, the file and line
|
||||
// where the error originated, plus potentially any context-specific
|
||||
// information about the error. `context` contains a pointer to user-supplied
|
||||
// data, which is currently unused.
|
||||
// If this callback returns a value <= 0, OpenSSL will stop processing the
|
||||
// error queue and return, otherwise it will continue calling this function
|
||||
// until all errors have been removed from the queue.
|
||||
int OpenSSLErrorCallback(const char* str, size_t len, void* context) {
|
||||
OSP_DVLOG << "\t" << std::string_view(str, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void EnsureOpenSSLInit() {
|
||||
// LOCAL PATCH (breadcast): upstream calls OPENSSL_init_ssl() here, but
|
||||
// this vendored subset never touches libssl (no TLS -- see
|
||||
// ../../../PATCHES.md), so this just does the general libcrypto init
|
||||
// instead. Safe to call repeatedly; OpenSSL 3.x makes this optional
|
||||
// anyway, but frame_crypto.cc's key setup wants it done up front.
|
||||
OPENSSL_init_crypto(0, nullptr);
|
||||
}
|
||||
|
||||
void ClearOpenSSLERRStack(const Location& location) {
|
||||
if (OSP_DCHECK_IS_ON()) {
|
||||
uint32_t error_num = ERR_peek_error();
|
||||
if (error_num == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
OSP_DVLOG << "OpenSSL ERR_get_error stack from " << location;
|
||||
ERR_print_errors_cb(&OpenSSLErrorCallback, nullptr);
|
||||
} else {
|
||||
ERR_clear_error();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
61
breadcast-caststream-sys/vendor/openscreen/util/crypto/openssl_util.h
vendored
Normal file
61
breadcast-caststream-sys/vendor/openscreen/util/crypto/openssl_util.h
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_CRYPTO_OPENSSL_UTIL_H_
|
||||
#define UTIL_CRYPTO_OPENSSL_UTIL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "platform/base/error.h"
|
||||
#include "platform/base/location.h"
|
||||
|
||||
// LOCAL PATCH (breadcast): dropped SSLErrorCodeToError()/GetSSLError(),
|
||||
// which format an SSL_get_error() result and reference BoringSSL's
|
||||
// SSL_error_description() (not part of system OpenSSL's public API). Unused
|
||||
// here -- the TLS CASTV2 control channel is handled by the existing
|
||||
// rust_cast-based Rust code, not this vendored openscreen subset, which only
|
||||
// needs the general ERR_*/AES pieces. See vendor/openscreen/PATCHES.md.
|
||||
|
||||
namespace openscreen {
|
||||
// Initialize OpenSSL if it isn't already initialized. This must be called
|
||||
// before any other OpenSSL functions though it is safe and cheap to call this
|
||||
// multiple times.
|
||||
// This function is thread-safe, and OpenSSL will only ever be initialized once.
|
||||
// OpenSSL will be properly shut down on program exit.
|
||||
// Multiple sequential calls to EnsureOpenSSLInit or EnsureOpenSSLCleanup are
|
||||
// ignored by OpenSSL itself.
|
||||
void EnsureOpenSSLInit();
|
||||
|
||||
// Drains the OpenSSL ERR_get_error stack. On a debug build the error codes
|
||||
// are send to VLOG(1), on a release build they are disregarded. In most
|
||||
// cases you should pass CURRENT_LOCATION as the `location`.
|
||||
void ClearOpenSSLERRStack(const Location& location);
|
||||
|
||||
// Place an instance of this class on the call stack to automatically clear
|
||||
// the OpenSSL error stack on function exit.
|
||||
class OpenSSLErrStackTracer {
|
||||
public:
|
||||
// Pass CURRENT_LOCATION as `location`, to help track the source of OpenSSL
|
||||
// error messages. Note any diagnostic emitted will be tagged with the
|
||||
// location of the constructor call as it's not possible to trace a
|
||||
// destructor's callsite.
|
||||
explicit OpenSSLErrStackTracer(const Location& location)
|
||||
: location_(location) {
|
||||
EnsureOpenSSLInit();
|
||||
}
|
||||
OpenSSLErrStackTracer(const OpenSSLErrStackTracer&) = delete;
|
||||
OpenSSLErrStackTracer(OpenSSLErrStackTracer&&) noexcept = delete;
|
||||
OpenSSLErrStackTracer& operator=(const OpenSSLErrStackTracer&) = delete;
|
||||
OpenSSLErrStackTracer& operator=(OpenSSLErrStackTracer&&) = delete;
|
||||
~OpenSSLErrStackTracer() { ClearOpenSSLERRStack(location_); }
|
||||
|
||||
private:
|
||||
const Location location_;
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_CRYPTO_OPENSSL_UTIL_H_
|
||||
23
breadcast-caststream-sys/vendor/openscreen/util/crypto/random_bytes.cc
vendored
Normal file
23
breadcast-caststream-sys/vendor/openscreen/util/crypto/random_bytes.cc
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/crypto/random_bytes.h"
|
||||
|
||||
#include "openssl/rand.h"
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
std::array<uint8_t, 16> GenerateRandomBytes16() {
|
||||
std::array<uint8_t, 16> result;
|
||||
GenerateRandomBytes(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void GenerateRandomBytes(ByteBuffer out) {
|
||||
// Working cryptography is mandatory for our library to run.
|
||||
OSP_CHECK(RAND_bytes(out.data(), out.size()) == 1);
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
20
breadcast-caststream-sys/vendor/openscreen/util/crypto/random_bytes.h
vendored
Normal file
20
breadcast-caststream-sys/vendor/openscreen/util/crypto/random_bytes.h
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_CRYPTO_RANDOM_BYTES_H_
|
||||
#define UTIL_CRYPTO_RANDOM_BYTES_H_
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
#include "platform/base/span.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
std::array<uint8_t, 16> GenerateRandomBytes16();
|
||||
void GenerateRandomBytes(ByteBuffer out);
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_CRYPTO_RANDOM_BYTES_H_
|
||||
51
breadcast-caststream-sys/vendor/openscreen/util/enum_name_table.h
vendored
Normal file
51
breadcast-caststream-sys/vendor/openscreen/util/enum_name_table.h
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// This file contains helpers for working with enums that require
|
||||
// both enum->string and string->enum conversions.
|
||||
|
||||
#ifndef UTIL_ENUM_NAME_TABLE_H_
|
||||
#define UTIL_ENUM_NAME_TABLE_H_
|
||||
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "platform/base/error.h"
|
||||
#include "util/osp_logging.h"
|
||||
#include "util/string_util.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
inline constexpr char kUnknownEnumError[] = "Enum value not in array";
|
||||
|
||||
template <typename Enum, size_t Size>
|
||||
using EnumNameTable = std::array<std::pair<const char*, Enum>, Size>;
|
||||
|
||||
// Get the name of an enum from the enum value.
|
||||
template <typename Enum, size_t Size>
|
||||
ErrorOr<const char*> GetEnumName(const EnumNameTable<Enum, Size>& map,
|
||||
Enum enum_) {
|
||||
for (auto pair : map) {
|
||||
if (pair.second == enum_) {
|
||||
return pair.first;
|
||||
}
|
||||
}
|
||||
return Error(Error::Code::kParameterInvalid, kUnknownEnumError);
|
||||
}
|
||||
|
||||
// Get the value of an enum from the enum name.
|
||||
template <typename Enum, size_t Size>
|
||||
ErrorOr<Enum> GetEnum(const EnumNameTable<Enum, Size>& map,
|
||||
std::string_view name) {
|
||||
for (auto pair : map) {
|
||||
if (::openscreen::string_util::EqualsIgnoreCase(pair.first, name)) {
|
||||
return pair.second;
|
||||
}
|
||||
}
|
||||
return Error(Error::Code::kParameterInvalid, kUnknownEnumError);
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
#endif // UTIL_ENUM_NAME_TABLE_H_
|
||||
66
breadcast-caststream-sys/vendor/openscreen/util/flat_map.h
vendored
Normal file
66
breadcast-caststream-sys/vendor/openscreen/util/flat_map.h
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_FLAT_MAP_H_
|
||||
#define UTIL_FLAT_MAP_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// For small numbers of elements, a vector is much more efficient than a
|
||||
// map or unordered_map due to not needing hashing. FlatMap allows for
|
||||
// using map-like syntax but is backed by a std::vector, combining all the
|
||||
// performance of a vector with the convenience of a map.
|
||||
//
|
||||
// NOTE: this class allows usage of const char* as Key or Value types, but
|
||||
// it is generally recommended that you use std::string, or std::string_view
|
||||
// for literals. string_view is similarly efficient to a raw char* pointer,
|
||||
// but gives sizing and equality operators, among other features.
|
||||
template <class Key, class Value>
|
||||
class FlatMap final : public std::vector<std::pair<Key, Value>> {
|
||||
public:
|
||||
FlatMap(std::initializer_list<std::pair<Key, Value>> init_list)
|
||||
: std::vector<std::pair<Key, Value>>(init_list) {}
|
||||
FlatMap() = default;
|
||||
FlatMap(const FlatMap&) = default;
|
||||
FlatMap(FlatMap&&) noexcept = default;
|
||||
FlatMap& operator=(const FlatMap&) = default;
|
||||
FlatMap& operator=(FlatMap&&) = default;
|
||||
~FlatMap() = default;
|
||||
|
||||
// Accessors that wrap std::find_if, and return an iterator to the key value
|
||||
// pair.
|
||||
decltype(auto) find(const Key& key) {
|
||||
return std::find_if(
|
||||
this->begin(), this->end(),
|
||||
[key](const std::pair<Key, Value>& pair) { return key == pair.first; });
|
||||
}
|
||||
|
||||
decltype(auto) find(const Key& key) const {
|
||||
return const_cast<FlatMap<Key, Value>*>(this)->find(key);
|
||||
}
|
||||
|
||||
// Remove an entry from the map. Returns an iterator pointing to the new
|
||||
// location of the element that followed the last element erased by the
|
||||
// function call. This is the container end if the operation erased the last
|
||||
// element in the sequence.
|
||||
decltype(auto) erase_key(const Key& key) {
|
||||
auto it = find(key);
|
||||
if (it == this->end()) {
|
||||
return this->end();
|
||||
}
|
||||
return static_cast<std::vector<std::pair<Key, Value>>*>(this)->erase(it);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_FLAT_MAP_H_
|
||||
55
breadcast-caststream-sys/vendor/openscreen/util/hashing.h
vendored
Normal file
55
breadcast-caststream-sys/vendor/openscreen/util/hashing.h
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_HASHING_H_
|
||||
#define UTIL_HASHING_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// This value is taken from absl::Hash implementation.
|
||||
inline constexpr uint64_t kDefaultSeed = UINT64_C(0xc3a5c85c97cb3127);
|
||||
|
||||
// Computes the aggregate hash of the provided hashable objects.
|
||||
// Seed must initially use a large prime between 2^63 and 2^64 as a starting
|
||||
// value, or the result of a previous call to this function.
|
||||
template <typename... T>
|
||||
uint64_t ComputeAggregateHash(uint64_t original_seed, const T&... objs) {
|
||||
auto hash_combiner = [](uint64_t current_seed,
|
||||
uint64_t hash_value) -> uint64_t {
|
||||
static const uint64_t kMultiplier = UINT64_C(0x9ddfea08eb382d69);
|
||||
uint64_t a = (hash_value ^ current_seed) * kMultiplier;
|
||||
a ^= (a >> 47);
|
||||
uint64_t b = (current_seed ^ a) * kMultiplier;
|
||||
b ^= (b >> 47);
|
||||
b *= kMultiplier;
|
||||
return b;
|
||||
};
|
||||
|
||||
uint64_t result = original_seed;
|
||||
std::vector<uint64_t> hashes = {std::hash<T>()(objs)...};
|
||||
for (uint64_t hash : hashes) {
|
||||
result = hash_combiner(result, hash);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
uint64_t ComputeAggregateHash(const T&... objs) {
|
||||
return ComputeAggregateHash(kDefaultSeed, objs...);
|
||||
}
|
||||
|
||||
struct PairHash {
|
||||
template <typename TFirst, typename TSecond>
|
||||
size_t operator()(const std::pair<TFirst, TSecond>& pair) const {
|
||||
return ComputeAggregateHash(pair.first, pair.second);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_HASHING_H_
|
||||
67
breadcast-caststream-sys/vendor/openscreen/util/integer_division.h
vendored
Normal file
67
breadcast-caststream-sys/vendor/openscreen/util/integer_division.h
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_INTEGER_DIVISION_H_
|
||||
#define UTIL_INTEGER_DIVISION_H_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// Returns CEIL(num ÷ denom). `denom` must not equal zero. This function is
|
||||
// compatible with any integer-like type, including the integer-based
|
||||
// std::chrono duration types.
|
||||
//
|
||||
// Optimization note: See DividePositivesRoundingUp().
|
||||
template <typename Integer>
|
||||
constexpr auto DivideRoundingUp(Integer num, Integer denom) {
|
||||
if (denom < Integer{0}) {
|
||||
num *= -1;
|
||||
denom *= -1;
|
||||
}
|
||||
if (num < Integer{0}) {
|
||||
return num / denom;
|
||||
}
|
||||
return (num + denom - Integer{1}) / denom;
|
||||
}
|
||||
|
||||
// Same as DivideRoundingUp(), except is more-efficient for hot code paths that
|
||||
// know `num` is always greater or equal to zero, and `denom` is always greater
|
||||
// than zero.
|
||||
template <typename Integer>
|
||||
constexpr Integer DividePositivesRoundingUp(Integer num, Integer denom) {
|
||||
return DivideRoundingUp<typename std::make_unsigned<Integer>::type>(num,
|
||||
denom);
|
||||
}
|
||||
|
||||
// Divides `num` by `denom`, and rounds to the nearest integer (exactly halfway
|
||||
// between integers will round to the higher integer). This function is
|
||||
// compatible with any integer-like type, including the integer-based
|
||||
// std::chrono duration types.
|
||||
//
|
||||
// Optimization note: See DividePositivesRoundingNearest().
|
||||
template <typename Integer>
|
||||
constexpr auto DivideRoundingNearest(Integer num, Integer denom) {
|
||||
if (denom < Integer{0}) {
|
||||
num *= -1;
|
||||
denom *= -1;
|
||||
}
|
||||
if (num < Integer{0}) {
|
||||
return (num - ((denom - Integer{1}) / 2)) / denom;
|
||||
}
|
||||
return (num + (denom / 2)) / denom;
|
||||
}
|
||||
|
||||
// Same as DivideRoundingNearest(), except is more-efficient for hot code paths
|
||||
// that know `num` is always greater or equal to zero, and `denom` is always
|
||||
// greater than zero.
|
||||
template <typename Integer>
|
||||
constexpr Integer DividePositivesRoundingNearest(Integer num, Integer denom) {
|
||||
return DivideRoundingNearest<typename std::make_unsigned<Integer>::type>(
|
||||
num, denom);
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_INTEGER_DIVISION_H_
|
||||
205
breadcast-caststream-sys/vendor/openscreen/util/json/json_helpers.h
vendored
Normal file
205
breadcast-caststream-sys/vendor/openscreen/util/json/json_helpers.h
vendored
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_JSON_JSON_HELPERS_H_
|
||||
#define UTIL_JSON_JSON_HELPERS_H_
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "json/value.h"
|
||||
#include "platform/base/error.h"
|
||||
#include "util/chrono_helpers.h"
|
||||
#include "util/json/json_serialization.h"
|
||||
#include "util/simple_fraction.h"
|
||||
|
||||
// This file contains helper methods for parsing JSON, in an attempt to
|
||||
// reduce boilerplate code when working with JsonCpp.
|
||||
namespace openscreen::json {
|
||||
|
||||
inline bool TryParseBool(const Json::Value& value, bool* out) {
|
||||
if (!value.isBool()) {
|
||||
return false;
|
||||
}
|
||||
*out = value.asBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
// A general note about parsing primitives. "Validation" in this context
|
||||
// generally means ensuring that the values are non-negative, excepting doubles
|
||||
// which may be negative in some cases.
|
||||
inline bool TryParseDouble(const Json::Value& value,
|
||||
double* out,
|
||||
bool allow_negative = false) {
|
||||
if (!value.isDouble()) {
|
||||
return false;
|
||||
}
|
||||
const double d = value.asDouble();
|
||||
if (std::isnan(d)) {
|
||||
return false;
|
||||
}
|
||||
if (!allow_negative && d < 0) {
|
||||
return false;
|
||||
}
|
||||
*out = d;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool TryParseInt(const Json::Value& value, int* out) {
|
||||
if (!value.isInt()) {
|
||||
return false;
|
||||
}
|
||||
int i = value.asInt();
|
||||
if (i < 0) {
|
||||
return false;
|
||||
}
|
||||
*out = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool TryParseUint(const Json::Value& value, uint32_t* out) {
|
||||
if (!value.isUInt()) {
|
||||
return false;
|
||||
}
|
||||
*out = value.asUInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool TryParseString(const Json::Value& value, std::string* out) {
|
||||
if (!value.isString()) {
|
||||
return false;
|
||||
}
|
||||
*out = value.asString();
|
||||
return true;
|
||||
}
|
||||
|
||||
// We want to be more robust when we parse fractions then just
|
||||
// allowing strings, this will parse numeral values such as
|
||||
// value: 50 as well as value: "50" and value: "100/2".
|
||||
inline bool TryParseSimpleFraction(const Json::Value& value,
|
||||
SimpleFraction* out) {
|
||||
if (value.isInt()) {
|
||||
int parsed = value.asInt();
|
||||
if (parsed < 0) {
|
||||
return false;
|
||||
}
|
||||
*out = SimpleFraction{parsed, 1};
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value.isString()) {
|
||||
auto fraction_or_error = SimpleFraction::FromString(value.asString());
|
||||
if (!fraction_or_error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fraction_or_error.value().is_positive() ||
|
||||
!fraction_or_error.value().is_defined()) {
|
||||
return false;
|
||||
}
|
||||
*out = std::move(fraction_or_error.value());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryParseMilliseconds(const Json::Value& value, milliseconds* out) {
|
||||
int out_ms;
|
||||
if (!TryParseInt(value, &out_ms) || out_ms < 0) {
|
||||
return false;
|
||||
}
|
||||
*out = milliseconds(out_ms);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using Parser = std::function<bool(const Json::Value&, T*)>;
|
||||
|
||||
// NOTE: array parsing methods reset the output vector to an empty vector in
|
||||
// any error case. This is especially useful for optional arrays.
|
||||
template <typename T>
|
||||
bool TryParseArray(const Json::Value& value,
|
||||
Parser<T> parser,
|
||||
std::vector<T>* out) {
|
||||
out->clear();
|
||||
if (!value.isArray() || value.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
out->reserve(value.size());
|
||||
for (Json::ArrayIndex i = 0; i < value.size(); ++i) {
|
||||
T v;
|
||||
if (!parser(value[i], &v)) {
|
||||
out->clear();
|
||||
return false;
|
||||
}
|
||||
out->push_back(v);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool TryParseIntArray(const Json::Value& value, std::vector<int>* out) {
|
||||
return TryParseArray<int>(value, TryParseInt, out);
|
||||
}
|
||||
|
||||
inline bool TryParseUintArray(const Json::Value& value,
|
||||
std::vector<uint32_t>* out) {
|
||||
return TryParseArray<uint32_t>(value, TryParseUint, out);
|
||||
}
|
||||
|
||||
inline bool TryParseStringArray(const Json::Value& value,
|
||||
std::vector<std::string>* out) {
|
||||
return TryParseArray<std::string>(value, TryParseString, out);
|
||||
}
|
||||
|
||||
inline bool TryParseNestedStringArray(
|
||||
const Json::Value& value,
|
||||
std::vector<std::vector<std::string>>* out) {
|
||||
return TryParseArray<std::vector<std::string>>(value, TryParseStringArray,
|
||||
out);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Json::Value PrimitiveVectorToJson(const std::vector<T>& vec) {
|
||||
Json::Value array(Json::ValueType::arrayValue);
|
||||
array.resize(vec.size());
|
||||
|
||||
for (Json::Value::ArrayIndex i = 0; i < vec.size(); ++i) {
|
||||
array[i] = Json::Value(vec[i]);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
inline Json::Value NestedStringArrayToJson(
|
||||
const std::vector<std::vector<std::string>>& vec) {
|
||||
Json::Value array(Json::ValueType::arrayValue);
|
||||
array.resize(vec.size());
|
||||
|
||||
for (Json::Value::ArrayIndex i = 0; i < vec.size(); ++i) {
|
||||
array[i] = PrimitiveVectorToJson(vec[i]);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
inline bool Contains(const Json::Value& array, std::string_view value) {
|
||||
if (!array.isArray()) {
|
||||
return false;
|
||||
}
|
||||
for (const Json::Value& entry : array) {
|
||||
if (entry.isString() && entry.asString() == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace openscreen::json
|
||||
|
||||
#endif // UTIL_JSON_JSON_HELPERS_H_
|
||||
62
breadcast-caststream-sys/vendor/openscreen/util/json/json_serialization.cc
vendored
Normal file
62
breadcast-caststream-sys/vendor/openscreen/util/json/json_serialization.cc
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/json/json_serialization.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "json/reader.h"
|
||||
#include "json/writer.h"
|
||||
#include "platform/base/error.h"
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen::json {
|
||||
|
||||
ErrorOr<Json::Value> Parse(std::string_view document) {
|
||||
Json::CharReaderBuilder builder;
|
||||
Json::CharReaderBuilder::strictMode(&builder.settings_);
|
||||
if (document.empty()) {
|
||||
return ErrorOr<Json::Value>(Error::Code::kJsonParseError, "empty document");
|
||||
}
|
||||
|
||||
Json::Value root_node;
|
||||
std::string error_msg;
|
||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||
const bool succeeded = reader->parse(&*document.begin(), &*document.end(),
|
||||
&root_node, &error_msg);
|
||||
if (!succeeded) {
|
||||
return ErrorOr<Json::Value>(Error::Code::kJsonParseError, error_msg);
|
||||
}
|
||||
|
||||
return root_node;
|
||||
}
|
||||
|
||||
ErrorOr<std::string> Stringify(const Json::Value& value) {
|
||||
Json::StreamWriterBuilder factory;
|
||||
#ifndef _DEBUG
|
||||
// Default is to "pretty print" the output JSON in a human readable
|
||||
// format. On non-debug builds, we can remove pretty printing by simply
|
||||
// getting rid of all indentation.
|
||||
factory["indentation"] = "";
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Json::StreamWriter> const writer(factory.newStreamWriter());
|
||||
std::ostringstream stream;
|
||||
writer->write(value, &stream);
|
||||
|
||||
if (!stream) {
|
||||
// Note: jsoncpp doesn't give us more information about what actually
|
||||
// went wrong, just says to "check the stream". However, failures on
|
||||
// the stream should be rare, as we do not throw any errors in the jsoncpp
|
||||
// library.
|
||||
return ErrorOr<std::string>(Error::Code::kJsonWriteError, "Invalid stream");
|
||||
}
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
} // namespace openscreen::json
|
||||
24
breadcast-caststream-sys/vendor/openscreen/util/json/json_serialization.h
vendored
Normal file
24
breadcast-caststream-sys/vendor/openscreen/util/json/json_serialization.h
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_JSON_JSON_SERIALIZATION_H_
|
||||
#define UTIL_JSON_JSON_SERIALIZATION_H_
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "json/value.h"
|
||||
#include "platform/base/error.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
namespace json {
|
||||
|
||||
ErrorOr<Json::Value> Parse(std::string_view value);
|
||||
ErrorOr<std::string> Stringify(const Json::Value& value);
|
||||
|
||||
} // namespace json
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_JSON_JSON_SERIALIZATION_H_
|
||||
43
breadcast-caststream-sys/vendor/openscreen/util/json/json_value.cc
vendored
Normal file
43
breadcast-caststream-sys/vendor/openscreen/util/json/json_value.cc
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/json/json_value.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
std::optional<int> MaybeGetInt(const Json::Value& message,
|
||||
const char* first,
|
||||
const char* last) {
|
||||
const Json::Value* value = message.find(first, last);
|
||||
std::optional<int> result;
|
||||
if (value && value->isInt()) {
|
||||
result = value->asInt();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<std::string_view> MaybeGetString(const Json::Value& message) {
|
||||
if (message.isString()) {
|
||||
const char* begin = nullptr;
|
||||
const char* end = nullptr;
|
||||
message.getString(&begin, &end);
|
||||
if (begin && end >= begin) {
|
||||
return std::string_view(begin, end - begin);
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string_view> MaybeGetString(const Json::Value& message,
|
||||
const char* first,
|
||||
const char* last) {
|
||||
const Json::Value* value = message.find(first, last);
|
||||
std::optional<std::string_view> result;
|
||||
if (value && value->isString()) {
|
||||
return MaybeGetString(*value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
29
breadcast-caststream-sys/vendor/openscreen/util/json/json_value.h
vendored
Normal file
29
breadcast-caststream-sys/vendor/openscreen/util/json/json_value.h
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_JSON_JSON_VALUE_H_
|
||||
#define UTIL_JSON_JSON_VALUE_H_
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
#include "json/value.h"
|
||||
|
||||
#define JSON_EXPAND_FIND_CONSTANT_ARGS(s) (s), ((s) + sizeof(s) - 1)
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
std::optional<int> MaybeGetInt(const Json::Value& message,
|
||||
const char* first,
|
||||
const char* last);
|
||||
|
||||
std::optional<std::string_view> MaybeGetString(const Json::Value& message);
|
||||
|
||||
std::optional<std::string_view> MaybeGetString(const Json::Value& message,
|
||||
const char* first,
|
||||
const char* last);
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_JSON_JSON_VALUE_H_
|
||||
79
breadcast-caststream-sys/vendor/openscreen/util/no_destructor.h
vendored
Normal file
79
breadcast-caststream-sys/vendor/openscreen/util/no_destructor.h
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright 2026 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_NO_DESTRUCTOR_H_
|
||||
#define UTIL_NO_DESTRUCTOR_H_
|
||||
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// Helper type to create a function-local static variable of type `T` when `T`
|
||||
// has a non-trivial destructor. Storing a `T` in a `NoDestructor<T>` will
|
||||
// prevent `~T()` from running, even when the variable goes out of scope.
|
||||
//
|
||||
// Useful when a variable has static storage duration but its type has a
|
||||
// non-trivial destructor. Using a function-local static variable prevents
|
||||
// global constructors, while using `NoDestructor<T>` prevents global
|
||||
// destructors.
|
||||
//
|
||||
// ## Example Usage
|
||||
//
|
||||
// const std::string& GetDefaultText() {
|
||||
// // Required since `static const std::string` requires a global destructor.
|
||||
// static const openscreen::NoDestructor<std::string> s("Hello world!");
|
||||
// return *s;
|
||||
// }
|
||||
template <typename T>
|
||||
class NoDestructor {
|
||||
public:
|
||||
static_assert(!(std::is_trivially_constructible_v<T> &&
|
||||
std::is_trivially_destructible_v<T>),
|
||||
"T is trivially constructible and destructible; please use a "
|
||||
"constinit object of type T directly instead");
|
||||
|
||||
static_assert(
|
||||
!std::is_trivially_destructible_v<T>,
|
||||
"T is trivially destructible; please use a function-local static "
|
||||
"of type T directly instead");
|
||||
|
||||
// Not constexpr; just write static constexpr T x = ...; if the value should
|
||||
// be a constexpr.
|
||||
template <typename... Args>
|
||||
explicit NoDestructor(Args&&... args) {
|
||||
new (storage_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Allows copy and move construction of the contained type, to allow
|
||||
// construction from an initializer list, e.g. for std::vector.
|
||||
explicit NoDestructor(const T& x) { new (storage_) T(x); }
|
||||
explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); }
|
||||
|
||||
NoDestructor(const NoDestructor&) = delete;
|
||||
NoDestructor& operator=(const NoDestructor&) = delete;
|
||||
|
||||
~NoDestructor() = default;
|
||||
|
||||
const T& operator*() const { return *get(); }
|
||||
T& operator*() { return *get(); }
|
||||
|
||||
const T* operator->() const { return get(); }
|
||||
T* operator->() { return get(); }
|
||||
|
||||
const T* get() const { return reinterpret_cast<const T*>(storage_); }
|
||||
T* get() { return reinterpret_cast<T*>(storage_); }
|
||||
|
||||
private:
|
||||
alignas(T) char storage_[sizeof(T)];
|
||||
|
||||
#if defined(LEAK_SANITIZER)
|
||||
T* storage_ptr_ = reinterpret_cast<T*>(storage_);
|
||||
#endif // defined(LEAK_SANITIZER)
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_NO_DESTRUCTOR_H_
|
||||
145
breadcast-caststream-sys/vendor/openscreen/util/osp_logging.h
vendored
Normal file
145
breadcast-caststream-sys/vendor/openscreen/util/osp_logging.h
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_OSP_LOGGING_H_
|
||||
#define UTIL_OSP_LOGGING_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "platform/api/logging.h"
|
||||
|
||||
namespace openscreen::internal {
|
||||
|
||||
// The stream-based logging macros below are adapted from Chromium's
|
||||
// base/logging.h.
|
||||
class LogMessage {
|
||||
public:
|
||||
LogMessage(LogLevel level, const char* file, int line)
|
||||
: level_(level), file_(file), line_(line) {}
|
||||
|
||||
~LogMessage() {
|
||||
LogWithLevel(level_, file_, line_, std::move(stream_));
|
||||
if (level_ == LogLevel::kFatal) {
|
||||
Break();
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& stream() { return stream_; }
|
||||
|
||||
protected:
|
||||
const LogLevel level_;
|
||||
|
||||
// The file here comes from the __FILE__ macro, which should persist while
|
||||
// we are doing the logging. Hence, keeping it unmanaged here and not
|
||||
// creating a copy should be safe.
|
||||
const char* const file_;
|
||||
const int line_;
|
||||
std::stringstream stream_;
|
||||
};
|
||||
|
||||
// Used by the OSP_LAZY_STREAM macro to return void after evaluating an ostream
|
||||
// chain expression.
|
||||
class Voidify {
|
||||
public:
|
||||
void operator&(std::ostream&) {}
|
||||
};
|
||||
|
||||
} // namespace openscreen::internal
|
||||
|
||||
#define OSP_LAZY_STREAM(condition, stream) \
|
||||
!(condition) ? (void)0 : openscreen::internal::Voidify() & (stream)
|
||||
#define OSP_LOG_IS_ON(level_enum) \
|
||||
openscreen::IsLoggingOn(openscreen::LogLevel::level_enum, \
|
||||
std::string_view(__FILE__, std::size(__FILE__)))
|
||||
#define OSP_LOG_STREAM(level_enum) \
|
||||
openscreen::internal::LogMessage(openscreen::LogLevel::level_enum, __FILE__, \
|
||||
__LINE__) \
|
||||
.stream()
|
||||
|
||||
#define OSP_VLOG \
|
||||
OSP_LAZY_STREAM(OSP_LOG_IS_ON(kVerbose), OSP_LOG_STREAM(kVerbose))
|
||||
#define OSP_LOG_INFO \
|
||||
OSP_LAZY_STREAM(OSP_LOG_IS_ON(kInfo), OSP_LOG_STREAM(kInfo))
|
||||
#define OSP_LOG_WARN \
|
||||
OSP_LAZY_STREAM(OSP_LOG_IS_ON(kWarning), OSP_LOG_STREAM(kWarning))
|
||||
#define OSP_LOG_ERROR \
|
||||
OSP_LAZY_STREAM(OSP_LOG_IS_ON(kError), OSP_LOG_STREAM(kError))
|
||||
#define OSP_LOG_FATAL \
|
||||
OSP_LAZY_STREAM(OSP_LOG_IS_ON(kFatal), OSP_LOG_STREAM(kFatal))
|
||||
|
||||
#define OSP_VLOG_IF(condition) !(condition) ? (void)0 : OSP_VLOG
|
||||
#define OSP_LOG_IF(level, condition) !(condition) ? (void)0 : OSP_LOG_##level
|
||||
|
||||
#define OSP_CHECK(condition) \
|
||||
OSP_LOG_IF(FATAL, !(condition)) << "OSP_CHECK(" << #condition << ") failed: "
|
||||
|
||||
#define OSP_CHECK_EQ(a, b) \
|
||||
OSP_CHECK((a) == (b)) << (a) << " vs. " << (b) << ": "
|
||||
#define OSP_CHECK_NE(a, b) \
|
||||
OSP_CHECK((a) != (b)) << (a) << " vs. " << (b) << ": "
|
||||
#define OSP_CHECK_LT(a, b) OSP_CHECK((a) < (b)) << (a) << " vs. " << (b) << ": "
|
||||
#define OSP_CHECK_LE(a, b) \
|
||||
OSP_CHECK((a) <= (b)) << (a) << " vs. " << (b) << ": "
|
||||
#define OSP_CHECK_GT(a, b) OSP_CHECK((a) > (b)) << (a) << " vs. " << (b) << ": "
|
||||
#define OSP_CHECK_GE(a, b) \
|
||||
OSP_CHECK((a) >= (b)) << (a) << " vs. " << (b) << ": "
|
||||
|
||||
#if defined(_DEBUG) || defined(DCHECK_ALWAYS_ON)
|
||||
#define OSP_DCHECK_IS_ON() 1
|
||||
#define OSP_DCHECK(condition) OSP_CHECK(condition)
|
||||
#define OSP_DCHECK_EQ(a, b) OSP_CHECK_EQ(a, b)
|
||||
#define OSP_DCHECK_NE(a, b) OSP_CHECK_NE(a, b)
|
||||
#define OSP_DCHECK_LT(a, b) OSP_CHECK_LT(a, b)
|
||||
#define OSP_DCHECK_LE(a, b) OSP_CHECK_LE(a, b)
|
||||
#define OSP_DCHECK_GT(a, b) OSP_CHECK_GT(a, b)
|
||||
#define OSP_DCHECK_GE(a, b) OSP_CHECK_GE(a, b)
|
||||
#else
|
||||
#define OSP_DCHECK_IS_ON() 0
|
||||
// When DCHECKs are off, nothing will be logged. Use that fact to make
|
||||
// references to the `condition` expression (or `a` and `b`) so the compiler
|
||||
// won't emit unused variable warnings/errors when DCHECKs are turned off.
|
||||
#define OSP_EAT_STREAM OSP_LOG_IF(FATAL, false)
|
||||
#define OSP_DCHECK(condition) OSP_EAT_STREAM << !(condition)
|
||||
#define OSP_DCHECK_EQ(a, b) OSP_EAT_STREAM << !((a) == (b))
|
||||
#define OSP_DCHECK_NE(a, b) OSP_EAT_STREAM << !((a) != (b))
|
||||
#define OSP_DCHECK_LT(a, b) OSP_EAT_STREAM << !((a) < (b))
|
||||
#define OSP_DCHECK_LE(a, b) OSP_EAT_STREAM << !((a) <= (b))
|
||||
#define OSP_DCHECK_GT(a, b) OSP_EAT_STREAM << !((a) > (b))
|
||||
#define OSP_DCHECK_GE(a, b) OSP_EAT_STREAM << !((a) >= (b))
|
||||
#endif
|
||||
|
||||
#define OSP_DVLOG OSP_VLOG_IF(OSP_DCHECK_IS_ON())
|
||||
#define OSP_DLOG_INFO OSP_LOG_IF(INFO, OSP_DCHECK_IS_ON())
|
||||
#define OSP_DLOG_WARN OSP_LOG_IF(WARN, OSP_DCHECK_IS_ON())
|
||||
#define OSP_DLOG_ERROR OSP_LOG_IF(ERROR, OSP_DCHECK_IS_ON())
|
||||
#define OSP_DLOG_FATAL OSP_LOG_IF(FATAL, OSP_DCHECK_IS_ON())
|
||||
#define OSP_DVLOG_IF(condition) OSP_VLOG_IF(OSP_DCHECK_IS_ON() && (condition))
|
||||
#define OSP_DLOG_IF(level, condition) \
|
||||
OSP_LOG_IF(level, OSP_DCHECK_IS_ON() && (condition))
|
||||
|
||||
// Log when unimplemented code points are reached: If verbose logging is turned
|
||||
// on, log always. Otherwise, just attempt to log once.
|
||||
#define OSP_UNIMPLEMENTED() \
|
||||
if (OSP_LOG_IS_ON(kVerbose)) { \
|
||||
OSP_LOG_STREAM(kVerbose) << __func__ << ": UNIMPLEMENTED() hit."; \
|
||||
} else { \
|
||||
static bool needs_warning = true; \
|
||||
if (needs_warning) { \
|
||||
OSP_LOG_WARN << __func__ << ": UNIMPLEMENTED() hit."; \
|
||||
needs_warning = false; \
|
||||
} \
|
||||
}
|
||||
|
||||
// Since Break() is annotated as noreturn, this will properly signal to the
|
||||
// compiler that this code is truly not reached (and thus doesn't need a return
|
||||
// statement for non-void returning functions/methods).
|
||||
#define OSP_NOTREACHED() \
|
||||
{ \
|
||||
OSP_LOG_FATAL << __func__ << ": NOTREACHED() hit."; \
|
||||
Break(); \
|
||||
}
|
||||
|
||||
#endif // UTIL_OSP_LOGGING_H_
|
||||
441
breadcast-caststream-sys/vendor/openscreen/util/raw_ptr.h
vendored
Normal file
441
breadcast-caststream-sys/vendor/openscreen/util/raw_ptr.h
vendored
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
// Copyright 2026 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_RAW_PTR_H_
|
||||
#define UTIL_RAW_PTR_H_
|
||||
|
||||
// This header implements a conditional `raw_ptr` template.
|
||||
//
|
||||
// In Chromium builds (when `BUILD_WITH_CHROMIUM` is defined), it aliases
|
||||
// Chromium's `base::raw_ptr` (MiraclePtr / BackupRefPtr). This allows Open
|
||||
// Screen code to benefit from Chromium's UAF protection when running inside
|
||||
// Chrome.
|
||||
//
|
||||
// In standalone builds (e.g., embedded/IoT builds where dependencies must be
|
||||
// minimized and overhead must be zero), it provides a zero-overhead,
|
||||
// dependency-free polyfill that behaves like a standard raw pointer but
|
||||
// enforces initialization to `nullptr`.
|
||||
//
|
||||
// Note: Traits (like DanglingUntriaged or AllowPtrArithmetic) are intentionally
|
||||
// not supported in Open Screen to ensure code safety and compatibility.
|
||||
|
||||
#if defined(BUILD_WITH_CHROMIUM)
|
||||
|
||||
#include "partition_alloc/pointers/raw_ptr.h" // nogncheck
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// Alias the Chromium implementation, restricting it to not use traits.
|
||||
template <typename T>
|
||||
using raw_ptr = ::base::raw_ptr<T>;
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#else // !defined(BUILD_WITH_CHROMIUM)
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
// Optimization macros to ensure the polyfill truly has zero overhead at the ABI
|
||||
// level.
|
||||
#if defined(__clang__)
|
||||
#define OPENSCREEN_TRIVIAL_ABI [[clang::trivial_abi]]
|
||||
#else
|
||||
#define OPENSCREEN_TRIVIAL_ABI
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define OPENSCREEN_ALWAYS_INLINE __forceinline
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define OPENSCREEN_ALWAYS_INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define OPENSCREEN_ALWAYS_INLINE inline
|
||||
#endif
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// Standalone polyfill for `raw_ptr`.
|
||||
// It has zero runtime overhead compared to a raw pointer and compiles away.
|
||||
template <typename T>
|
||||
class OPENSCREEN_TRIVIAL_ABI raw_ptr {
|
||||
public:
|
||||
// Safety: auto-initialize to nullptr.
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr() noexcept : ptr_(nullptr) {}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr(
|
||||
std::nullptr_t) noexcept // NOLINT(runtime/explicit)
|
||||
: ptr_(nullptr) {}
|
||||
|
||||
// Implicit conversion from raw pointer.
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr(
|
||||
T* ptr) noexcept // NOLINT(runtime/explicit)
|
||||
: ptr_(ptr) {}
|
||||
|
||||
// Copy and Move constructors.
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr(const raw_ptr& other) noexcept =
|
||||
default;
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr(raw_ptr&& other) noexcept
|
||||
: ptr_(other.ptr_) {
|
||||
other.ptr_ = nullptr;
|
||||
}
|
||||
|
||||
// Templated copy/move constructors for upcasting (Derived -> Base).
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible_v<U*, T*> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr(
|
||||
const raw_ptr<U>& other) noexcept // NOLINT(runtime/explicit)
|
||||
: ptr_(other.get()) {}
|
||||
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible_v<U*, T*> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr(
|
||||
raw_ptr<U>&& other) noexcept // NOLINT(runtime/explicit)
|
||||
: ptr_(other.ptr_) {
|
||||
other.ptr_ = nullptr;
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr ~raw_ptr() noexcept { ptr_ = nullptr; }
|
||||
|
||||
// Assignment operators.
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr& operator=(
|
||||
const raw_ptr& other) noexcept = default;
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr& operator=(
|
||||
raw_ptr&& other) noexcept {
|
||||
if (this != &other) {
|
||||
ptr_ = other.ptr_;
|
||||
other.ptr_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr& operator=(T* ptr) noexcept {
|
||||
ptr_ = ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr& operator=(
|
||||
std::nullptr_t) noexcept {
|
||||
ptr_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Templated assignment operators for upcasting.
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible_v<U*, T*> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr& operator=(
|
||||
const raw_ptr<U>& other) noexcept {
|
||||
ptr_ = other.get();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible_v<U*, T*> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr& operator=(
|
||||
raw_ptr<U>&& other) noexcept {
|
||||
ptr_ = other.ptr_;
|
||||
other.ptr_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Pointer operations.
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr T* get() const noexcept { return ptr_; }
|
||||
|
||||
// Disable operator* for void types to prevent illegal void* dereferences and
|
||||
// void& signatures.
|
||||
template <typename U = T, typename = std::enable_if_t<!std::is_void_v<U> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr U& operator*() const noexcept {
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr T* operator->() const noexcept {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr operator T*() const noexcept {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr& operator+=(
|
||||
ptrdiff_t delta) noexcept {
|
||||
ptr_ += delta;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr& operator-=(
|
||||
ptrdiff_t delta) noexcept {
|
||||
ptr_ -= delta;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr operator+(
|
||||
ptrdiff_t delta) const noexcept {
|
||||
return raw_ptr(ptr_ + delta);
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ptr operator-(
|
||||
ptrdiff_t delta) const noexcept {
|
||||
return raw_ptr(ptr_ - delta);
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr explicit operator bool() const noexcept {
|
||||
return ptr_ != nullptr;
|
||||
}
|
||||
|
||||
// Swap helper.
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr void swap(raw_ptr& lhs,
|
||||
raw_ptr& rhs) noexcept {
|
||||
std::swap(lhs.ptr_, rhs.ptr_);
|
||||
}
|
||||
|
||||
// Comparison operators (raw_ptr OP raw_ptr<U>).
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator==(
|
||||
const raw_ptr& lhs,
|
||||
const raw_ptr<U>& rhs) noexcept {
|
||||
return lhs.ptr_ == rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator!=(
|
||||
const raw_ptr& lhs,
|
||||
const raw_ptr<U>& rhs) noexcept {
|
||||
return lhs.ptr_ != rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<(
|
||||
const raw_ptr& lhs,
|
||||
const raw_ptr<U>& rhs) noexcept {
|
||||
return lhs.ptr_ < rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>(
|
||||
const raw_ptr& lhs,
|
||||
const raw_ptr<U>& rhs) noexcept {
|
||||
return lhs.ptr_ > rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<=(
|
||||
const raw_ptr& lhs,
|
||||
const raw_ptr<U>& rhs) noexcept {
|
||||
return lhs.ptr_ <= rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>=(
|
||||
const raw_ptr& lhs,
|
||||
const raw_ptr<U>& rhs) noexcept {
|
||||
return lhs.ptr_ >= rhs.ptr_;
|
||||
}
|
||||
|
||||
// Comparison operators (raw_ptr OP U*).
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator==(const raw_ptr& lhs,
|
||||
U* rhs) noexcept {
|
||||
return lhs.ptr_ == rhs;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator!=(const raw_ptr& lhs,
|
||||
U* rhs) noexcept {
|
||||
return lhs.ptr_ != rhs;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<(const raw_ptr& lhs,
|
||||
U* rhs) noexcept {
|
||||
return lhs.ptr_ < rhs;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>(const raw_ptr& lhs,
|
||||
U* rhs) noexcept {
|
||||
return lhs.ptr_ > rhs;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<=(const raw_ptr& lhs,
|
||||
U* rhs) noexcept {
|
||||
return lhs.ptr_ <= rhs;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>=(const raw_ptr& lhs,
|
||||
U* rhs) noexcept {
|
||||
return lhs.ptr_ >= rhs;
|
||||
}
|
||||
|
||||
// Comparison operators (U* OP raw_ptr).
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator==(
|
||||
U* lhs,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return lhs == rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator!=(
|
||||
U* lhs,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return lhs != rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<(
|
||||
U* lhs,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return lhs < rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>(
|
||||
U* lhs,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return lhs > rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<=(
|
||||
U* lhs,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return lhs <= rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>=(
|
||||
U* lhs,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return lhs >= rhs.ptr_;
|
||||
}
|
||||
|
||||
// Comparison operators (raw_ptr OP nullptr).
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator==(
|
||||
const raw_ptr& lhs,
|
||||
std::nullptr_t) noexcept {
|
||||
return lhs.ptr_ == nullptr;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator!=(
|
||||
const raw_ptr& lhs,
|
||||
std::nullptr_t) noexcept {
|
||||
return lhs.ptr_ != nullptr;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<(
|
||||
const raw_ptr& lhs,
|
||||
std::nullptr_t) noexcept {
|
||||
return lhs.ptr_ < nullptr;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>(
|
||||
const raw_ptr& lhs,
|
||||
std::nullptr_t) noexcept {
|
||||
return lhs.ptr_ > nullptr;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<=(
|
||||
const raw_ptr& lhs,
|
||||
std::nullptr_t) noexcept {
|
||||
return lhs.ptr_ <= nullptr;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>=(
|
||||
const raw_ptr& lhs,
|
||||
std::nullptr_t) noexcept {
|
||||
return lhs.ptr_ >= nullptr;
|
||||
}
|
||||
|
||||
// Comparison operators (nullptr OP raw_ptr).
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator==(
|
||||
std::nullptr_t,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return nullptr == rhs.ptr_;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator!=(
|
||||
std::nullptr_t,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return nullptr != rhs.ptr_;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<(
|
||||
std::nullptr_t,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return nullptr < rhs.ptr_;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>(
|
||||
std::nullptr_t,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return nullptr > rhs.ptr_;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator<=(
|
||||
std::nullptr_t,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return nullptr <= rhs.ptr_;
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator>=(
|
||||
std::nullptr_t,
|
||||
const raw_ptr& rhs) noexcept {
|
||||
return nullptr >= rhs.ptr_;
|
||||
}
|
||||
|
||||
// Stream output helper.
|
||||
template <typename CharT, typename Traits>
|
||||
OPENSCREEN_ALWAYS_INLINE friend std::basic_ostream<CharT, Traits>& operator<<(
|
||||
std::basic_ostream<CharT, Traits>& os,
|
||||
const raw_ptr& ptr) {
|
||||
return os << ptr.ptr_;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename U>
|
||||
friend class raw_ptr;
|
||||
|
||||
#if defined(__clang__)
|
||||
[[clang::annotate("raw_ptr_exclusion")]]
|
||||
#endif
|
||||
T* ptr_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
namespace std {
|
||||
|
||||
// Override so map/set lookups work correctly.
|
||||
template <typename T>
|
||||
struct less<openscreen::raw_ptr<T> > {
|
||||
using is_transparent = void;
|
||||
|
||||
bool operator()(const openscreen::raw_ptr<T>& lhs,
|
||||
const openscreen::raw_ptr<T>& rhs) const {
|
||||
return lhs < rhs;
|
||||
}
|
||||
bool operator()(T* lhs, const openscreen::raw_ptr<T>& rhs) const {
|
||||
return lhs < rhs.get();
|
||||
}
|
||||
bool operator()(const openscreen::raw_ptr<T>& lhs, T* rhs) const {
|
||||
return lhs.get() < rhs;
|
||||
}
|
||||
};
|
||||
|
||||
// Override so unordered_map/unordered_set lookups work correctly.
|
||||
template <typename T>
|
||||
struct hash<openscreen::raw_ptr<T> > {
|
||||
using argument_type = openscreen::raw_ptr<T>;
|
||||
using result_type = std::size_t;
|
||||
result_type operator()(argument_type const& ptr) const {
|
||||
return hash<T*>()(ptr.get());
|
||||
}
|
||||
};
|
||||
|
||||
// Required for algorithms like std::to_address to unpack the pointer.
|
||||
template <typename T>
|
||||
struct pointer_traits<openscreen::raw_ptr<T> > {
|
||||
using pointer = openscreen::raw_ptr<T>;
|
||||
using element_type = T;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
template <typename U>
|
||||
using rebind = openscreen::raw_ptr<U>;
|
||||
|
||||
static constexpr pointer pointer_to(element_type& r) noexcept {
|
||||
return pointer(&r);
|
||||
}
|
||||
static constexpr element_type* to_address(pointer p) noexcept {
|
||||
return p.get();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // !defined(BUILD_WITH_CHROMIUM)
|
||||
|
||||
#endif // UTIL_RAW_PTR_H_
|
||||
122
breadcast-caststream-sys/vendor/openscreen/util/raw_ref.h
vendored
Normal file
122
breadcast-caststream-sys/vendor/openscreen/util/raw_ref.h
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright 2026 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_RAW_REF_H_
|
||||
#define UTIL_RAW_REF_H_
|
||||
|
||||
#if defined(BUILD_WITH_CHROMIUM)
|
||||
|
||||
#include "partition_alloc/pointers/raw_ref.h" // nogncheck
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
template <typename T>
|
||||
using raw_ref = ::base::raw_ref<T>;
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#else // !defined(BUILD_WITH_CHROMIUM)
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "util/raw_ptr.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
template <typename T>
|
||||
class raw_ref;
|
||||
|
||||
namespace internal {
|
||||
template <typename T>
|
||||
struct is_raw_ref : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_raw_ref<raw_ref<T> > : std::true_type {};
|
||||
} // namespace internal
|
||||
|
||||
template <typename T>
|
||||
class OPENSCREEN_TRIVIAL_ABI raw_ref {
|
||||
public:
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr explicit raw_ref(T& ref) noexcept
|
||||
: ptr_(&ref) {}
|
||||
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<
|
||||
!internal::is_raw_ref<std::decay_t<U> >::value &&
|
||||
std::is_convertible_v<U&, T&> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr explicit raw_ref(U& ref) noexcept
|
||||
: ptr_(&ref) {}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ref(const raw_ref& other) noexcept =
|
||||
default;
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ref(raw_ref&& other) noexcept =
|
||||
default;
|
||||
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible_v<U&, T&> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ref(const raw_ref<U>& other) noexcept
|
||||
: ptr_(other.ptr_) {}
|
||||
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible_v<U&, T&> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ref(raw_ref<U>&& other) noexcept
|
||||
: ptr_(std::move(other.ptr_)) {}
|
||||
|
||||
~raw_ref() = default;
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ref& operator=(
|
||||
const raw_ref& other) noexcept = default;
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ref& operator=(
|
||||
raw_ref&& other) noexcept = default;
|
||||
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible_v<U&, T&> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ref& operator=(
|
||||
const raw_ref<U>& other) noexcept {
|
||||
ptr_ = other.ptr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible_v<U&, T&> > >
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr raw_ref& operator=(
|
||||
raw_ref<U>&& other) noexcept {
|
||||
ptr_ = std::move(other.ptr_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr T& get() const noexcept { return *ptr_; }
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr T* operator->() const noexcept {
|
||||
return ptr_.get();
|
||||
}
|
||||
OPENSCREEN_ALWAYS_INLINE constexpr T& operator*() const noexcept {
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator==(
|
||||
const raw_ref& lhs,
|
||||
const raw_ref<U>& rhs) noexcept {
|
||||
return lhs.ptr_ == rhs.ptr_;
|
||||
}
|
||||
template <typename U>
|
||||
OPENSCREEN_ALWAYS_INLINE friend constexpr bool operator!=(
|
||||
const raw_ref& lhs,
|
||||
const raw_ref<U>& rhs) noexcept {
|
||||
return lhs.ptr_ != rhs.ptr_;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename U>
|
||||
friend class raw_ref;
|
||||
|
||||
raw_ptr<T> ptr_;
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // !defined(BUILD_WITH_CHROMIUM)
|
||||
|
||||
#endif // UTIL_RAW_REF_H_
|
||||
34
breadcast-caststream-sys/vendor/openscreen/util/read_file.cc
vendored
Normal file
34
breadcast-caststream-sys/vendor/openscreen/util/read_file.cc
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/read_file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
std::string ReadEntireFileToString(std::string_view filename) {
|
||||
FILE* file = fopen(filename.data(), "r");
|
||||
if (file == nullptr) {
|
||||
return {};
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
long file_size = ftell(file); // NOLINT
|
||||
fseek(file, 0, SEEK_SET);
|
||||
std::string contents(file_size, 0);
|
||||
int bytes_read = 0;
|
||||
while (bytes_read < file_size) {
|
||||
size_t ret = fread(&contents[bytes_read], 1, file_size - bytes_read, file);
|
||||
if (ret == 0 && ferror(file)) {
|
||||
return {};
|
||||
} else {
|
||||
bytes_read += ret;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
17
breadcast-caststream-sys/vendor/openscreen/util/read_file.h
vendored
Normal file
17
breadcast-caststream-sys/vendor/openscreen/util/read_file.h
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_READ_FILE_H_
|
||||
#define UTIL_READ_FILE_H_
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
std::string ReadEntireFileToString(std::string_view filename);
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_READ_FILE_H_
|
||||
145
breadcast-caststream-sys/vendor/openscreen/util/saturate_cast.h
vendored
Normal file
145
breadcast-caststream-sys/vendor/openscreen/util/saturate_cast.h
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_SATURATE_CAST_H_
|
||||
#define UTIL_SATURATE_CAST_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// Case 0: When To and From are the same type, saturate_cast<> is pass-through.
|
||||
template <typename To, typename From>
|
||||
constexpr std::enable_if_t<
|
||||
std::is_same<std::remove_cv<To>, std::remove_cv<From>>::value,
|
||||
To>
|
||||
saturate_cast(From from) {
|
||||
return from;
|
||||
}
|
||||
|
||||
// Because of the way C++ signed versus unsigned comparison works (i.e., the
|
||||
// type promotion strategy employed), extra care must be taken to range-check
|
||||
// the input value. For example, if the current architecture is 32-bits, then
|
||||
// any int32_t compared with a uint32_t will NOT promote to a int64_t↔int64_t
|
||||
// comparison. Instead, it will become a uint32_t↔uint32_t comparison (!),
|
||||
// which will sometimes produce invalid results.
|
||||
|
||||
// Case 1: "From" and "To" are either both signed, or are both unsigned. In
|
||||
// this case, the smaller of the two types will be promoted to match the
|
||||
// larger's size, and a valid comparison will be made.
|
||||
template <typename To, typename From>
|
||||
constexpr std::enable_if_t<
|
||||
std::is_integral<From>::value && std::is_integral<To>::value &&
|
||||
(std::is_signed<From>::value == std::is_signed<To>::value),
|
||||
To>
|
||||
saturate_cast(From from) {
|
||||
if (from <= std::numeric_limits<To>::min()) {
|
||||
return std::numeric_limits<To>::min();
|
||||
}
|
||||
if (from >= std::numeric_limits<To>::max()) {
|
||||
return std::numeric_limits<To>::max();
|
||||
}
|
||||
return static_cast<To>(from);
|
||||
}
|
||||
|
||||
// Case 2: "From" is signed, but "To" is unsigned.
|
||||
template <typename To, typename From>
|
||||
constexpr std::enable_if_t<
|
||||
std::is_integral<From>::value && std::is_integral<To>::value &&
|
||||
std::is_signed<From>::value && !std::is_signed<To>::value,
|
||||
To>
|
||||
saturate_cast(From from) {
|
||||
if (from <= From{0}) {
|
||||
return To{0};
|
||||
}
|
||||
if (static_cast<std::make_unsigned_t<From>>(from) >=
|
||||
std::numeric_limits<To>::max()) {
|
||||
return std::numeric_limits<To>::max();
|
||||
}
|
||||
return static_cast<To>(from);
|
||||
}
|
||||
|
||||
// Case 3: "From" is unsigned, but "To" is signed.
|
||||
template <typename To, typename From>
|
||||
constexpr std::enable_if_t<
|
||||
std::is_integral<From>::value && std::is_integral<To>::value &&
|
||||
!std::is_signed<From>::value && std::is_signed<To>::value,
|
||||
To>
|
||||
saturate_cast(From from) {
|
||||
if (from >= static_cast<typename std::make_unsigned_t<To>>(
|
||||
std::numeric_limits<To>::max())) {
|
||||
return std::numeric_limits<To>::max();
|
||||
}
|
||||
return static_cast<To>(from);
|
||||
}
|
||||
|
||||
// Case 4: "From" is a floating-point type, and "To" is an integer type (signed
|
||||
// or unsigned). The result is truncated, per the usual C++ float-to-int
|
||||
// conversion rules.
|
||||
template <typename To, typename From>
|
||||
constexpr std::enable_if_t<std::is_floating_point<From>::value &&
|
||||
std::is_integral<To>::value,
|
||||
To>
|
||||
saturate_cast(From from) {
|
||||
// Note: It's invalid to compare the argument against
|
||||
// std::numeric_limits<To>::max() because the latter, an integer value, will
|
||||
// be type-promoted to the floating-point type. The problem is that the
|
||||
// conversion is imprecise, as "max int" might not be exactly representable as
|
||||
// a floating-point value (depending on the actual types of From and To).
|
||||
//
|
||||
// Thus, the strategy is to compare only floating-point values/constants to
|
||||
// determine whether the bounds of the range of integers has been exceeded.
|
||||
// Two assumptions here: 1) "To" is either unsigned, or is a 2's complement
|
||||
// signed integer type. 2) "From" is a floating-point type that can exactly
|
||||
// represent all powers of 2 within its value range.
|
||||
static_assert((~To(1) + To(1)) == To(-1), "assumed 2's complement integers");
|
||||
constexpr From kMaxIntPlusOne =
|
||||
From(To(1) << (std::numeric_limits<To>::digits - 1)) * From(2);
|
||||
constexpr From kMaxInt = kMaxIntPlusOne - 1;
|
||||
// Note: In some cases, the kMaxInt constant will equal kMaxIntPlusOne because
|
||||
// there isn't an exact floating-point representation for 2^N - 1. That said,
|
||||
// the following upper-bound comparison is still valid because all
|
||||
// floating-point values less than 2^N would also be less than 2^N - 1.
|
||||
if (from >= kMaxInt) {
|
||||
return std::numeric_limits<To>::max();
|
||||
}
|
||||
if (std::is_signed<To>::value) {
|
||||
constexpr From kMinInt = -kMaxIntPlusOne;
|
||||
if (from <= kMinInt) {
|
||||
return std::numeric_limits<To>::min();
|
||||
}
|
||||
} else /* if To is unsigned */ {
|
||||
if (from <= From(0)) {
|
||||
return To(0);
|
||||
}
|
||||
}
|
||||
return static_cast<To>(from);
|
||||
}
|
||||
|
||||
// Like saturate_cast<>, but rounds to the nearest integer instead of
|
||||
// truncating.
|
||||
template <typename To, typename From>
|
||||
constexpr std::enable_if_t<std::is_floating_point<From>::value &&
|
||||
std::is_integral<To>::value,
|
||||
To>
|
||||
rounded_saturate_cast(From from) {
|
||||
const To saturated = saturate_cast<To>(from);
|
||||
if (saturated == std::numeric_limits<To>::min() ||
|
||||
saturated == std::numeric_limits<To>::max()) {
|
||||
return saturated;
|
||||
}
|
||||
|
||||
static_assert(sizeof(To) <= sizeof(decltype(llround(from))),
|
||||
"No version of lround() for the required range of values.");
|
||||
if (sizeof(To) <= sizeof(decltype(lround(from)))) {
|
||||
return static_cast<To>(lround(from));
|
||||
}
|
||||
return static_cast<To>(llround(from));
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_SATURATE_CAST_H_
|
||||
12
breadcast-caststream-sys/vendor/openscreen/util/scoped_wake_lock.cc
vendored
Normal file
12
breadcast-caststream-sys/vendor/openscreen/util/scoped_wake_lock.cc
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/scoped_wake_lock.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
ScopedWakeLock::ScopedWakeLock() = default;
|
||||
ScopedWakeLock::~ScopedWakeLock() = default;
|
||||
|
||||
} // namespace openscreen
|
||||
46
breadcast-caststream-sys/vendor/openscreen/util/scoped_wake_lock.h
vendored
Normal file
46
breadcast-caststream-sys/vendor/openscreen/util/scoped_wake_lock.h
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_SCOPED_WAKE_LOCK_H_
|
||||
#define UTIL_SCOPED_WAKE_LOCK_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "platform/api/task_runner.h"
|
||||
#include "platform/api/task_runner_deleter.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// Ensures that the device does not got to sleep. This is used, for example,
|
||||
// while Open Screen is communicating with peers over the network for things
|
||||
// like media streaming.
|
||||
//
|
||||
// The wake lock is RAII: It is automatically engaged when the ScopedWakeLock is
|
||||
// created and released when the ScopedWakeLock is destroyed. Open Screen code
|
||||
// may sometimes create multiple instances. In that case, the wake lock should
|
||||
// be engaged upon creating the first instance, and then held until all
|
||||
// instances have been destroyed.
|
||||
//
|
||||
// TODO(issuetracker.google.com/288311411): Implement for Linux.
|
||||
|
||||
class ScopedWakeLock;
|
||||
using ScopedWakeLockPtr = std::unique_ptr<ScopedWakeLock, TaskRunnerDeleter>;
|
||||
|
||||
class ScopedWakeLock {
|
||||
public:
|
||||
static ScopedWakeLockPtr Create(TaskRunner& task_runner);
|
||||
|
||||
// Instances are not copied nor moved.
|
||||
ScopedWakeLock(const ScopedWakeLock&) = delete;
|
||||
ScopedWakeLock(ScopedWakeLock&&) noexcept = delete;
|
||||
ScopedWakeLock& operator=(const ScopedWakeLock&) = delete;
|
||||
ScopedWakeLock& operator=(ScopedWakeLock&&) noexcept = delete;
|
||||
|
||||
ScopedWakeLock();
|
||||
virtual ~ScopedWakeLock();
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_SCOPED_WAKE_LOCK_H_
|
||||
52
breadcast-caststream-sys/vendor/openscreen/util/simple_fraction.cc
vendored
Normal file
52
breadcast-caststream-sys/vendor/openscreen/util/simple_fraction.cc
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/simple_fraction.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
#include "util/string_parse.h"
|
||||
#include "util/string_util.h"
|
||||
#include "util/stringprintf.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// static
|
||||
ErrorOr<SimpleFraction> SimpleFraction::FromString(std::string_view value) {
|
||||
if (value.size() > 0 && value.at(0) == '/') {
|
||||
return Error::Code::kParameterInvalid;
|
||||
}
|
||||
|
||||
std::vector<std::string_view> fields = string_util::Split(value, '/');
|
||||
if (fields.size() != 1 && fields.size() != 2) {
|
||||
return Error::Code::kParameterInvalid;
|
||||
}
|
||||
|
||||
int numerator;
|
||||
int denominator = 1;
|
||||
if (!string_parse::ParseAsciiNumber(fields[0], numerator)) {
|
||||
return Error::Code::kParameterInvalid;
|
||||
}
|
||||
|
||||
if (fields.size() == 2) {
|
||||
if (!string_parse::ParseAsciiNumber(fields[1], denominator)) {
|
||||
return Error::Code::kParameterInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
return SimpleFraction(numerator, denominator);
|
||||
}
|
||||
|
||||
std::string SimpleFraction::ToString() const {
|
||||
if (denominator_ == 1) {
|
||||
return std::to_string(numerator_);
|
||||
}
|
||||
return StringFormat("{}/{}", numerator_, denominator_);
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
73
breadcast-caststream-sys/vendor/openscreen/util/simple_fraction.h
vendored
Normal file
73
breadcast-caststream-sys/vendor/openscreen/util/simple_fraction.h
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_SIMPLE_FRACTION_H_
|
||||
#define UTIL_SIMPLE_FRACTION_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "platform/base/error.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// SimpleFraction is used to represent simple (or "common") fractions, composed
|
||||
// of a rational number written a/b where a and b are both integers.
|
||||
// Some helpful notes on SimpleFraction assumptions/limitations:
|
||||
// 1. SimpleFraction does not perform reductions. 2/4 != 1/2, and -1/-1 != 1/1.
|
||||
// 2. denominator = 0 is considered undefined.
|
||||
// 3. numerator = saturates range to int min or int max
|
||||
// 4. A SimpleFraction is "positive" if and only if it is defined and at least
|
||||
// equal to zero. Since reductions are not performed, -1/-1 is negative.
|
||||
class SimpleFraction {
|
||||
public:
|
||||
static ErrorOr<SimpleFraction> FromString(std::string_view value);
|
||||
std::string ToString() const;
|
||||
|
||||
constexpr SimpleFraction() = default;
|
||||
constexpr SimpleFraction(int numerator) // NOLINT
|
||||
: numerator_(numerator) {}
|
||||
constexpr SimpleFraction(int numerator, int denominator)
|
||||
: numerator_(numerator), denominator_(denominator) {}
|
||||
|
||||
constexpr SimpleFraction(const SimpleFraction&) = default;
|
||||
constexpr SimpleFraction(SimpleFraction&&) noexcept = default;
|
||||
constexpr SimpleFraction& operator=(const SimpleFraction&) = default;
|
||||
constexpr SimpleFraction& operator=(SimpleFraction&&) = default;
|
||||
~SimpleFraction() = default;
|
||||
|
||||
constexpr bool operator==(const SimpleFraction& other) const {
|
||||
return numerator_ == other.numerator_ && denominator_ == other.denominator_;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const SimpleFraction& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
constexpr bool is_defined() const { return denominator_ != 0; }
|
||||
|
||||
constexpr bool is_positive() const {
|
||||
return (numerator_ >= 0) && (denominator_ > 0);
|
||||
}
|
||||
|
||||
constexpr explicit operator double() const {
|
||||
if (denominator_ == 0) {
|
||||
return nan("");
|
||||
}
|
||||
return static_cast<double>(numerator_) / static_cast<double>(denominator_);
|
||||
}
|
||||
|
||||
constexpr int numerator() const { return numerator_; }
|
||||
constexpr int denominator() const { return denominator_; }
|
||||
|
||||
private:
|
||||
int numerator_ = 0;
|
||||
int denominator_ = 1;
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_SIMPLE_FRACTION_H_
|
||||
20
breadcast-caststream-sys/vendor/openscreen/util/std_util.cc
vendored
Normal file
20
breadcast-caststream-sys/vendor/openscreen/util/std_util.cc
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2023 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/std_util.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
std::string& RemoveWhitespace(std::string& s) {
|
||||
s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
104
breadcast-caststream-sys/vendor/openscreen/util/std_util.h
vendored
Normal file
104
breadcast-caststream-sys/vendor/openscreen/util/std_util.h
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_STD_UTIL_H_
|
||||
#define UTIL_STD_UTIL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "util/stringprintf.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
template <typename T, size_t N>
|
||||
constexpr size_t countof(T (&array)[N]) {
|
||||
return N;
|
||||
}
|
||||
|
||||
// Removes ALL whitespace in place from the string, based on the present C
|
||||
// locale. This includes spaces, tabs, and returns. This is useful for string
|
||||
// comparisons where whitespace doesn't matter, or, in the case of JSON
|
||||
// serialization, is dependent on build configuration and other settings.
|
||||
std::string& RemoveWhitespace(std::string& s);
|
||||
|
||||
template <typename Key, typename Value>
|
||||
void RemoveValueFromMap(std::map<Key, Value*>* map, Value* value) {
|
||||
for (auto it = map->begin(); it != map->end();) {
|
||||
if (it->second == value) {
|
||||
it = map->erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ForwardIteratingContainer>
|
||||
bool AreElementsSortedAndUnique(const ForwardIteratingContainer& c) {
|
||||
return std::is_sorted(c.begin(), c.end()) &&
|
||||
std::adjacent_find(c.begin(), c.end()) == c.end();
|
||||
}
|
||||
|
||||
template <typename RandomAccessContainer>
|
||||
void SortAndDedupeElements(RandomAccessContainer* c) {
|
||||
std::sort(c->begin(), c->end());
|
||||
const auto new_end = std::unique(c->begin(), c->end());
|
||||
c->erase(new_end, c->end());
|
||||
}
|
||||
|
||||
// Append the provided elements together into a single vector. This can be
|
||||
// useful when creating a vector of variadic templates in the ctor.
|
||||
//
|
||||
// This is the base case for the recursion
|
||||
template <typename T>
|
||||
std::vector<T>&& Append(std::vector<T>&& so_far) {
|
||||
return std::move(so_far);
|
||||
}
|
||||
|
||||
// This is the recursive call. Depending on the number of remaining elements, it
|
||||
// either calls into itself or into the above base case.
|
||||
template <typename T, typename TFirst, typename... TOthers>
|
||||
std::vector<T>&& Append(std::vector<T>&& so_far,
|
||||
TFirst&& new_element,
|
||||
TOthers&&... new_elements) {
|
||||
so_far.push_back(std::move(new_element));
|
||||
return Append(std::move(so_far), std::move(new_elements)...);
|
||||
}
|
||||
|
||||
// Creates an empty vector with `size` elements reserved. Intended to be used as
|
||||
// GetEmptyVectorOfSize<T>(sizeof...(variadic_input))
|
||||
template <typename T>
|
||||
std::vector<T> GetVectorWithCapacity(size_t size) {
|
||||
std::vector<T> results;
|
||||
results.reserve(size);
|
||||
return results;
|
||||
}
|
||||
|
||||
// Returns true if an element equal to `element` is found in `container`.
|
||||
// C.begin() must return an iterator to the beginning of C and C.end() must
|
||||
// return an iterator to the end.
|
||||
template <typename C, typename E>
|
||||
bool Contains(const C& container, const E& element) {
|
||||
return std::find(container.begin(), container.end(), element) !=
|
||||
container.end();
|
||||
}
|
||||
|
||||
// Returns true if any element in `container` returns true for `predicate`.
|
||||
// C.begin() must return an iterator to the beginning of C and C.end() must
|
||||
// return an iterator to the end.
|
||||
template <typename C, typename P>
|
||||
bool ContainsIf(const C& container, P predicate) {
|
||||
return std::find_if(container.begin(), container.end(),
|
||||
std::move(predicate)) != container.end();
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_STD_UTIL_H_
|
||||
32
breadcast-caststream-sys/vendor/openscreen/util/string_parse.h
vendored
Normal file
32
breadcast-caststream-sys/vendor/openscreen/util/string_parse.h
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_STRING_PARSE_H_
|
||||
#define UTIL_STRING_PARSE_H_
|
||||
|
||||
#include <charconv>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <system_error>
|
||||
|
||||
#include "platform/base/type_util.h"
|
||||
|
||||
namespace openscreen::string_parse {
|
||||
|
||||
// Parses `number` into the numeric type `result` and returns true if
|
||||
// successful. `number` must be an ASCII representation of an integer or
|
||||
// floating point value, and `result` must be compatible with the resulting
|
||||
// value. If `number` cannot be parsed, then returns false.
|
||||
template <typename T, typename = internal::EnableIfArithmetic<T>>
|
||||
bool ParseAsciiNumber(std::string_view number, T& result) {
|
||||
if (number.empty())
|
||||
return false;
|
||||
auto [unused_ptr, error_code] =
|
||||
std::from_chars(number.data(), &number.back() + 1, result);
|
||||
return error_code == std::errc();
|
||||
}
|
||||
|
||||
} // namespace openscreen::string_parse
|
||||
|
||||
#endif // UTIL_STRING_PARSE_H_
|
||||
160
breadcast-caststream-sys/vendor/openscreen/util/string_util.cc
vendored
Normal file
160
breadcast-caststream-sys/vendor/openscreen/util/string_util.cc
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// Copyright 2023 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/string_util.h"
|
||||
|
||||
#include <functional>
|
||||
#include <ranges>
|
||||
|
||||
namespace openscreen::string_util {
|
||||
namespace internal {
|
||||
// clang-format off
|
||||
// Array of bitfields holding character information. Note that bitfields for all
|
||||
// characters above ASCII 127 are zero-initialized.
|
||||
// Position Meaning
|
||||
// -------- -------
|
||||
// 1 alphabetic
|
||||
// 2 alphanumeric
|
||||
// 3 whitespace
|
||||
// 4 punctuation
|
||||
// 5 tab or space
|
||||
// 6 control character
|
||||
// 7 hex digit
|
||||
const unsigned char kPropertyBits[256] = {
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
|
||||
0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
|
||||
0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, // 0x30
|
||||
0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50
|
||||
0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70
|
||||
0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,
|
||||
};
|
||||
|
||||
// Array of characters for the ascii_tolower() function.
|
||||
const char kToLower[256] = {
|
||||
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
|
||||
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
|
||||
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
|
||||
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
|
||||
'\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
|
||||
'\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
|
||||
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
|
||||
'\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
|
||||
'\x40', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
||||
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
|
||||
'x', 'y', 'z', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
|
||||
'\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
|
||||
'\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
|
||||
'\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
|
||||
'\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
|
||||
'\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
|
||||
'\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
|
||||
'\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
|
||||
'\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
|
||||
'\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
|
||||
'\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
|
||||
'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
|
||||
'\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
|
||||
'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
|
||||
'\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
|
||||
'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
|
||||
'\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
|
||||
'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
|
||||
'\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
|
||||
'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
|
||||
'\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
|
||||
};
|
||||
|
||||
// Array of characters for the ascii_toupper() function.
|
||||
const char kToUpper[256] = {
|
||||
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
|
||||
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
|
||||
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
|
||||
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
|
||||
'\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
|
||||
'\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
|
||||
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
|
||||
'\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
|
||||
'\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
|
||||
'\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
|
||||
'\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
|
||||
'\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
|
||||
'\x60', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||
'X', 'Y', 'Z', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
|
||||
'\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
|
||||
'\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
|
||||
'\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
|
||||
'\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
|
||||
'\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
|
||||
'\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
|
||||
'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
|
||||
'\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
|
||||
'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
|
||||
'\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
|
||||
'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
|
||||
'\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
|
||||
'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
|
||||
'\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
|
||||
'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
|
||||
'\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
|
||||
};
|
||||
// clang-format on
|
||||
} // namespace internal
|
||||
|
||||
void AsciiStrToLower(std::string& s) {
|
||||
for (auto& c : s)
|
||||
c = ascii_tolower(c);
|
||||
}
|
||||
|
||||
std::string AsciiStrToLower(std::string_view s) {
|
||||
std::string result(s);
|
||||
AsciiStrToLower(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void AsciiStrToUpper(std::string& s) {
|
||||
for (auto& c : s)
|
||||
c = ascii_toupper(c);
|
||||
}
|
||||
|
||||
std::string AsciiStrToUpper(std::string_view s) {
|
||||
std::string result(s);
|
||||
AsciiStrToUpper(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool EqualsIgnoreCase(std::string_view a, std::string_view b) {
|
||||
// std::ranges::equal checks size() automatically for random-access ranges
|
||||
// like std::string_view.
|
||||
return std::ranges::equal(
|
||||
a, b, std::equal_to<>{}, // 1. The Predicate: Compare for equality
|
||||
ascii_tolower, // 2. Projection for piece1
|
||||
ascii_tolower // 3. Projection for piece2
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<std::string_view> Split(std::string_view value,
|
||||
char delim) {
|
||||
auto tokens = value | std::views::split(delim) |
|
||||
std::views::filter([](auto&& r) { return !r.empty(); });
|
||||
std::vector<std::string_view> result;
|
||||
for (auto&& token : tokens) {
|
||||
result.emplace_back(token.begin(), token.end());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace openscreen::string_util
|
||||
142
breadcast-caststream-sys/vendor/openscreen/util/string_util.h
vendored
Normal file
142
breadcast-caststream-sys/vendor/openscreen/util/string_util.h
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright 2023 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_STRING_UTIL_H_
|
||||
#define UTIL_STRING_UTIL_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <numeric>
|
||||
#include <ranges>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
// String query and manipulation utilities.
|
||||
// TODO(jophba): remove nested string_util namespace.
|
||||
namespace openscreen::string_util {
|
||||
|
||||
namespace internal {
|
||||
|
||||
extern const unsigned char kPropertyBits[256];
|
||||
extern const char kToLower[256];
|
||||
extern const char kToUpper[256];
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Determines whether `c` is a valid ASCII alphabetic character code.
|
||||
inline bool ascii_isalpha(unsigned char c) {
|
||||
return (internal::kPropertyBits[c] & 0x01) != 0;
|
||||
}
|
||||
|
||||
// Determines whether `c` is a valid ASCII decimal digit (i.e. [0-9]).
|
||||
inline bool ascii_isdigit(unsigned char c) {
|
||||
return '0' <= c && c <= '9';
|
||||
}
|
||||
|
||||
// Determines whether `c` is a valid ASCII lower case hexadecimal digit
|
||||
// (i.e. [a-fA-F0-9]).
|
||||
inline bool ascii_islowerhex(unsigned char c) {
|
||||
return ascii_isdigit(c) || ('a' <= c && c <= 'f');
|
||||
}
|
||||
|
||||
// Determines whether `c` is a valid ASCII hexadecimal digit (i.e. [a-fA-F0-9]).
|
||||
inline bool ascii_ishex(unsigned char c) {
|
||||
return ascii_islowerhex(c) || ('A' <= c && c <= 'F');
|
||||
}
|
||||
|
||||
// Determines whether `c` is a valid, printable ASCII digit.
|
||||
inline bool ascii_isprint(unsigned char c) {
|
||||
return c >= 32 && c < 127;
|
||||
}
|
||||
|
||||
// Determines whether `c` is a whitespace character
|
||||
// (space, tab, vertical tab, formfeed, linefeed, or carriage return).
|
||||
inline bool ascii_isspace(unsigned char c) {
|
||||
return (internal::kPropertyBits[c] & 0x08) != 0;
|
||||
}
|
||||
|
||||
// If `c` is an upper case ASCII character, returns its lower case equivalent.
|
||||
// Otherwise, returns `c` unchanged.
|
||||
inline char ascii_tolower(unsigned char c) {
|
||||
return internal::kToLower[c];
|
||||
}
|
||||
|
||||
// Converts `s` to lowercase.
|
||||
void AsciiStrToLower(std::string& s);
|
||||
|
||||
// Creates a lowercase string from a given string_view.
|
||||
std::string AsciiStrToLower(std::string_view s);
|
||||
|
||||
inline char ascii_toupper(unsigned char c) {
|
||||
return internal::kToUpper[c];
|
||||
}
|
||||
|
||||
// Converts `s` to uppercase.
|
||||
void AsciiStrToUpper(std::string& s);
|
||||
|
||||
// Creates a uppercase string from a given string_view.
|
||||
std::string AsciiStrToUpper(std::string_view s);
|
||||
|
||||
// Returns whether given ASCII strings `a` and `b` are equal, ignoring
|
||||
// case in the comparison.
|
||||
[[nodiscard]] bool EqualsIgnoreCase(std::string_view a, std::string_view b);
|
||||
|
||||
// Returns std::string_view with whitespace stripped from the beginning of the
|
||||
// given string_view.
|
||||
inline std::string_view StripLeadingAsciiWhitespace(std::string_view str) {
|
||||
auto it = std::find_if_not(str.cbegin(), str.cend(), ascii_isspace);
|
||||
return str.substr(static_cast<size_t>(it - str.begin()));
|
||||
}
|
||||
|
||||
// Concatenates arguments into a single string.
|
||||
[[nodiscard]] constexpr std::string StrCat(
|
||||
std::initializer_list<std::string_view> pieces) {
|
||||
// Prefer a loop over std::accumulate since it is not constexpr in C++20.
|
||||
size_t length = 0;
|
||||
for (const auto& piece : pieces) {
|
||||
length += piece.size();
|
||||
}
|
||||
|
||||
std::string result;
|
||||
result.reserve(length);
|
||||
for (const auto& piece : pieces) {
|
||||
result.append(piece);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Splits `value` into tokens separated by `delim`. Leading and trailing
|
||||
// delimeters are stripped, and multiple consecutive delimeters are treated as
|
||||
// one.
|
||||
[[nodiscard]] std::vector<std::string_view> Split(std::string_view value,
|
||||
char delim);
|
||||
|
||||
template <std::ranges::input_range R>
|
||||
[[nodiscard]] std::string Join(R&& range, std::string_view delimeter = ", ") {
|
||||
if (std::ranges::empty(range)) {
|
||||
return {};
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << range.front();
|
||||
for (auto element : range | std::views::drop(1)) {
|
||||
ss << delimeter << element;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Returns a string made by concatenating the strings iterated by `[begin,
|
||||
// end)`, each separated by `delim`.
|
||||
template <typename Iterator>
|
||||
[[nodiscard]] std::string Join(Iterator begin,
|
||||
Iterator end,
|
||||
std::string_view delimeter = ", ") {
|
||||
return Join(std::ranges::subrange{begin, end}, delimeter);
|
||||
}
|
||||
|
||||
} // namespace openscreen::string_util
|
||||
|
||||
#endif // UTIL_STRING_UTIL_H_
|
||||
29
breadcast-caststream-sys/vendor/openscreen/util/stringprintf.cc
vendored
Normal file
29
breadcast-caststream-sys/vendor/openscreen/util/stringprintf.cc
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/stringprintf.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
std::string HexEncode(const uint8_t* bytes, size_t len) {
|
||||
return HexEncode(ByteView(bytes, len));
|
||||
}
|
||||
|
||||
std::string HexEncode(ByteView bytes) {
|
||||
std::ostringstream hex_dump;
|
||||
hex_dump << std::setfill('0') << std::hex;
|
||||
for (uint8_t byte : bytes) {
|
||||
hex_dump << std::setw(2) << static_cast<int>(byte);
|
||||
}
|
||||
return hex_dump.str();
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
33
breadcast-caststream-sys/vendor/openscreen/util/stringprintf.h
vendored
Normal file
33
breadcast-caststream-sys/vendor/openscreen/util/stringprintf.h
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_STRINGPRINTF_H_
|
||||
#define UTIL_STRINGPRINTF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <format>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "platform/base/span.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// TODO(crbug.com/364687926): remove and replace with direct calls to
|
||||
// std::format now that we are on C++20.
|
||||
template <typename... Args>
|
||||
[[nodiscard]] std::string StringFormat(std::format_string<Args...> fmt,
|
||||
Args&&... args) {
|
||||
return std::format(fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Returns a hex string representation of the given `bytes`.
|
||||
std::string HexEncode(const uint8_t* bytes, size_t len);
|
||||
std::string HexEncode(ByteView bytes);
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_STRINGPRINTF_H_
|
||||
50
breadcast-caststream-sys/vendor/openscreen/util/thread_annotations.h
vendored
Normal file
50
breadcast-caststream-sys/vendor/openscreen/util/thread_annotations.h
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2026 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_THREAD_ANNOTATIONS_H_
|
||||
#define UTIL_THREAD_ANNOTATIONS_H_
|
||||
|
||||
#if defined(__clang__) && !defined(SWIG)
|
||||
#define OSP_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||
#else
|
||||
#define OSP_THREAD_ANNOTATION_ATTRIBUTE__(x)
|
||||
#endif
|
||||
|
||||
#define OSP_GUARDED_BY(x) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
||||
|
||||
#define OSP_PT_GUARDED_BY(x) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
|
||||
|
||||
#define OSP_EXCLUSIVE_LOCKS_REQUIRED(...) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
|
||||
|
||||
#define OSP_SHARED_LOCKS_REQUIRED(...) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
|
||||
|
||||
#define OSP_EXCLUSIVE_LOCK_FUNCTION(...) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
|
||||
|
||||
#define OSP_SHARED_LOCK_FUNCTION(...) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
|
||||
|
||||
#define OSP_UNLOCK_FUNCTION(...) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
|
||||
|
||||
#define OSP_LOCKS_EXCLUDED(...) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
|
||||
|
||||
#define OSP_LOCK_RETURNED(x) \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||
|
||||
#define OSP_LOCKABLE \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(lockable)
|
||||
|
||||
#define OSP_SCOPED_LOCKABLE \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||
|
||||
#define OSP_NO_THREAD_SAFETY_ANALYSIS \
|
||||
OSP_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
||||
|
||||
#endif // UTIL_THREAD_ANNOTATIONS_H_
|
||||
282
breadcast-caststream-sys/vendor/openscreen/util/trace_logging.h
vendored
Normal file
282
breadcast-caststream-sys/vendor/openscreen/util/trace_logging.h
vendored
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_TRACE_LOGGING_H_
|
||||
#define UTIL_TRACE_LOGGING_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "platform/base/trace_logging_types.h"
|
||||
|
||||
// All compile-time macros for tracing.
|
||||
// NOTE: The ternary operator is used here to ensure that the TraceLogger object
|
||||
// is only constructed if tracing is enabled, but at the same time is created in
|
||||
// the caller's scope. The C++ standards guide guarantees that the constructor
|
||||
// should only be called when IsTraceLoggingEnabled(...) evaluates to true.
|
||||
// static_cast calls are used because if the type of the result of the ternary
|
||||
// operator does not match the expected type, temporary storage is used for the
|
||||
// created object, which results in an extra call to the constructor and
|
||||
// destructor of the tracing objects.
|
||||
//
|
||||
// Further details about how these macros are used can be found in
|
||||
// docs/trace_logging.md.
|
||||
|
||||
#if defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
#define INCLUDING_FROM_UTIL_TRACE_LOGGING_H_
|
||||
#include "util/trace_logging/macro_support.h"
|
||||
#undef INCLUDING_FROM_UTIL_TRACE_LOGGING_H_
|
||||
|
||||
#define TRACE_SET_RESULT(result) \
|
||||
do { \
|
||||
if (TRACE_IS_ENABLED(openscreen::TraceCategory::kAny)) { \
|
||||
openscreen::internal::ScopedTraceOperation::set_result(result); \
|
||||
} \
|
||||
} while (false)
|
||||
#define TRACE_SET_HIERARCHY(ids) TRACE_SET_HIERARCHY_INTERNAL(__LINE__, ids)
|
||||
#define TRACE_HIERARCHY \
|
||||
(TRACE_IS_ENABLED(openscreen::TraceCategory::kAny) \
|
||||
? openscreen::internal::ScopedTraceOperation::hierarchy() \
|
||||
: openscreen::TraceIdHierarchy::Empty())
|
||||
#define TRACE_CURRENT_ID \
|
||||
(TRACE_IS_ENABLED(openscreen::TraceCategory::kAny) \
|
||||
? openscreen::internal::ScopedTraceOperation::current_id() \
|
||||
: kEmptyTraceId)
|
||||
#define TRACE_ROOT_ID \
|
||||
(TRACE_IS_ENABLED(openscreen::TraceCategory::kAny) \
|
||||
? openscreen::internal::ScopedTraceOperation::root_id() \
|
||||
: kEmptyTraceId)
|
||||
|
||||
namespace openscreen::internal {
|
||||
|
||||
template <typename T>
|
||||
std::string ToString(T&& val) {
|
||||
using DecayT = std::decay_t<T>;
|
||||
if constexpr (std::is_constructible_v<std::string, T>) {
|
||||
return std::string(std::forward<T>(val));
|
||||
} else if constexpr (std::is_arithmetic_v<DecayT>) {
|
||||
return std::to_string(val);
|
||||
} else {
|
||||
std::ostringstream oss;
|
||||
oss << val;
|
||||
return oss.str();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to extract a flow ID from various types (arithmetic or wrappers like
|
||||
// FrameId).
|
||||
template <typename T>
|
||||
constexpr uint64_t ToFlowId(const T& val) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
return static_cast<uint64_t>(val);
|
||||
} else {
|
||||
// Assume it's a numeric wrapper like FrameId with a .value() method.
|
||||
return static_cast<uint64_t>(val.value());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openscreen::internal
|
||||
|
||||
template <typename V1 = std::string, typename V2 = std::string>
|
||||
inline std::vector<openscreen::TraceEvent::Argument> ToArgumentArray(
|
||||
const char* argname = nullptr,
|
||||
V1&& argval = V1(),
|
||||
const char* argname_two = nullptr,
|
||||
V2&& argval_two = V2()) {
|
||||
std::vector<openscreen::TraceEvent::Argument> out;
|
||||
if (argname) {
|
||||
out.emplace_back(argname,
|
||||
openscreen::internal::ToString(std::forward<V1>(argval)));
|
||||
}
|
||||
if (argname_two) {
|
||||
out.emplace_back(argname_two, openscreen::internal::ToString(
|
||||
std::forward<V2>(argval_two)));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Synchronous Trace Macros.
|
||||
//
|
||||
// Scoped traces with no arguments.
|
||||
#define TRACE_SCOPED(category, name, ...) \
|
||||
TRACE_SCOPED_INTERNAL(__LINE__, category, name, ToArgumentArray(), \
|
||||
##__VA_ARGS__)
|
||||
#define TRACE_DEFAULT_SCOPED(category, ...) \
|
||||
TRACE_SCOPED(category, __PRETTY_FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
// Scoped traces with one argument.
|
||||
#define TRACE_SCOPED1(category, name, argname, argval, ...) \
|
||||
TRACE_SCOPED_INTERNAL(__LINE__, category, name, \
|
||||
ToArgumentArray(argname, argval), ##__VA_ARGS__)
|
||||
#define TRACE_DEFAULT_SCOPED1(category, argname, argval, ...) \
|
||||
TRACE_SCOPED1(category, __PRETTY_FUNCTION__, argname, argval, ##__VA_ARGS__)
|
||||
|
||||
// Scoped traces with two arguments.
|
||||
#define TRACE_SCOPED2(category, name, argname, argval, argname_two, \
|
||||
argval_two, ...) \
|
||||
TRACE_SCOPED_INTERNAL( \
|
||||
__LINE__, category, name, \
|
||||
ToArgumentArray(argname, argval, argname_two, argval_two), \
|
||||
##__VA_ARGS__)
|
||||
#define TRACE_DEFAULT_SCOPED2(category, argname, argval, argname_two, \
|
||||
argval_two, ...) \
|
||||
TRACE_SCOPED2(category, __PRETTY_FUNCTION__, argname, argval, argname_two, \
|
||||
argval_two, ##__VA_ARGS__)
|
||||
|
||||
// Asynchronous Trace Macros.
|
||||
#define TRACE_ASYNC_START(category, name, ...) \
|
||||
TRACE_ASYNC_START_INTERNAL(__LINE__, category, name, ToArgumentArray(), \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define TRACE_ASYNC_START1(category, name, argname, argval, ...) \
|
||||
TRACE_ASYNC_START_INTERNAL(__LINE__, category, name, \
|
||||
ToArgumentArray(argname, argval), ##__VA_ARGS__)
|
||||
|
||||
#define TRACE_ASYNC_START2(category, name, argname, argval, argname_two, \
|
||||
argval_two, ...) \
|
||||
TRACE_ASYNC_START_INTERNAL( \
|
||||
__LINE__, category, name, \
|
||||
ToArgumentArray(argname, argval, argname_two, argval_two), \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define TRACE_ASYNC_END(category, id, result) \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::ScopedTraceOperation::TraceAsyncEnd( \
|
||||
__LINE__, __FILE__, id, result) \
|
||||
: false
|
||||
|
||||
// Flow events are used to link trace events across different threads or
|
||||
// processes. Flows are linked by their flow_id.
|
||||
// - Flows can span across different trace categories.
|
||||
// - If a TRACE_FLOW_BEGIN is missing (e.g. because the embedder didn't
|
||||
// instrument it),
|
||||
// the first TRACE_FLOW_STEP encountered will effectively start the flow
|
||||
// visualization.
|
||||
#define TRACE_FLOW_BEGIN(category, name, flow_id) \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
||||
category, name, __FILE__, __LINE__, \
|
||||
openscreen::internal::ToFlowId(flow_id), \
|
||||
openscreen::FlowType::kFlowBegin) \
|
||||
: false
|
||||
|
||||
#define TRACE_FLOW_STEP(category, name, flow_id) \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
||||
category, name, __FILE__, __LINE__, \
|
||||
openscreen::internal::ToFlowId(flow_id), \
|
||||
openscreen::FlowType::kFlowStep) \
|
||||
: false
|
||||
|
||||
#define TRACE_FLOW_END(category, name, flow_id) \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
||||
category, name, __FILE__, __LINE__, \
|
||||
openscreen::internal::ToFlowId(flow_id), \
|
||||
openscreen::FlowType::kFlowEnd) \
|
||||
: false
|
||||
|
||||
#define TRACE_FLOW_BEGIN_WITH_TIME(category, name, flow_id, timestamp) \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
||||
category, name, __FILE__, __LINE__, \
|
||||
openscreen::internal::ToFlowId(flow_id), \
|
||||
openscreen::FlowType::kFlowBegin, timestamp) \
|
||||
: false
|
||||
|
||||
#define TRACE_FLOW_STEP_WITH_TIME(category, name, flow_id, timestamp) \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
||||
category, name, __FILE__, __LINE__, \
|
||||
openscreen::internal::ToFlowId(flow_id), \
|
||||
openscreen::FlowType::kFlowStep, timestamp) \
|
||||
: false
|
||||
|
||||
#define TRACE_FLOW_END_WITH_TIME(category, name, flow_id, timestamp) \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
||||
category, name, __FILE__, __LINE__, \
|
||||
openscreen::internal::ToFlowId(flow_id), \
|
||||
openscreen::FlowType::kFlowEnd, timestamp) \
|
||||
: false
|
||||
|
||||
#define TRACE_FLOW_DEFAULT_BEGIN(category, flow_id) \
|
||||
TRACE_FLOW_BEGIN(category, __PRETTY_FUNCTION__, flow_id)
|
||||
|
||||
#define TRACE_FLOW_DEFAULT_STEP(category, flow_id) \
|
||||
TRACE_FLOW_STEP(category, __PRETTY_FUNCTION__, flow_id)
|
||||
|
||||
#define TRACE_FLOW_DEFAULT_END(category, flow_id) \
|
||||
TRACE_FLOW_END(category, __PRETTY_FUNCTION__, flow_id)
|
||||
|
||||
#else // ENABLE_TRACE_LOGGING not defined
|
||||
|
||||
namespace openscreen::internal {
|
||||
// Consumes `args` (to avoid "warn unused variable" errors at compile time), and
|
||||
// provides a "void" result type in the macros below.
|
||||
template <typename... Args>
|
||||
inline void DoNothingForTracing(Args... args) {}
|
||||
} // namespace openscreen::internal
|
||||
|
||||
#define TRACE_SET_RESULT(result) \
|
||||
openscreen::internal::DoNothingForTracing(result)
|
||||
#define TRACE_SET_HIERARCHY(ids) openscreen::internal::DoNothingForTracing(ids)
|
||||
#define TRACE_HIERARCHY openscreen::TraceIdHierarchy::Empty()
|
||||
#define TRACE_CURRENT_ID openscreen::kEmptyTraceId
|
||||
#define TRACE_ROOT_ID openscreen::kEmptyTraceId
|
||||
#define TRACE_SCOPED(category, name, ...) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, ##__VA_ARGS__)
|
||||
#define TRACE_DEFAULT_SCOPED(category, ...) \
|
||||
TRACE_SCOPED(category, __PRETTY_FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
#define TRACE_SCOPED1(category, name, argname, argval, ...) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, argname, argval, \
|
||||
##__VA_ARGS__)
|
||||
#define TRACE_DEFAULT_SCOPED1(category, argname, argval, ...) \
|
||||
TRACE_SCOPED1(category, __PRETTY_FUNCTION__, argname, argval, ##__VA_ARGS__)
|
||||
|
||||
#define TRACE_SCOPED2(category, name, argname, argval, argname_two, \
|
||||
argval_two, ...) \
|
||||
openscreen::internal::DoNothingForTracing( \
|
||||
category, name, argname, argval, argname_two, argval_two, ##__VA_ARGS__)
|
||||
#define TRACE_DEFAULT_SCOPED2(category, argname, argval, argname_two, \
|
||||
argval_two, ...) \
|
||||
TRACE_SCOPED2(category, __PRETTY_FUNCTION__, argname, argval, argname_two, \
|
||||
argval_two, ##__VA_ARGS__)
|
||||
|
||||
#define TRACE_ASYNC_START(category, name, ...) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, ##__VA_ARGS__)
|
||||
#define TRACE_ASYNC_END(category, id, result) \
|
||||
openscreen::internal::DoNothingForTracing(category, id, result)
|
||||
|
||||
#define TRACE_FLOW_BEGIN(category, name, flow_id) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, flow_id)
|
||||
#define TRACE_FLOW_STEP(category, name, flow_id) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, flow_id)
|
||||
#define TRACE_FLOW_END(category, name, flow_id) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, flow_id)
|
||||
|
||||
#define TRACE_FLOW_BEGIN_WITH_TIME(category, name, flow_id, timestamp) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, flow_id, timestamp)
|
||||
|
||||
#define TRACE_FLOW_STEP_WITH_TIME(category, name, flow_id, timestamp) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, flow_id, timestamp)
|
||||
|
||||
#define TRACE_FLOW_END_WITH_TIME(category, name, flow_id, timestamp) \
|
||||
openscreen::internal::DoNothingForTracing(category, name, flow_id, timestamp)
|
||||
|
||||
#define TRACE_FLOW_DEFAULT_BEGIN(category, flow_id) \
|
||||
openscreen::internal::DoNothingForTracing(category, flow_id)
|
||||
#define TRACE_FLOW_DEFAULT_STEP(category, flow_id) \
|
||||
openscreen::internal::DoNothingForTracing(category, flow_id)
|
||||
#define TRACE_FLOW_DEFAULT_END(category, flow_id) \
|
||||
openscreen::internal::DoNothingForTracing(category, flow_id)
|
||||
|
||||
#endif // defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
#endif // UTIL_TRACE_LOGGING_H_
|
||||
84
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/macro_support.h
vendored
Normal file
84
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/macro_support.h
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_TRACE_LOGGING_MACRO_SUPPORT_H_
|
||||
#define UTIL_TRACE_LOGGING_MACRO_SUPPORT_H_
|
||||
|
||||
#ifndef INCLUDING_FROM_UTIL_TRACE_LOGGING_H_
|
||||
#error "Do not include this header directly. Use util/trace_logging.h."
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_TRACE_LOGGING
|
||||
#error "BUG: This file should not have been reached."
|
||||
#endif
|
||||
|
||||
#include "platform/api/trace_logging_platform.h"
|
||||
#include "platform/base/trace_logging_activation.h"
|
||||
#include "platform/base/trace_logging_types.h"
|
||||
#include "util/trace_logging/scoped_trace_operations.h"
|
||||
|
||||
// Helper macros. These are used to simplify the macros below.
|
||||
// NOTE: These cannot be #undef'd or they will stop working outside this file.
|
||||
// NOTE: Two of these below macros are intentionally the same. This is to work
|
||||
// around optimizations in the C++ Precompiler.
|
||||
#define TRACE_INTERNAL_CONCAT(a, b) a##b
|
||||
#define TRACE_INTERNAL_CONCAT_CONST(a, b) TRACE_INTERNAL_CONCAT(a, b)
|
||||
#define TRACE_INTERNAL_UNIQUE_VAR_NAME(a) \
|
||||
TRACE_INTERNAL_CONCAT_CONST(a, __LINE__)
|
||||
|
||||
namespace openscreen::internal {
|
||||
|
||||
inline bool IsTraceLoggingEnabled(TraceCategory category) {
|
||||
const CurrentTracingDestination destination;
|
||||
return destination && destination->IsTraceLoggingEnabled(category);
|
||||
}
|
||||
|
||||
} // namespace openscreen::internal
|
||||
|
||||
#define TRACE_IS_ENABLED(category) \
|
||||
openscreen::internal::IsTraceLoggingEnabled(category)
|
||||
|
||||
// Internal logging macros.
|
||||
#define TRACE_SET_HIERARCHY_INTERNAL(line, ids) \
|
||||
alignas(32) uint8_t TRACE_INTERNAL_CONCAT_CONST( \
|
||||
tracing_storage, line)[sizeof(openscreen::internal::TraceIdSetter)]; \
|
||||
[[maybe_unused]] \
|
||||
const auto TRACE_INTERNAL_UNIQUE_VAR_NAME(trace_ref_) = \
|
||||
TRACE_IS_ENABLED(openscreen::TraceCategory::kAny) \
|
||||
? openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::TraceIdSetter>:: \
|
||||
Create(TRACE_INTERNAL_CONCAT_CONST(tracing_storage, line), \
|
||||
ids) \
|
||||
: openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::TraceIdSetter>::Empty()
|
||||
|
||||
#define TRACE_SCOPED_INTERNAL(line, category, name, ...) \
|
||||
alignas(32) uint8_t TRACE_INTERNAL_CONCAT_CONST( \
|
||||
tracing_storage, \
|
||||
line)[sizeof(openscreen::internal::SynchronousTraceLogger)]; \
|
||||
[[maybe_unused]] \
|
||||
const auto TRACE_INTERNAL_UNIQUE_VAR_NAME(trace_ref_) = \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::SynchronousTraceLogger>:: \
|
||||
Create(TRACE_INTERNAL_CONCAT_CONST(tracing_storage, line), \
|
||||
category, name, __FILE__, __LINE__, ##__VA_ARGS__) \
|
||||
: openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::SynchronousTraceLogger>::Empty()
|
||||
|
||||
#define TRACE_ASYNC_START_INTERNAL(line, category, name, ...) \
|
||||
alignas(32) uint8_t TRACE_INTERNAL_CONCAT_CONST( \
|
||||
temp_storage, \
|
||||
line)[sizeof(openscreen::internal::AsynchronousTraceLogger)]; \
|
||||
[[maybe_unused]] \
|
||||
const auto TRACE_INTERNAL_UNIQUE_VAR_NAME(trace_ref_) = \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::AsynchronousTraceLogger>:: \
|
||||
Create(TRACE_INTERNAL_CONCAT_CONST(temp_storage, line), \
|
||||
category, name, __FILE__, __LINE__, ##__VA_ARGS__) \
|
||||
: openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::AsynchronousTraceLogger>::Empty()
|
||||
|
||||
#endif // UTIL_TRACE_LOGGING_MACRO_SUPPORT_H_
|
||||
160
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/scoped_trace_operations.cc
vendored
Normal file
160
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/scoped_trace_operations.cc
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/trace_logging/scoped_trace_operations.h"
|
||||
|
||||
#include "platform/api/trace_logging_platform.h"
|
||||
#include "platform/base/trace_logging_activation.h"
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
#if defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
namespace openscreen::internal {
|
||||
|
||||
// static
|
||||
bool ScopedTraceOperation::TraceAsyncEnd(const uint32_t line,
|
||||
const char* file,
|
||||
TraceId id,
|
||||
Error::Code e) {
|
||||
const CurrentTracingDestination destination;
|
||||
if (destination) {
|
||||
TraceEvent end_event;
|
||||
end_event.start_time = Clock::now();
|
||||
end_event.line_number = line;
|
||||
end_event.file_name = file;
|
||||
end_event.ids.current = id;
|
||||
end_event.result = e;
|
||||
destination->LogAsyncEnd(std::move(end_event));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool ScopedTraceOperation::TraceFlow(
|
||||
TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
uint64_t flow_id,
|
||||
FlowType type,
|
||||
std::optional<Clock::time_point> timestamp) {
|
||||
const CurrentTracingDestination destination;
|
||||
if (destination) {
|
||||
const auto start_time = timestamp ? *timestamp : Clock::now();
|
||||
TraceEvent event(category, start_time, name, file, line);
|
||||
event.flow_ids.push_back(flow_id);
|
||||
destination->LogFlow(std::move(event), type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedTraceOperation::ScopedTraceOperation(TraceId trace_id,
|
||||
TraceId parent_id,
|
||||
TraceId root_id) {
|
||||
if (traces_ == nullptr) {
|
||||
// Create the stack if it doesnt' exist.
|
||||
traces_ = new TraceStack();
|
||||
|
||||
// Create a new root node. This will re-call this constructor and add the
|
||||
// root node to the stack before proceeding with the original node.
|
||||
root_node_ = new TraceIdSetter(TraceIdHierarchy::Empty());
|
||||
OSP_CHECK(!traces_->empty());
|
||||
}
|
||||
|
||||
// Setting trace id fields.
|
||||
root_id_ = root_id != kUnsetTraceId ? root_id : traces_->top()->root_id_;
|
||||
parent_id_ =
|
||||
parent_id != kUnsetTraceId ? parent_id : traces_->top()->trace_id_;
|
||||
trace_id_ =
|
||||
trace_id != kUnsetTraceId ? trace_id : trace_id_counter_.fetch_add(1);
|
||||
|
||||
// Add this item to the stack.
|
||||
traces_->push(this);
|
||||
OSP_CHECK_LT(traces_->size(), 1024);
|
||||
}
|
||||
|
||||
ScopedTraceOperation::~ScopedTraceOperation() {
|
||||
OSP_CHECK(traces_ != nullptr && !traces_->empty());
|
||||
OSP_CHECK_EQ(traces_->top(), this);
|
||||
traces_->pop();
|
||||
|
||||
// If there's only one item left, it must be the root node. Deleting the root
|
||||
// node will re-call this destructor and delete the traces_ stack.
|
||||
if (traces_->size() == 1) {
|
||||
OSP_CHECK_EQ(traces_->top(), root_node_);
|
||||
delete root_node_;
|
||||
root_node_ = nullptr;
|
||||
} else if (traces_->empty()) {
|
||||
delete traces_;
|
||||
traces_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
thread_local ScopedTraceOperation::TraceStack* ScopedTraceOperation::traces_ =
|
||||
nullptr;
|
||||
|
||||
// static
|
||||
thread_local ScopedTraceOperation* ScopedTraceOperation::root_node_ = nullptr;
|
||||
|
||||
// static
|
||||
std::atomic<std::uint64_t> ScopedTraceOperation::trace_id_counter_{
|
||||
uint64_t{0x01} << (sizeof(TraceId) * 8 - 1)};
|
||||
|
||||
TraceLoggerBase::TraceLoggerBase(TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
std::vector<TraceEvent::Argument> arguments,
|
||||
TraceId current,
|
||||
TraceId parent,
|
||||
TraceId root)
|
||||
: ScopedTraceOperation(current, parent, root),
|
||||
event_(category, Clock::now(), name, file, line) {
|
||||
event_.arguments = std::move(arguments);
|
||||
event_.TruncateStrings();
|
||||
}
|
||||
|
||||
TraceLoggerBase::TraceLoggerBase(TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
std::vector<TraceEvent::Argument> arguments,
|
||||
TraceIdHierarchy ids)
|
||||
: TraceLoggerBase(category,
|
||||
name,
|
||||
file,
|
||||
line,
|
||||
std::move(arguments),
|
||||
ids.current,
|
||||
ids.parent,
|
||||
ids.root) {}
|
||||
|
||||
SynchronousTraceLogger::~SynchronousTraceLogger() {
|
||||
const CurrentTracingDestination destination;
|
||||
if (destination) {
|
||||
const auto end_time = Clock::now();
|
||||
event_.ids = to_hierarchy();
|
||||
destination->LogTrace(event_, end_time);
|
||||
}
|
||||
}
|
||||
|
||||
AsynchronousTraceLogger::~AsynchronousTraceLogger() {
|
||||
const CurrentTracingDestination destination;
|
||||
if (destination) {
|
||||
event_.ids = to_hierarchy();
|
||||
destination->LogAsyncStart(event_);
|
||||
}
|
||||
}
|
||||
|
||||
TraceIdSetter::TraceIdSetter(TraceIdHierarchy ids)
|
||||
: ScopedTraceOperation(ids.current, ids.parent, ids.root) {}
|
||||
|
||||
TraceIdSetter::~TraceIdSetter() = default;
|
||||
|
||||
} // namespace openscreen::internal
|
||||
|
||||
#endif // defined(ENABLE_TRACE_LOGGING)
|
||||
224
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/scoped_trace_operations.h
vendored
Normal file
224
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/scoped_trace_operations.h
vendored
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_TRACE_LOGGING_SCOPED_TRACE_OPERATIONS_H_
|
||||
#define UTIL_TRACE_LOGGING_SCOPED_TRACE_OPERATIONS_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "platform/api/time.h"
|
||||
#include "platform/api/trace_logging_platform.h"
|
||||
#include "platform/base/error.h"
|
||||
#include "platform/base/trace_logging_types.h"
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
#if defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
namespace openscreen::internal {
|
||||
|
||||
// A base class for all trace logging objects which will create new entries in
|
||||
// the Trace Hierarchy.
|
||||
// 1) The sharing of all static and thread_local variables across template
|
||||
// specializations.
|
||||
// 2) Including all children in the same traces vector.
|
||||
class ScopedTraceOperation {
|
||||
public:
|
||||
// Define the destructor to remove this item from the stack when it's
|
||||
// destroyed.
|
||||
virtual ~ScopedTraceOperation();
|
||||
|
||||
ScopedTraceOperation(const ScopedTraceOperation&) = delete;
|
||||
ScopedTraceOperation(ScopedTraceOperation&&) noexcept = delete;
|
||||
ScopedTraceOperation& operator=(const ScopedTraceOperation&) = delete;
|
||||
ScopedTraceOperation& operator=(ScopedTraceOperation&&) = delete;
|
||||
|
||||
// Getters the current Trace Hierarchy. If the traces_ stack hasn't been
|
||||
// created yet, return as if the empty root node is there.
|
||||
static TraceId current_id() {
|
||||
return traces_ == nullptr ? kEmptyTraceId : traces_->top()->trace_id_;
|
||||
}
|
||||
|
||||
static TraceId root_id() {
|
||||
return traces_ == nullptr ? kEmptyTraceId : traces_->top()->root_id_;
|
||||
}
|
||||
|
||||
static TraceIdHierarchy hierarchy() {
|
||||
if (traces_ == nullptr) {
|
||||
return TraceIdHierarchy::Empty();
|
||||
}
|
||||
|
||||
return traces_->top()->to_hierarchy();
|
||||
}
|
||||
|
||||
// Static method to set the result of the most recent trace.
|
||||
static void set_result(const Error& error) { set_result(error.code()); }
|
||||
static void set_result(Error::Code error) {
|
||||
if (traces_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
traces_->top()->SetTraceResult(error);
|
||||
}
|
||||
|
||||
// Traces the end of an asynchronous call.
|
||||
// NOTE: This returns a bool rather than a void because it keeps the syntax of
|
||||
// the ternary operator in the macros simpler.
|
||||
static bool TraceAsyncEnd(const uint32_t line,
|
||||
const char* file,
|
||||
TraceId id,
|
||||
Error::Code e);
|
||||
|
||||
// Traces a flow event.
|
||||
static bool TraceFlow(
|
||||
TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
uint64_t flow_id,
|
||||
FlowType type,
|
||||
std::optional<Clock::time_point> timestamp = std::nullopt);
|
||||
|
||||
protected:
|
||||
// Sets the result of this trace log.
|
||||
// NOTE: this must be define in this class rather than TraceLogger so that it
|
||||
// can be called on traces.back() without a potentially unsafe cast or type
|
||||
// checking at runtime.
|
||||
virtual void SetTraceResult(Error::Code error) = 0;
|
||||
|
||||
// Constructor to set all trace id information.
|
||||
ScopedTraceOperation(TraceId current_id = kUnsetTraceId,
|
||||
TraceId parent_id = kUnsetTraceId,
|
||||
TraceId root_id = kUnsetTraceId);
|
||||
|
||||
// Current TraceId information.
|
||||
TraceId trace_id_;
|
||||
TraceId parent_id_;
|
||||
TraceId root_id_;
|
||||
|
||||
TraceIdHierarchy to_hierarchy() { return {trace_id_, parent_id_, root_id_}; }
|
||||
|
||||
private:
|
||||
// NOTE: A std::vector is used for backing the stack because it provides the
|
||||
// best perf. Further perf improvement could be achieved later by swapping
|
||||
// this out for a circular buffer once OSP supports that. Additional details
|
||||
// can be found here:
|
||||
// https://www.codeproject.com/Articles/1185449/Performance-of-a-Circular-Buffer-vs-Vector-Deque-a
|
||||
using TraceStack =
|
||||
std::stack<ScopedTraceOperation*, std::vector<ScopedTraceOperation*>>;
|
||||
|
||||
// Counter to pick IDs when it is not provided.
|
||||
static std::atomic<std::uint64_t> trace_id_counter_;
|
||||
|
||||
// The LIFO stack of TraceLoggers currently being watched by this
|
||||
// thread.
|
||||
static thread_local TraceStack* traces_;
|
||||
static thread_local ScopedTraceOperation* root_node_;
|
||||
};
|
||||
|
||||
// The class which does actual trace logging.
|
||||
class TraceLoggerBase : public ScopedTraceOperation {
|
||||
public:
|
||||
TraceLoggerBase(TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
std::vector<TraceEvent::Argument> arguments = {},
|
||||
TraceId current = kUnsetTraceId,
|
||||
TraceId parent = kUnsetTraceId,
|
||||
TraceId root = kUnsetTraceId);
|
||||
|
||||
TraceLoggerBase(TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
std::vector<TraceEvent::Argument> arguments,
|
||||
TraceIdHierarchy ids);
|
||||
|
||||
TraceLoggerBase(const TraceLoggerBase&) = delete;
|
||||
TraceLoggerBase(TraceLoggerBase&&) noexcept = delete;
|
||||
TraceLoggerBase& operator=(const TraceLoggerBase&) = delete;
|
||||
TraceLoggerBase& operator=(TraceLoggerBase&&) = delete;
|
||||
|
||||
protected:
|
||||
// Set the result.
|
||||
void SetTraceResult(Error::Code error) override { event_.result = error; }
|
||||
|
||||
TraceEvent event_;
|
||||
};
|
||||
|
||||
class SynchronousTraceLogger : public TraceLoggerBase {
|
||||
public:
|
||||
using TraceLoggerBase::TraceLoggerBase;
|
||||
|
||||
SynchronousTraceLogger(const SynchronousTraceLogger&) = delete;
|
||||
SynchronousTraceLogger(SynchronousTraceLogger&&) noexcept = delete;
|
||||
SynchronousTraceLogger& operator=(const SynchronousTraceLogger&) = delete;
|
||||
SynchronousTraceLogger& operator=(SynchronousTraceLogger&&) = delete;
|
||||
|
||||
~SynchronousTraceLogger() override;
|
||||
};
|
||||
|
||||
class AsynchronousTraceLogger : public TraceLoggerBase {
|
||||
public:
|
||||
using TraceLoggerBase::TraceLoggerBase;
|
||||
|
||||
AsynchronousTraceLogger(const AsynchronousTraceLogger&) = delete;
|
||||
AsynchronousTraceLogger(AsynchronousTraceLogger&&) noexcept = delete;
|
||||
AsynchronousTraceLogger& operator=(const AsynchronousTraceLogger&) = delete;
|
||||
AsynchronousTraceLogger& operator=(AsynchronousTraceLogger&&) = delete;
|
||||
|
||||
~AsynchronousTraceLogger() override;
|
||||
};
|
||||
|
||||
// Inserts a fake element into the ScopedTraceOperation stack to set
|
||||
// the current TraceId Hierarchy manually.
|
||||
class TraceIdSetter final : public ScopedTraceOperation {
|
||||
public:
|
||||
explicit TraceIdSetter(TraceIdHierarchy ids);
|
||||
TraceIdSetter(const TraceIdSetter&) = delete;
|
||||
TraceIdSetter(TraceIdSetter&&) noexcept = delete;
|
||||
TraceIdSetter& operator=(const TraceIdSetter&) = delete;
|
||||
TraceIdSetter& operator=(TraceIdSetter&&) = delete;
|
||||
~TraceIdSetter() final;
|
||||
|
||||
// Creates a new TraceIdSetter to set the full TraceId Hierarchy to default
|
||||
// values and does not push it to the traces stack.
|
||||
static TraceIdSetter* CreateStackRootNode();
|
||||
|
||||
private:
|
||||
// Implement abstract method for use in Macros.
|
||||
void SetTraceResult(Error::Code error) {}
|
||||
};
|
||||
|
||||
// This helper object allows us to delete objects allocated on the stack in a
|
||||
// unique_ptr.
|
||||
template <class T>
|
||||
class TraceInstanceHelper {
|
||||
private:
|
||||
class TraceOperationOnStackDeleter {
|
||||
public:
|
||||
void operator()(T* ptr) { ptr->~T(); }
|
||||
};
|
||||
|
||||
using TraceInstanceWrapper = std::unique_ptr<T, TraceOperationOnStackDeleter>;
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
static TraceInstanceWrapper Create(uint8_t storage[sizeof(T)], Args... args) {
|
||||
return TraceInstanceWrapper(new (storage) T(std::forward<Args&&>(args)...));
|
||||
}
|
||||
|
||||
static TraceInstanceWrapper Empty() { return TraceInstanceWrapper(); }
|
||||
};
|
||||
|
||||
} // namespace openscreen::internal
|
||||
|
||||
#endif // defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
#endif // UTIL_TRACE_LOGGING_SCOPED_TRACE_OPERATIONS_H_
|
||||
127
breadcast-caststream-sys/vendor/openscreen/util/uuid.cc
vendored
Normal file
127
breadcast-caststream-sys/vendor/openscreen/util/uuid.cc
vendored
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
// Copyright 2025 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/uuid.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include "util/big_endian.h"
|
||||
#include "util/crypto/random_bytes.h"
|
||||
#include "util/hashing.h"
|
||||
#include "util/osp_logging.h"
|
||||
#include "util/string_util.h"
|
||||
#include "util/stringprintf.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr bool IsHyphenPosition(size_t i) {
|
||||
return i == 8 || i == 13 || i == 18 || i == 23;
|
||||
}
|
||||
|
||||
// Returns a canonical Uuid string given that `input` is validly formatted
|
||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, such that x is a hexadecimal digit.
|
||||
// If `strict`, x must be a lower-case hexadecimal digit.
|
||||
std::string GetCanonicalUuidInternal(std::string_view input, bool strict) {
|
||||
constexpr size_t kUuidLength = 36;
|
||||
if (input.length() != kUuidLength) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string lowercase;
|
||||
lowercase.resize(kUuidLength);
|
||||
for (size_t i = 0; i < input.length(); ++i) {
|
||||
auto current = input[i];
|
||||
if (IsHyphenPosition(i)) {
|
||||
if (current != '-') {
|
||||
return {};
|
||||
}
|
||||
lowercase[i] = '-';
|
||||
} else {
|
||||
if (strict ? !string_util::ascii_islowerhex(current)
|
||||
: !string_util::ascii_ishex(current)) {
|
||||
return {};
|
||||
}
|
||||
lowercase[i] = static_cast<char>(string_util::ascii_tolower(current));
|
||||
}
|
||||
}
|
||||
|
||||
return lowercase;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
Uuid Uuid::GenerateRandomV4() {
|
||||
return FormatRandomDataAsV4Impl(GenerateRandomBytes16());
|
||||
}
|
||||
|
||||
// static
|
||||
Uuid Uuid::FormatRandomDataAsV4Impl(ByteView input) {
|
||||
OSP_CHECK_EQ(input.size(), kGuidV4InputLength);
|
||||
|
||||
auto first_u64 = ReadBigEndian<uint64_t>(input.first(8).data());
|
||||
auto second_u64 = ReadBigEndian<uint64_t>(input.last(8).data());
|
||||
|
||||
// Set the Uuid to version 4 as described in RFC 4122, section 4.4.
|
||||
// The format of Uuid version 4 must be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,
|
||||
// where y is one of [8, 9, a, b].
|
||||
|
||||
// Clear the version bits and set the version to 4:
|
||||
first_u64 &= 0xffffffff'ffff0fffULL;
|
||||
first_u64 |= 0x00000000'00004000ULL;
|
||||
|
||||
// Clear bit 65 and set bit 64, to set the 'var' field to 0b10 per RFC 9562
|
||||
// section 5.4.
|
||||
second_u64 &= 0x3fffffff'ffffffffULL;
|
||||
second_u64 |= 0x80000000'00000000ULL;
|
||||
|
||||
Uuid uuid;
|
||||
uuid.lowercase_ =
|
||||
StringFormat("{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
|
||||
static_cast<uint32_t>(first_u64 >> 32),
|
||||
static_cast<uint32_t>((first_u64 >> 16) & 0x0000'ffff),
|
||||
static_cast<uint32_t>(first_u64 & 0x0000'ffff),
|
||||
static_cast<uint32_t>(second_u64 >> 48),
|
||||
second_u64 & 0x0000'ffff'ffff'ffffULL);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
// static
|
||||
Uuid Uuid::ParseCaseInsensitive(std::string_view input) {
|
||||
Uuid uuid;
|
||||
uuid.lowercase_ = GetCanonicalUuidInternal(input, /*strict=*/false);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
// static
|
||||
Uuid Uuid::ParseLowercase(std::string_view input) {
|
||||
Uuid uuid;
|
||||
uuid.lowercase_ = GetCanonicalUuidInternal(input, /*strict=*/true);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
Uuid::Uuid() = default;
|
||||
Uuid::Uuid(const Uuid& other) = default;
|
||||
Uuid::Uuid(Uuid&& other) noexcept = default;
|
||||
Uuid& Uuid::operator=(const Uuid& other) = default;
|
||||
Uuid& Uuid::operator=(Uuid&& other) = default;
|
||||
|
||||
const std::string& Uuid::AsLowercaseString() const {
|
||||
return lowercase_;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Uuid& uuid) {
|
||||
return out << uuid.AsLowercaseString();
|
||||
}
|
||||
|
||||
size_t UuidHash::operator()(const Uuid& uuid) const {
|
||||
return ComputeAggregateHash(uuid.AsLowercaseString());
|
||||
}
|
||||
|
||||
} // namespace openscreen
|
||||
81
breadcast-caststream-sys/vendor/openscreen/util/uuid.h
vendored
Normal file
81
breadcast-caststream-sys/vendor/openscreen/util/uuid.h
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2025 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_UUID_H_
|
||||
#define UTIL_UUID_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <compare>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "platform/base/span.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// UUID implementation strongly based off of Chromium's base::Uuid
|
||||
// implementation. Provides securely generated random Uuids as well as parsing
|
||||
// logic for inputted UUIDs.
|
||||
class Uuid {
|
||||
public:
|
||||
// Length in bytes of the input required to format the input as a Uuid in the
|
||||
// form of version 4.
|
||||
static constexpr size_t kGuidV4InputLength = 16;
|
||||
|
||||
// Generate a 128-bit random Uuid in the form of version 4. see RFC 4122,
|
||||
// section 4.4. The format of Uuid version 4 must be
|
||||
// xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where y is one of [8, 9, a, b]. The
|
||||
// hexadecimal values "a" through "f" are output as lower case characters.
|
||||
static Uuid GenerateRandomV4();
|
||||
|
||||
// Returns a valid Uuid if the input string conforms to the Uuid format, and
|
||||
// an invalid Uuid otherwise. Accepts both lower case and upper case hex
|
||||
// characters.
|
||||
static Uuid ParseCaseInsensitive(std::string_view input);
|
||||
|
||||
// Similar to ParseCaseInsensitive(), but all hexadecimal values "a" through
|
||||
// "f" must be lower case characters.
|
||||
static Uuid ParseLowercase(std::string_view input);
|
||||
|
||||
// Constructs an invalid Uuid.
|
||||
Uuid();
|
||||
|
||||
Uuid(const Uuid& other);
|
||||
Uuid(Uuid&& other) noexcept;
|
||||
Uuid& operator=(const Uuid& other);
|
||||
Uuid& operator=(Uuid&& other);
|
||||
|
||||
bool is_valid() const { return !lowercase_.empty(); }
|
||||
|
||||
// Returns the Uuid in a lowercase string format if it is valid, and an empty
|
||||
// string otherwise. The returned value is guaranteed to be parsed by
|
||||
// ParseLowercase().
|
||||
const std::string& AsLowercaseString() const;
|
||||
|
||||
// Invalid Uuids are equal.
|
||||
friend bool operator==(const Uuid&, const Uuid&) = default;
|
||||
// Uuids are 128bit chunks of data so must be indistinguishable if equivalent.
|
||||
friend std::strong_ordering operator<=>(const Uuid&, const Uuid&) = default;
|
||||
|
||||
private:
|
||||
static Uuid FormatRandomDataAsV4Impl(ByteView input);
|
||||
|
||||
// The lowercase form of the Uuid. Empty for invalid Uuids.
|
||||
std::string lowercase_;
|
||||
};
|
||||
|
||||
// For runtime usage only. Do not store the result of this hash, as it may
|
||||
// change in the future.
|
||||
struct UuidHash {
|
||||
size_t operator()(const Uuid& uuid) const;
|
||||
};
|
||||
|
||||
// Stream operator so Uuid objects can be used in logging statements.
|
||||
std::ostream& operator<<(std::ostream& out, const Uuid& uuid);
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_UUID_H_
|
||||
217
breadcast-caststream-sys/vendor/openscreen/util/weak_ptr.h
vendored
Normal file
217
breadcast-caststream-sys/vendor/openscreen/util/weak_ptr.h
vendored
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_WEAK_PTR_H_
|
||||
#define UTIL_WEAK_PTR_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// Weak pointers are pointers to an object that do not affect its lifetime,
|
||||
// and which may be invalidated (i.e. reset to nullptr) by the object, or its
|
||||
// owner, at any time; most commonly when the object is about to be deleted.
|
||||
//
|
||||
// Weak pointers are useful when an object needs to be accessed safely by one
|
||||
// or more objects other than its owner, and those callers can cope with the
|
||||
// object vanishing and e.g. tasks posted to it being silently dropped.
|
||||
// Reference-counting such an object would complicate the ownership graph and
|
||||
// make it harder to reason about the object's lifetime.
|
||||
//
|
||||
// EXAMPLE:
|
||||
//
|
||||
// class Controller {
|
||||
// public:
|
||||
// void SpawnWorker() { new Worker(weak_factory_.GetWeakPtr()); }
|
||||
// void WorkComplete(const Result& result) { ... }
|
||||
// private:
|
||||
// // Member variables should appear before the WeakPtrFactory, to ensure
|
||||
// // that any WeakPtrs to Controller are invalidated before its members
|
||||
// // variable's destructors are executed, rendering them invalid.
|
||||
// WeakPtrFactory<Controller> weak_factory_{this};
|
||||
// };
|
||||
//
|
||||
// class Worker {
|
||||
// public:
|
||||
// explicit Worker(WeakPtr<Controller> controller)
|
||||
// : controller_(std::move(controller)) {}
|
||||
// private:
|
||||
// void DidCompleteAsynchronousProcessing(const Result& result) {
|
||||
// if (controller_)
|
||||
// controller_->WorkComplete(result);
|
||||
// delete this;
|
||||
// }
|
||||
// const WeakPtr<Controller> controller_;
|
||||
// };
|
||||
//
|
||||
// With this implementation a caller may use SpawnWorker() to dispatch multiple
|
||||
// Workers and subsequently delete the Controller, without waiting for all
|
||||
// Workers to have completed.
|
||||
//
|
||||
// ------------------------- IMPORTANT: Thread-safety -------------------------
|
||||
//
|
||||
// Generally, Open Screen code is meant to be single-threaded. For the few
|
||||
// exceptional cases, the following is relevant:
|
||||
//
|
||||
// WeakPtrs may be created from WeakPtrFactory, and also duplicated/moved on any
|
||||
// thread/sequence. However, they may only be dereferenced on the same
|
||||
// thread/sequence that will ultimately execute the WeakPtrFactory destructor or
|
||||
// call InvalidateWeakPtrs(). Otherwise, use-during-free or use-after-free is
|
||||
// possible.
|
||||
//
|
||||
// openscreen::WeakPtr and WeakPtrFactory are similar, but not identical, to
|
||||
// Chromium's base::WeakPtrFactory. Open Screen WeakPtrs may be safely created
|
||||
// from WeakPtrFactory on any thread/sequence, since they are backed by the
|
||||
// thread-safe bookkeeping of std::shared_ptr<>.
|
||||
|
||||
template <typename T>
|
||||
class WeakPtrFactory;
|
||||
|
||||
template <typename T>
|
||||
class WeakPtr {
|
||||
public:
|
||||
WeakPtr() = default;
|
||||
~WeakPtr() = default;
|
||||
|
||||
// Copy/Move constructors and assignment operators.
|
||||
WeakPtr(const WeakPtr& other) : impl_(other.impl_) {}
|
||||
|
||||
WeakPtr(WeakPtr&& other) noexcept : impl_(std::move(other.impl_)) {}
|
||||
|
||||
WeakPtr& operator=(const WeakPtr& other) {
|
||||
impl_ = other.impl_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
WeakPtr& operator=(WeakPtr&& other) noexcept {
|
||||
impl_ = std::move(other.impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Create/Assign from nullptr.
|
||||
WeakPtr(std::nullptr_t) {} // NOLINT
|
||||
|
||||
WeakPtr& operator=(std::nullptr_t) {
|
||||
impl_.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy/Move constructors and assignment operators with upcast conversion.
|
||||
template <typename U>
|
||||
WeakPtr(const WeakPtr<U>& other) : impl_(other.as_std_weak_ptr()) {}
|
||||
|
||||
template <typename U>
|
||||
WeakPtr(WeakPtr<U>&& other) noexcept
|
||||
: impl_(std::move(other).as_std_weak_ptr()) {}
|
||||
|
||||
template <typename U>
|
||||
WeakPtr& operator=(const WeakPtr<U>& other) {
|
||||
impl_ = other.as_std_weak_ptr();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
WeakPtr& operator=(WeakPtr<U>&& other) noexcept {
|
||||
impl_ = std::move(other).as_std_weak_ptr();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Accessors.
|
||||
T* get() const { return impl_.lock().get(); }
|
||||
|
||||
T& operator*() const {
|
||||
T* const pointer = get();
|
||||
OSP_CHECK(pointer);
|
||||
return *pointer;
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
T* const pointer = get();
|
||||
OSP_CHECK(pointer);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// Allow conditionals to test validity, e.g. if (weak_ptr) {...}
|
||||
explicit operator bool() const { return get() != nullptr; }
|
||||
|
||||
// Conversion to std::weak_ptr<T>. It is unsafe to convert in the other
|
||||
// direction. See comments for private constructors, below.
|
||||
const std::weak_ptr<T>& as_std_weak_ptr() const& { return impl_; }
|
||||
std::weak_ptr<T> as_std_weak_ptr() && { return std::move(impl_); }
|
||||
|
||||
private:
|
||||
friend class WeakPtrFactory<T>;
|
||||
|
||||
// Called by WeakPtrFactory<T> and the WeakPtr<T> upcast conversion
|
||||
// constructors and assigners. These are purposely not being exposed publicly
|
||||
// because that would allow a WeakPtr<T> to be valid/invalid by a different
|
||||
// ownership/threading model than the intended one (see top-level comments).
|
||||
template <typename U>
|
||||
explicit WeakPtr(const std::weak_ptr<U>& other) : impl_(other) {}
|
||||
|
||||
template <typename U>
|
||||
explicit WeakPtr(std::weak_ptr<U>&& other) noexcept
|
||||
: impl_(std::move(other)) {}
|
||||
|
||||
std::weak_ptr<T> impl_;
|
||||
};
|
||||
|
||||
// Allow callers to compare WeakPtrs against nullptr to test validity.
|
||||
template <typename T>
|
||||
bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
|
||||
return weak_ptr.get() != nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
|
||||
return weak_ptr.get() != nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
|
||||
return weak_ptr.get() == nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
|
||||
return weak_ptr == nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class WeakPtrFactory {
|
||||
public:
|
||||
explicit WeakPtrFactory(T* instance) { Reset(instance); }
|
||||
WeakPtrFactory(WeakPtrFactory&& other) noexcept = default;
|
||||
WeakPtrFactory& operator=(WeakPtrFactory&& other) noexcept = default;
|
||||
|
||||
// Thread-safe: WeakPtrs may be created on any thread/seuence. They may also
|
||||
// be copied and moved on any thread/sequence. However, they MUST only be
|
||||
// dereferenced on the same thread/sequence that calls the destructor or
|
||||
// InvalidateWeakPtrs().
|
||||
WeakPtr<T> GetWeakPtr() const {
|
||||
return WeakPtr<T>(std::weak_ptr<T>(bookkeeper_));
|
||||
}
|
||||
|
||||
// Destruction and Invalidation: These must be called on the same
|
||||
// thread/sequence that dereferences any WeakPtrs to avoid use-after-free
|
||||
// bugs.
|
||||
~WeakPtrFactory() = default;
|
||||
void InvalidateWeakPtrs() { Reset(bookkeeper_.get()); }
|
||||
|
||||
private:
|
||||
WeakPtrFactory(const WeakPtrFactory& other) = delete;
|
||||
WeakPtrFactory& operator=(const WeakPtrFactory& other) = delete;
|
||||
|
||||
void Reset(T* instance) {
|
||||
// T is owned externally to WeakPtrFactory. Thus, provide a no-op Deleter.
|
||||
bookkeeper_ = {instance, [](T*) {}};
|
||||
}
|
||||
|
||||
// Manages the std::weak_ptr's referring to T. Does not own T.
|
||||
std::shared_ptr<T> bookkeeper_;
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_WEAK_PTR_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue