Files
Z3D/source/assets/data_stores/shader_source_store.ipp

304 lines
7.5 KiB
C++

#ifndef INCLUDE_SHADER_SOURCE_STORE_IMPLEMENTATION
# error Never include this file directly include 'shader_source_store.hpp'
#endif
#include <vector>
#include <span>
#include <tuple>
#include <cstddef>
#include <type_traits>
#include <algorithm>
template<typename Char>
assets::shader_source_store_iterator<Char>::shader_source_store_iterator(
id_iterator_type ids,
string_iterator_type strings,
length_iterator_type lengths,
std::size_t index,
const offset_type& offset
) :
m_ids{ ids },
m_strings{ strings },
m_lengths{ lengths },
m_index{ index },
m_offset{ offset } {}
template<typename Char>
typename assets::shader_source_store_iterator<Char>::reference assets::shader_source_store_iterator<Char>::operator*() const {
return dereference(std::index_sequence_for<Char>{});
}
template<typename Char>
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator++() {
adjust_offsets(std::index_sequence_for<Char>{}, 1);
++m_index;
return *this;
}
template<typename Char>
assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<Char>::operator++(int) {
shader_source_store_iterator tmp = *this;
++(*this);
return tmp;
}
template<typename Char>
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator--() {
adjust_offsets(std::index_sequence_for<Char>{}, -1);
--m_index;
return *this;
}
template<typename Char>
assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<Char>::operator--(int) {
auto tmp = *this;
--(*this);
return tmp;
}
template<typename Char>
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator+=(const difference_type n)
{
adjust_offsets(std::index_sequence_for<Char>{}, n);
m_index += n;
return *this;
}
template<typename Char>
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator-=(const difference_type n)
{
return (*this) += -n;
}
template<typename Char>
assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<Char>::operator+(const difference_type n) const
{
auto tmp = *this;
return tmp += n; // TODO clion says n is unused
}
template<typename Char>
assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<Char>::operator-(const difference_type n) const
{
auto tmp = *this;
return tmp -= n; // TODO clion says n is unused
}
template<typename Char>
typename assets::shader_source_store_iterator<Char>::difference_type
assets::shader_source_store_iterator<Char>::operator-(const shader_source_store_iterator& other) const
{
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
}
template<typename Char>
typename assets::shader_source_store_iterator<Char>::reference assets::shader_source_store_iterator<Char>::operator[](
const difference_type n
) const {
return *(*this + n);
}
template<typename Char>
bool assets::shader_source_store_iterator<Char>::operator==(const shader_source_store_iterator& other) const
{
return m_ids == other.m_ids and m_index == other.m_index;
}
template<typename Char>
bool assets::shader_source_store_iterator<Char>::operator!=(const shader_source_store_iterator& other) const
{
return not (*this == other);
}
template<typename Char>
bool assets::shader_source_store_iterator<Char>::operator<(const shader_source_store_iterator& other) const
{
return m_index < other.m_index;
}
template<typename Char>
bool assets::shader_source_store_iterator<Char>::operator<=(const shader_source_store_iterator& other) const
{
return m_index <= other.m_index;
}
template<typename Char>
bool assets::shader_source_store_iterator<Char>::operator>(const shader_source_store_iterator& other) const
{
return m_index > other.m_index;
}
template<typename Char>
bool assets::shader_source_store_iterator<Char>::operator>=(const shader_source_store_iterator& other) const
{
return m_index >= other.m_index;
}
template<typename Char>
void assets::shader_source_store_iterator<Char>::calc_offset(
difference_type n
) {
const auto negative = n < difference_type{ 0 };
const auto positive = n > difference_type{ 0 };
const auto step = difference_type{ positive } - difference_type{ negative };
n = negative ? -n : n;
// TODO template optimize for single steps
while (n--)
{
const auto& count = m_lengths[m_index];
m_offset += step * count;
m_index += step;
}
}
template<typename Char>
template<std::size_t... Is>
typename assets::shader_source_store_iterator<Char>::reference
assets::shader_source_store_iterator<Char>::dereference(std::index_sequence<Is...>) const
{
return std::make_pair(
m_ids[m_index],
shader_source_view(
m_strings[m_offset],
m_lengths[m_index]
)
);
}
assets::shader_source_store::id_type assets::shader_source_store::add(
const shader_source_data& shader_source
) {
const auto id = id_type{ m_next_data_id.index++ };
m_ids.push_back(id);
m_strings.reserve(m_strings.size() + shader_source.source.size() + 1);
m_strings.insert(m_strings.end(), shader_source.source.begin(), shader_source.source.end());
m_strings.push_back('\0');
m_lengths.push_back(shader_source.source.size());
return id;
}
std::pair<assets::shader_source_store::iterator_type, bool> assets::shader_source_store::find(id_type id)
{
const auto id_it = std::ranges::upper_bound(m_ids, id);
const auto match = (
id_it != m_ids.begin() and
*std::prev(id_it) == id
);
const auto index = id_it - m_ids.begin() - match;
auto it = begin();
it += index;
return { it, match };
}
std::pair<assets::shader_source_store::const_iterator, bool> assets::shader_source_store::find(id_type id) const
{
const auto id_it = std::ranges::upper_bound(m_ids, id);
const auto match = (
id_it != m_ids.begin() and
*std::prev(id_it) == id
);
const auto index = id_it - m_ids.begin() - match;
auto it = begin();
it += index;
return { it, match };
}
void assets::shader_source_store::remove(const iterator_type& it)
{
m_ids.erase(m_ids.begin() + it.m_index);
const auto begin = m_strings.begin() + it.m_offset;
const auto end = begin + it.m_lengths[it.m_index];
m_strings.erase(begin, end);
m_lengths.erase(m_lengths.begin() + it.m_index);
}
void assets::shader_source_store::clear()
{
m_ids.clear();
m_strings.clear();
m_lengths.clear();
}
assets::shader_source_store::iterator_type assets::shader_source_store::begin()
{
return iterator_type{
m_ids.data(),
m_strings.data(),
m_lengths.data(),
0,
{}
};
}
assets::shader_source_store::iterator_type assets::shader_source_store::end()
{
return iterator_type{
m_ids.data(),
m_strings.data(),
m_lengths.data(),
m_lengths.size(),
m_strings.size()
};
}
assets::shader_source_store::const_iterator assets::shader_source_store::begin() const
{
return const_iterator{
m_ids.data(),
m_strings.data(),
m_lengths.data(),
0,
{}
};
}
assets::shader_source_store::const_iterator assets::shader_source_store::end() const
{
return const_iterator{
m_ids.data(),
m_strings.data(),
m_lengths.data(),
m_lengths.size(),
m_strings.size()
};
}
assets::shader_source_store::const_iterator assets::shader_source_store::cbegin() const
{
return const_cast<const shader_source_store*>(this)->begin();
}
assets::shader_source_store::const_iterator assets::shader_source_store::cend() const
{
return const_cast<const shader_source_store*>(this)->end();
}
assets::shader_source_store::view_type assets::shader_source_store::view()
{
return { begin(), end() };
}
assets::shader_source_store::const_view_type assets::shader_source_store::view() const
{
return { begin(), end() };
}