X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/53b27422d140022594fc241cca91c3183be57bca..48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff:/iOS/Pods/Realm/include/index_set.hpp diff --git a/iOS/Pods/Realm/include/index_set.hpp b/iOS/Pods/Realm/include/index_set.hpp new file mode 100644 index 0000000..55bedcc --- /dev/null +++ b/iOS/Pods/Realm/include/index_set.hpp @@ -0,0 +1,325 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +#ifndef REALM_INDEX_SET_HPP +#define REALM_INDEX_SET_HPP + +#include +#include +#include +#include +#include +#include + +namespace realm { +namespace _impl { +template +class MutableChunkedRangeVectorIterator; + +// An iterator for ChunkedRangeVector, templated on the vector iterator/const_iterator +template +class ChunkedRangeVectorIterator { +public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = typename std::remove_referencedata.begin())>::type; + using difference_type = ptrdiff_t; + using pointer = const value_type*; + using reference = const value_type&; + + ChunkedRangeVectorIterator(OuterIterator outer, OuterIterator end, value_type* inner) + : m_outer(outer), m_end(end), m_inner(inner) { } + + reference operator*() const noexcept { return *m_inner; } + pointer operator->() const noexcept { return m_inner; } + + template bool operator==(Other const& it) const noexcept; + template bool operator!=(Other const& it) const noexcept; + + ChunkedRangeVectorIterator& operator++() noexcept; + ChunkedRangeVectorIterator operator++(int) noexcept; + + ChunkedRangeVectorIterator& operator--() noexcept; + ChunkedRangeVectorIterator operator--(int) noexcept; + + // Advance directly to the next outer block + void next_chunk() noexcept; + + OuterIterator outer() const noexcept { return m_outer; } + size_t offset() const noexcept { return m_inner - &m_outer->data[0]; } + +private: + OuterIterator m_outer; + OuterIterator m_end; + value_type* m_inner; + friend struct ChunkedRangeVector; + friend class MutableChunkedRangeVectorIterator; +}; + +// A mutable iterator that adds some invariant-preserving mutation methods +template +class MutableChunkedRangeVectorIterator : public ChunkedRangeVectorIterator { +public: + using ChunkedRangeVectorIterator::ChunkedRangeVectorIterator; + + // Set this iterator to the given range and update the parent if needed + void set(size_t begin, size_t end); + // Adjust the begin and end of this iterator by the given amounts and + // update the parent if needed + void adjust(ptrdiff_t front, ptrdiff_t back); + // Shift this iterator by the given amount and update the parent if needed + void shift(ptrdiff_t distance); +}; + +// A vector which stores ranges in chunks with a maximum size +struct ChunkedRangeVector { + struct Chunk { + std::vector> data; + size_t begin; + size_t end; + size_t count; + }; + std::vector m_data; + + using value_type = std::pair; + using iterator = MutableChunkedRangeVectorIterator; + using const_iterator = ChunkedRangeVectorIterator; + +#ifdef REALM_DEBUG + static const size_t max_size = 4; +#else + static const size_t max_size = 4096 / sizeof(std::pair); +#endif + + iterator begin() noexcept { return empty() ? end() : iterator(m_data.begin(), m_data.end(), &m_data[0].data[0]); } + iterator end() noexcept { return iterator(m_data.end(), m_data.end(), nullptr); } + const_iterator begin() const noexcept { return cbegin(); } + const_iterator end() const noexcept { return cend(); } + const_iterator cbegin() const noexcept { return empty() ? cend() : const_iterator(m_data.cbegin(), m_data.end(), &m_data[0].data[0]); } + const_iterator cend() const noexcept { return const_iterator(m_data.end(), m_data.end(), nullptr); } + + bool empty() const noexcept { return m_data.empty(); } + + iterator insert(iterator pos, value_type value); + iterator erase(iterator pos) noexcept; + void push_back(value_type value); + iterator ensure_space(iterator pos); + + void verify() const noexcept; +}; +} // namespace _impl + +class IndexSet : private _impl::ChunkedRangeVector { +public: + static const size_t npos = -1; + + using ChunkedRangeVector::value_type; + using ChunkedRangeVector::iterator; + using ChunkedRangeVector::const_iterator; + using ChunkedRangeVector::begin; + using ChunkedRangeVector::end; + using ChunkedRangeVector::empty; + using ChunkedRangeVector::verify; + + IndexSet() = default; + IndexSet(std::initializer_list); + + // Check if the index set contains the given index + bool contains(size_t index) const noexcept; + + // Counts the number of indices in the set in the given range + size_t count(size_t start_index=0, size_t end_index=-1) const noexcept; + + // Add an index to the set, doing nothing if it's already present + void add(size_t index); + void add(IndexSet const& is); + + // Add an index which has had all of the ranges in the set before it removed + // Returns the unshifted index + size_t add_shifted(size_t index); + // Add indexes which have had the ranges in `shifted_by` added and the ranges + // in the current set removed + void add_shifted_by(IndexSet const& shifted_by, IndexSet const& values); + + // Remove all indexes from the set and then add a single range starting from + // zero with the given length + void set(size_t len); + + // Insert an index at the given position, shifting existing indexes at or + // after that point back by one + void insert_at(size_t index, size_t count=1); + void insert_at(IndexSet const&); + + // Shift indexes at or after the given point back by one + void shift_for_insert_at(size_t index, size_t count=1); + void shift_for_insert_at(IndexSet const&); + + // Delete an index at the given position, shifting indexes after that point + // forward by one + void erase_at(size_t index); + void erase_at(IndexSet const&); + + // If the given index is in the set remove it and return npos; otherwise unshift() it + size_t erase_or_unshift(size_t index); + + // Remove the indexes at the given index from the set, without shifting + void remove(size_t index, size_t count=1); + void remove(IndexSet const&); + + // Shift an index by inserting each of the indexes in this set + size_t shift(size_t index) const noexcept; + // Shift an index by deleting each of the indexes in this set + size_t unshift(size_t index) const noexcept; + + // Remove all indexes from the set + void clear() noexcept; + + // An iterator over the individual indices in the set rather than the ranges + class IndexIterator : public std::iterator { + public: + IndexIterator(IndexSet::const_iterator it) : m_iterator(it) { } + size_t operator*() const noexcept { return m_iterator->first + m_offset; } + bool operator==(IndexIterator const& it) const noexcept { return m_iterator == it.m_iterator; } + bool operator!=(IndexIterator const& it) const noexcept { return m_iterator != it.m_iterator; } + + IndexIterator& operator++() noexcept + { + ++m_offset; + if (m_iterator->first + m_offset == m_iterator->second) { + ++m_iterator; + m_offset = 0; + } + return *this; + } + + IndexIterator operator++(int) noexcept + { + auto value = *this; + ++*this; + return value; + } + + private: + IndexSet::const_iterator m_iterator; + size_t m_offset = 0; + }; + + class IndexIteratableAdaptor { + public: + using value_type = size_t; + using iterator = IndexIterator; + using const_iterator = iterator; + + const_iterator begin() const noexcept { return m_index_set.begin(); } + const_iterator end() const noexcept { return m_index_set.end(); } + + IndexIteratableAdaptor(IndexSet const& is) : m_index_set(is) { } + private: + IndexSet const& m_index_set; + }; + + IndexIteratableAdaptor as_indexes() const noexcept { return *this; } + +private: + // Find the range which contains the index, or the first one after it if + // none do + iterator find(size_t index) noexcept; + iterator find(size_t index, iterator it) noexcept; + // Insert the index before the given position, combining existing ranges as + // applicable + // returns inserted position + iterator do_add(iterator pos, size_t index); + void do_erase(iterator it, size_t index); + iterator do_remove(iterator it, size_t index, size_t count); + + void shift_until_end_by(iterator begin, ptrdiff_t shift); +}; + +namespace util { +// This was added in C++14 but is missing from libstdc++ 4.9 +template +std::reverse_iterator make_reverse_iterator(Iterator it) noexcept +{ + return std::reverse_iterator(it); +} +} // namespace util + + +namespace _impl { +template +template +inline bool ChunkedRangeVectorIterator::operator==(OtherIterator const& it) const noexcept +{ + return m_outer == it.outer() && m_inner == it.operator->(); +} + +template +template +inline bool ChunkedRangeVectorIterator::operator!=(OtherIterator const& it) const noexcept +{ + return !(*this == it); +} + +template +inline ChunkedRangeVectorIterator& ChunkedRangeVectorIterator::operator++() noexcept +{ + ++m_inner; + if (offset() == m_outer->data.size()) + next_chunk(); + return *this; +} + +template +inline ChunkedRangeVectorIterator ChunkedRangeVectorIterator::operator++(int) noexcept +{ + auto value = *this; + ++*this; + return value; +} + +template +inline ChunkedRangeVectorIterator& ChunkedRangeVectorIterator::operator--() noexcept +{ + if (!m_inner || m_inner == &m_outer->data.front()) { + --m_outer; + m_inner = &m_outer->data.back(); + } + else { + --m_inner; + } + return *this; +} + +template +inline ChunkedRangeVectorIterator ChunkedRangeVectorIterator::operator--(int) noexcept +{ + auto value = *this; + --*this; + return value; +} + +template +inline void ChunkedRangeVectorIterator::next_chunk() noexcept +{ + ++m_outer; + m_inner = m_outer != m_end ? &m_outer->data[0] : nullptr; +} +} // namespace _impl + +} // namespace realm + +#endif // REALM_INDEX_SET_HPP