#ifndef INCLUDE_SHADER_SOURCE_STORE_IMPLEMENTATION # error Never include this file directly include 'shader_source_store.hpp' #endif #include #include #include #include #include #include #include "opengl/metadata/shader_source_metadata.hpp" template assets::shader_source_store_iterator::shader_source_store_iterator( id_iterator_type ids, string_iterator_type strings, length_iterator_type lengths, metadata_iterator_type metadata, const size_type index, const offset_type& offset ) : m_ids{ ids }, m_strings{ strings }, m_lengths{ lengths }, m_metadata{ metadata }, m_index{ index }, m_offset{ offset } {} template typename assets::shader_source_store_iterator::reference assets::shader_source_store_iterator::operator*() const { return dereference(); } template assets::shader_source_store_iterator& assets::shader_source_store_iterator::operator++() { calc_offset(1); ++m_index; return *this; } template assets::shader_source_store_iterator assets::shader_source_store_iterator::operator++(int) { shader_source_store_iterator tmp = *this; ++(*this); return tmp; } template assets::shader_source_store_iterator& assets::shader_source_store_iterator::operator--() { calc_offset(-1); --m_index; return *this; } template assets::shader_source_store_iterator assets::shader_source_store_iterator::operator--(int) { auto tmp = *this; --(*this); return tmp; } template assets::shader_source_store_iterator& assets::shader_source_store_iterator::operator+=(const difference_type n) { calc_offset(n); m_index += n; return *this; } template assets::shader_source_store_iterator& assets::shader_source_store_iterator::operator-=(const difference_type n) { return (*this) += -n; } template assets::shader_source_store_iterator assets::shader_source_store_iterator::operator+(const difference_type n) const { auto tmp = *this; return tmp += n; // TODO clion says n is unused } template assets::shader_source_store_iterator assets::shader_source_store_iterator::operator-(const difference_type n) const { auto tmp = *this; return tmp -= n; // TODO clion says n is unused } template typename assets::shader_source_store_iterator::difference_type assets::shader_source_store_iterator::operator-(const shader_source_store_iterator& other) const { return static_cast(m_index) - static_cast(other.m_index); } template typename assets::shader_source_store_iterator::reference assets::shader_source_store_iterator::operator[]( const difference_type n ) const { return *(*this + n); } template bool assets::shader_source_store_iterator::operator==(const shader_source_store_iterator& other) const { return m_ids == other.m_ids and m_index == other.m_index; } template bool assets::shader_source_store_iterator::operator!=(const shader_source_store_iterator& other) const { return not (*this == other); } template bool assets::shader_source_store_iterator::operator<(const shader_source_store_iterator& other) const { return m_index < other.m_index; } template bool assets::shader_source_store_iterator::operator<=(const shader_source_store_iterator& other) const { return m_index <= other.m_index; } template bool assets::shader_source_store_iterator::operator>(const shader_source_store_iterator& other) const { return m_index > other.m_index; } template bool assets::shader_source_store_iterator::operator>=(const shader_source_store_iterator& other) const { return m_index >= other.m_index; } template void assets::shader_source_store_iterator::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 assets::shader_source_store_iterator::reference assets::shader_source_store_iterator::dereference() const { return std::make_pair( m_ids[m_index], shader_source_view{ .source = { m_strings[m_offset], m_lengths[m_index] }, .meta = m_metadata[m_index] } ); } inline bool assets::shader_source_store::insert(const id_type id, const data_type& data) { auto lock = std::unique_lock{ m_mutex }; const auto result = find(id); return insert(result.first, id, data); } inline std::pair assets::shader_source_store::find(id_type id) { auto lock = std::shared_lock{ m_mutex }; return unsafe_find(id); } inline std::pair assets::shader_source_store::find(id_type id) const { auto lock = std::shared_lock{ m_mutex }; return unsafe_find(id); } inline bool assets::shader_source_store::unsafe_insert(iterator it, const id_type id, const data_type& data) { auto lock = std::unique_lock{ m_mutex }; const auto index = it.m_index; const auto new_entry = index == m_ids.size() or m_ids[index] != id; auto dst_source_length = count_type{}; const auto src_source_length = data.source.size(); if (new_entry) { m_ids.insert(m_ids.begin() + index, id); m_lengths.insert(m_lengths.begin() + index, src_source_length); m_metadata.insert(m_metadata.begin() + index, data.meta); } else { dst_source_length = m_lengths[index]; m_lengths[index] = src_source_length; m_metadata[index] = data.meta; } const auto dst_string_it = m_strings.begin() + it.m_offset; ztu::replace_range( m_strings, dst_string_it, dst_string_it + dst_source_length, data.source.begin(), data.source.end() ); if (new_entry) { m_strings.insert(m_strings.begin() + it.m_offset + src_source_length, '\0'); } return new_entry; } inline std::pair assets::shader_source_store::unsafe_find(id_type id) { const auto it = std::ranges::lower_bound(m_ids, id); const auto found = it != m_ids.end() and *it == id; const auto index = std::distance(m_ids.begin(), it); return { begin() + index, found }; } inline std::pair assets::shader_source_store::unsafe_find(id_type id) const { const auto it = std::ranges::lower_bound(m_ids, id); const auto found = it != m_ids.end() and *it == id; const auto index = std::distance(m_ids.begin(), it); return { begin() + index, found }; } void assets::shader_source_store::remove(const iterator& it) { auto lock = std::unique_lock{ m_mutex }; const auto index = it.m_index; m_ids.erase(m_ids.begin() + index); const auto strings_begin = m_strings.begin() + it.m_offset; const auto strings_end = strings_begin + it.m_lengths[it.m_index] + sizeof('\0'); m_strings.erase(strings_begin, strings_end); m_lengths.erase(m_lengths.begin() + index); m_metadata.erase(m_metadata.begin() + index); } void assets::shader_source_store::clear() { auto lock = std::unique_lock{ m_mutex }; m_ids.clear(); m_strings.clear(); m_lengths.clear(); m_metadata.clear(); } std::shared_lock assets::shader_source_store::acquire_read_lock() const { return std::shared_lock{ m_mutex }; } std::unique_lock assets::shader_source_store::acquire_write_lock() { return std::unique_lock{ m_mutex }; } assets::shader_source_store::iterator assets::shader_source_store::begin() { return iterator{ m_ids.data(), m_strings.data(), m_lengths.data(), m_metadata.data(), 0, {} }; } assets::shader_source_store::iterator assets::shader_source_store::end() { return iterator{ m_ids.data(), m_strings.data(), m_lengths.data(), m_metadata.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(), m_metadata.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_metadata.data(), m_lengths.size(), m_strings.size() }; } assets::shader_source_store::const_iterator assets::shader_source_store::cbegin() const { return this->begin(); } assets::shader_source_store::const_iterator assets::shader_source_store::cend() const { return this->end(); }