зеркало из https://github.com/microsoft/cppwinrt.git
340 строки
12 KiB
C++
340 строки
12 KiB
C++
|
|
namespace winrt::impl
|
|
{
|
|
template <typename T, typename Container>
|
|
using multi_threaded_vector = vector_impl<T, Container, multi_threaded_collection_base>;
|
|
|
|
template <typename Container, typename ThreadingBase = single_threaded_collection_base>
|
|
struct inspectable_observable_vector :
|
|
observable_vector_base<inspectable_observable_vector<Container, ThreadingBase>, Windows::Foundation::IInspectable>,
|
|
implements<inspectable_observable_vector<Container, ThreadingBase>,
|
|
wfc::IObservableVector<Windows::Foundation::IInspectable>, wfc::IVector<Windows::Foundation::IInspectable>, wfc::IVectorView<Windows::Foundation::IInspectable>, wfc::IIterable<Windows::Foundation::IInspectable>>,
|
|
ThreadingBase
|
|
{
|
|
static_assert(std::is_same_v<Container, std::remove_reference_t<Container>>, "Must be constructed with rvalue.");
|
|
|
|
explicit inspectable_observable_vector(Container&& values) : m_values(std::forward<Container>(values))
|
|
{
|
|
}
|
|
|
|
auto& get_container() noexcept
|
|
{
|
|
return m_values;
|
|
}
|
|
|
|
auto& get_container() const noexcept
|
|
{
|
|
return m_values;
|
|
}
|
|
|
|
using ThreadingBase::acquire_shared;
|
|
using ThreadingBase::acquire_exclusive;
|
|
|
|
private:
|
|
|
|
Container m_values;
|
|
};
|
|
|
|
template <typename Container>
|
|
using multi_threaded_inspectable_observable_vector = inspectable_observable_vector<Container, multi_threaded_collection_base>;
|
|
|
|
template <typename T, typename Container, typename ThreadingBase = single_threaded_collection_base>
|
|
struct convertible_observable_vector :
|
|
observable_vector_base<convertible_observable_vector<T, Container, ThreadingBase>, T>,
|
|
implements<convertible_observable_vector<T, Container, ThreadingBase>,
|
|
wfc::IObservableVector<T>, wfc::IVector<T>, wfc::IVectorView<T>, wfc::IIterable<T>,
|
|
wfc::IObservableVector<Windows::Foundation::IInspectable>, wfc::IVector<Windows::Foundation::IInspectable>, wfc::IVectorView<Windows::Foundation::IInspectable>, wfc::IIterable<Windows::Foundation::IInspectable>>,
|
|
ThreadingBase
|
|
{
|
|
static_assert(!std::is_same_v<T, Windows::Foundation::IInspectable>);
|
|
static_assert(std::is_same_v<Container, std::remove_reference_t<Container>>, "Must be constructed with rvalue.");
|
|
|
|
using container_type = convertible_observable_vector<T, Container, ThreadingBase>;
|
|
using base_type = observable_vector_base<convertible_observable_vector<T, Container, ThreadingBase>, T>;
|
|
|
|
explicit convertible_observable_vector(Container&& values) : m_values(std::forward<Container>(values))
|
|
{
|
|
}
|
|
|
|
auto& get_container() noexcept
|
|
{
|
|
return m_values;
|
|
}
|
|
|
|
auto& get_container() const noexcept
|
|
{
|
|
return m_values;
|
|
}
|
|
|
|
using ThreadingBase::acquire_shared;
|
|
using ThreadingBase::acquire_exclusive;
|
|
|
|
auto First()
|
|
{
|
|
struct result
|
|
{
|
|
container_type* container;
|
|
|
|
operator wfc::IIterator<T>()
|
|
{
|
|
return static_cast<base_type*>(container)->First();
|
|
}
|
|
|
|
operator wfc::IIterator<Windows::Foundation::IInspectable>()
|
|
{
|
|
[[maybe_unused]] auto guard = container->acquire_shared();
|
|
return make<iterator>(container);
|
|
}
|
|
};
|
|
|
|
return result{ this };
|
|
}
|
|
|
|
auto GetAt(uint32_t const index) const
|
|
{
|
|
struct result
|
|
{
|
|
base_type const* container;
|
|
uint32_t const index;
|
|
|
|
operator T() const
|
|
{
|
|
return container->GetAt(index);
|
|
}
|
|
|
|
operator Windows::Foundation::IInspectable() const
|
|
{
|
|
return box_value(container->GetAt(index));
|
|
}
|
|
};
|
|
|
|
return result{ this, index };
|
|
}
|
|
|
|
using base_type::IndexOf;
|
|
|
|
bool IndexOf(Windows::Foundation::IInspectable const& value, uint32_t& index) const
|
|
{
|
|
if constexpr (is_com_interface_v<T>)
|
|
{
|
|
if (!value)
|
|
{
|
|
return base_type::IndexOf(nullptr, index);
|
|
}
|
|
else if (auto as = value.try_as<T>())
|
|
{
|
|
return base_type::IndexOf(as, index);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (auto as = value.try_as<T>())
|
|
{
|
|
return base_type::IndexOf(as.value(), index);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
using base_type::GetMany;
|
|
|
|
uint32_t GetMany(uint32_t const startIndex, array_view<Windows::Foundation::IInspectable> values) const
|
|
{
|
|
[[maybe_unused]] auto guard = this->acquire_shared();
|
|
if (startIndex >= m_values.size())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
uint32_t const actual = (std::min)(static_cast<uint32_t>(m_values.size() - startIndex), values.size());
|
|
|
|
std::transform(m_values.begin() + startIndex, m_values.begin() + startIndex + actual, values.begin(), [&](auto && value)
|
|
{
|
|
return box_value(value);
|
|
});
|
|
|
|
return actual;
|
|
}
|
|
|
|
auto GetView() const noexcept
|
|
{
|
|
struct result
|
|
{
|
|
container_type const* container;
|
|
|
|
operator wfc::IVectorView<T>() const
|
|
{
|
|
return *container;
|
|
}
|
|
|
|
operator wfc::IVectorView<Windows::Foundation::IInspectable>() const
|
|
{
|
|
return *container;
|
|
}
|
|
};
|
|
|
|
return result{ this };
|
|
}
|
|
|
|
using base_type::SetAt;
|
|
|
|
void SetAt(uint32_t const index, Windows::Foundation::IInspectable const& value)
|
|
{
|
|
SetAt(index, unbox_value<T>(value));
|
|
}
|
|
|
|
using base_type::InsertAt;
|
|
|
|
void InsertAt(uint32_t const index, Windows::Foundation::IInspectable const& value)
|
|
{
|
|
InsertAt(index, unbox_value<T>(value));
|
|
}
|
|
|
|
using base_type::Append;
|
|
|
|
void Append(Windows::Foundation::IInspectable const& value)
|
|
{
|
|
Append(unbox_value<T>(value));
|
|
}
|
|
|
|
using base_type::ReplaceAll;
|
|
|
|
void ReplaceAll(array_view<Windows::Foundation::IInspectable const> values)
|
|
{
|
|
Container new_values;
|
|
new_values.reserve(values.size());
|
|
|
|
std::transform(values.begin(), values.end(), std::back_inserter(new_values), [&](auto && value)
|
|
{
|
|
return unbox_value<T>(value);
|
|
});
|
|
|
|
base_type::ReplaceAll(std::move(new_values));
|
|
}
|
|
|
|
using base_type::VectorChanged;
|
|
|
|
event_token VectorChanged(wfc::VectorChangedEventHandler<Windows::Foundation::IInspectable> const& handler)
|
|
{
|
|
return base_type::VectorChanged([handler](auto && sender, auto && args)
|
|
{
|
|
handler(sender.template try_as<wfc::IObservableVector<Windows::Foundation::IInspectable>>(), args);
|
|
});
|
|
}
|
|
|
|
private:
|
|
|
|
struct iterator :
|
|
impl::collection_version::iterator_type,
|
|
implements<iterator, Windows::Foundation::Collections::IIterator<Windows::Foundation::IInspectable>>
|
|
{
|
|
explicit iterator(container_type* const container) noexcept :
|
|
impl::collection_version::iterator_type(*container),
|
|
m_current(container->get_container().begin()),
|
|
m_end(container->get_container().end())
|
|
{
|
|
m_owner.copy_from(container);
|
|
}
|
|
|
|
Windows::Foundation::IInspectable Current() const
|
|
{
|
|
[[maybe_unused]] auto guard = m_owner->acquire_shared();
|
|
check_version(*m_owner);
|
|
if (m_current == m_end)
|
|
{
|
|
throw hresult_out_of_bounds();
|
|
}
|
|
|
|
return box_value(*m_current);
|
|
}
|
|
|
|
bool HasCurrent() const
|
|
{
|
|
[[maybe_unused]] auto guard = m_owner->acquire_shared();
|
|
check_version(*m_owner);
|
|
return m_current != m_end;
|
|
}
|
|
|
|
bool MoveNext()
|
|
{
|
|
[[maybe_unused]] auto guard = m_owner->acquire_exclusive();
|
|
check_version(*m_owner);
|
|
if (m_current != m_end)
|
|
{
|
|
++m_current;
|
|
}
|
|
|
|
return m_current != m_end;
|
|
}
|
|
|
|
uint32_t GetMany(array_view<Windows::Foundation::IInspectable> values)
|
|
{
|
|
[[maybe_unused]] auto guard = m_owner->acquire_exclusive();
|
|
check_version(*m_owner);
|
|
uint32_t const actual = (std::min)(static_cast<uint32_t>(std::distance(m_current, m_end)), values.size());
|
|
|
|
std::transform(m_current, m_current + actual, values.begin(), [&](auto && value)
|
|
{
|
|
return box_value(value);
|
|
});
|
|
|
|
std::advance(m_current, actual);
|
|
return actual;
|
|
}
|
|
|
|
private:
|
|
|
|
com_ptr<container_type> m_owner;
|
|
decltype(m_owner->get_container().begin()) m_current;
|
|
decltype(m_owner->get_container().end()) const m_end;
|
|
};
|
|
|
|
Container m_values;
|
|
};
|
|
|
|
template <typename T, typename Container>
|
|
using multi_threaded_convertible_observable_vector = convertible_observable_vector<T, Container, multi_threaded_collection_base>;
|
|
}
|
|
|
|
WINRT_EXPORT namespace winrt
|
|
{
|
|
template <typename T, typename Allocator = std::allocator<T>>
|
|
Windows::Foundation::Collections::IVector<T> single_threaded_vector(std::vector<T, Allocator>&& values = {})
|
|
{
|
|
return make<impl::input_vector<T, std::vector<T, Allocator>>>(std::move(values));
|
|
}
|
|
|
|
template <typename T, typename Allocator = std::allocator<T>>
|
|
Windows::Foundation::Collections::IVector<T> multi_threaded_vector(std::vector<T, Allocator>&& values = {})
|
|
{
|
|
return make<impl::multi_threaded_vector<T, std::vector<T, Allocator>>>(std::move(values));
|
|
}
|
|
|
|
template <typename T, typename Allocator = std::allocator<T>>
|
|
Windows::Foundation::Collections::IObservableVector<T> single_threaded_observable_vector(std::vector<T, Allocator>&& values = {})
|
|
{
|
|
if constexpr (std::is_same_v<T, Windows::Foundation::IInspectable>)
|
|
{
|
|
return make<impl::inspectable_observable_vector<std::vector<T, Allocator>>>(std::move(values));
|
|
}
|
|
else
|
|
{
|
|
return make<impl::convertible_observable_vector<T, std::vector<T, Allocator>>>(std::move(values));
|
|
}
|
|
}
|
|
|
|
template <typename T, typename Allocator = std::allocator<T>>
|
|
Windows::Foundation::Collections::IObservableVector<T> multi_threaded_observable_vector(std::vector<T, Allocator>&& values = {})
|
|
{
|
|
if constexpr (std::is_same_v<T, Windows::Foundation::IInspectable>)
|
|
{
|
|
return make<impl::multi_threaded_inspectable_observable_vector<std::vector<T, Allocator>>>(std::move(values));
|
|
}
|
|
else
|
|
{
|
|
return make<impl::multi_threaded_convertible_observable_vector<T, std::vector<T, Allocator>>>(std::move(values));
|
|
}
|
|
}
|
|
}
|