diff --git a/include/mio/detail/basic_mmap.hpp b/include/mio/detail/basic_mmap.hpp index 7d0aa3a..84afbe2 100644 --- a/include/mio/detail/basic_mmap.hpp +++ b/include/mio/detail/basic_mmap.hpp @@ -1,6 +1,9 @@ #ifndef MIO_BASIC_MMAP_HEADER #define MIO_BASIC_MMAP_HEADER +#include +#include + #ifdef _WIN32 # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN @@ -10,14 +13,18 @@ # define INVALID_HANDLE_VALUE -1 #endif // ifdef _WIN32 -#include -#include - namespace mio { namespace detail { size_t page_size(); +template struct basic_mmap; + +template +bool operator==(const basic_mmap& a, const basic_mmap& b); +template +bool operator!=(const basic_mmap& a, const basic_mmap& b); + /** * Most of the logic in establishing a memory mapping is the same for both read-only and * read-write mappings, so they both inherit from basic_mmap. @@ -27,15 +34,14 @@ template struct basic_mmap using value_type = CharT; using size_type = int64_t; using reference = value_type&; - using const_reference = const reference; + using const_reference = const value_type&; using pointer = value_type*; - using const_pointer = const pointer; + using const_pointer = const value_type*; using difference_type = std::ptrdiff_t; using iterator = pointer; using const_iterator = const_pointer; - // TODO these don't seem to work with regular pointers - //using reverse_iterator = std::reverse_iterator; - //using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; using iterator_category = std::random_access_iterator_tag; #ifdef _WIN32 using handle_type = HANDLE; @@ -56,8 +62,7 @@ private: // On POSIX, we only need a file handle to create a mapping, while on Windows // systems the file handle is necessary to retrieve a file mapping handle, but any - // subsequent operations on the mapped region must be done through the file mapping - // handle. + // subsequent operations on the mapped region must be done through the latter. handle_type file_handle_ = INVALID_HANDLE_VALUE; #if defined(_WIN32) handle_type file_mapping_handle_ = INVALID_HANDLE_VALUE; @@ -110,6 +115,14 @@ public: const_iterator end() const noexcept { return begin() + length(); } const_iterator cend() const noexcept { return begin() + length(); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rcbegin() const { return const_reverse_iterator(end()); } + + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator rcend() const { return const_reverse_iterator(begin()); } + reference operator[](const size_type i) noexcept { return data_[i]; } const_reference operator[](const size_type i) const noexcept { return data_[i]; } @@ -117,11 +130,15 @@ public: const access_mode mode, std::error_code& error); void map(const handle_type handle, const size_type offset, const size_type length, const access_mode mode, std::error_code& error); - void unmap(); void sync(std::error_code& error); + void swap(basic_mmap& other); + + friend bool operator==(const basic_mmap& a, const basic_mmap& b); + friend bool operator!=(const basic_mmap& a, const basic_mmap& b); + private: static handle_type open_file(const std::string& path, diff --git a/include/mio/detail/basic_mmap.ipp b/include/mio/detail/basic_mmap.ipp index 34e6c39..16bf267 100644 --- a/include/mio/detail/basic_mmap.ipp +++ b/include/mio/detail/basic_mmap.ipp @@ -3,6 +3,8 @@ #include "basic_mmap.hpp" +#include + #ifndef _WIN32 # include # include @@ -330,6 +332,38 @@ bool basic_mmap::is_mapped() const noexcept #endif } +template +void basic_mmap::swap(basic_mmap& other) +{ + if(this != &other) + { + using std::swap; + swap(data_, other.data_); + swap(file_handle_, other.file_handle_); +#ifdef _WIN32 + swap(file_mapping_handle_, other.file_mapping_handle_); +#endif + swap(length_, other.length_); + swap(mapped_length_, other.mapped_length_); + } +} + +template +bool operator==(const basic_mmap& a, const basic_mmap& b) +{ + if(a.is_mapped() && b.is_mapped()) + { + return (a.size() == b.size()) && std::equal(a.begin(), a.end(), b.begin()); + } + return !a.is_mapped() && !b.is_mapped(); +} + +template +bool operator!=(const basic_mmap& a, const basic_mmap& b) +{ + return !(a == b); +} + } // namespace detail } // namespace mio diff --git a/include/mio/detail/mmap.ipp b/include/mio/detail/mmap.ipp index 7083ca3..1720a10 100644 --- a/include/mio/detail/mmap.ipp +++ b/include/mio/detail/mmap.ipp @@ -76,6 +76,30 @@ void basic_mmap_sink::map(const handle_type handle, const size_type offse template void basic_mmap_sink::sync(std::error_code& error) { impl_.sync(error); } +template +bool operator==(const basic_mmap_source& a, const basic_mmap_source& b) +{ + return a.impl_ == b.impl_; +} + +template +bool operator!=(const basic_mmap_source& a, const basic_mmap_source& b) +{ + return a.impl_ != b.impl_; +} + +template +bool operator==(const basic_mmap_sink& a, const basic_mmap_sink& b) +{ + return a.impl_ == b.impl_; +} + +template +bool operator!=(const basic_mmap_sink& a, const basic_mmap_sink& b) +{ + return a.impl_ != b.impl_; +} + } // namespace mio #endif // MIO_MMAP_IMPL diff --git a/include/mio/mmap.hpp b/include/mio/mmap.hpp index d7f400f..673d217 100644 --- a/include/mio/mmap.hpp +++ b/include/mio/mmap.hpp @@ -5,6 +5,18 @@ namespace mio { +template class basic_mmap_source; +template class basic_mmap_sink; + +template +bool operator==(const basic_mmap_source& a, const basic_mmap_source& b); +template +bool operator!=(const basic_mmap_source& a, const basic_mmap_source& b); +template +bool operator==(const basic_mmap_sink& a, const basic_mmap_sink& b); +template +bool operator!=(const basic_mmap_sink& a, const basic_mmap_sink& b); + /** * When specifying a file to map, there is no need to worry about providing * offsets that are aligned with the operating system's page granularity, this is taken @@ -23,9 +35,13 @@ namespace mio { */ /** A read-only file memory mapping. */ -template struct basic_mmap_source +template class basic_mmap_source { using impl_type = detail::basic_mmap; + impl_type impl_; + +public: + using value_type = typename impl_type::value_type; using size_type = typename impl_type::size_type; using reference = typename impl_type::reference; @@ -35,15 +51,11 @@ template struct basic_mmap_source using difference_type = typename impl_type::difference_type; using iterator = typename impl_type::iterator; using const_iterator = typename impl_type::const_iterator; - //using reverse_iterator = std::reverse_iterator; - //using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; using iterator_category = typename impl_type::iterator_category; using handle_type = typename impl_type::handle_type; -private: - impl_type impl_; -public: - basic_mmap_source() = default; basic_mmap_source(const std::string& path, const size_type offset, const size_type length); @@ -80,20 +92,33 @@ public: const_iterator end() const noexcept { return impl_.end(); } const_iterator cend() const noexcept { return impl_.cend(); } + const_reverse_iterator rbegin() const noexcept { return impl_.rbegin(); } + const_reverse_iterator crbegin() const noexcept { return impl_.crbegin(); } + const_reverse_iterator rend() const noexcept { return impl_.rend(); } + const_reverse_iterator crend() const noexcept { return impl_.crend(); } + const_reference operator[](const size_type i) const noexcept { return impl_[i]; } void map(const std::string& path, const size_type offset, const size_type length, std::error_code& error); void map(const handle_type handle, const size_type offset, const size_type length, std::error_code& error); - void unmap() { impl_.unmap(); } + + void swap(basic_mmap_source& other) { impl_.swap(other.impl_); } + + friend bool operator==(const basic_mmap_source& a, const basic_mmap_source& b); + friend bool operator!=(const basic_mmap_source& a, const basic_mmap_source& b); }; /** A read-write file memory mapping. */ -template struct basic_mmap_sink +template class basic_mmap_sink { using impl_type = detail::basic_mmap; + impl_type impl_; + +public: + using value_type = typename impl_type::value_type; using size_type = typename impl_type::size_type; using reference = typename impl_type::reference; @@ -103,15 +128,11 @@ template struct basic_mmap_sink using difference_type = typename impl_type::difference_type; using iterator = typename impl_type::iterator; using const_iterator = typename impl_type::const_iterator; - //using reverse_iterator = std::reverse_iterator; - //using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; using iterator_category = typename impl_type::iterator_category; using handle_type = typename impl_type::handle_type; -private: - impl_type impl_; -public: - basic_mmap_sink() = default; basic_mmap_sink(const std::string& path, const size_type offset, const size_type length); @@ -144,14 +165,22 @@ public: pointer data() noexcept { return impl_.data(); } const_pointer data() const noexcept { return impl_.data(); } - iterator begin() noexcept; + iterator begin() noexcept { return impl_.begin(); } const_iterator begin() const noexcept { return impl_.begin(); } const_iterator cbegin() const noexcept { return impl_.cbegin(); } - iterator end() noexcept; + iterator end() noexcept { return impl_.end(); } const_iterator end() const noexcept { return impl_.end(); } const_iterator cend() const noexcept { return impl_.cend(); } + reverse_iterator rbegin() noexcept { return impl_.rbegin(); } + const_reverse_iterator rbegin() const noexcept { return impl_.rbegin(); } + const_reverse_iterator crbegin() const noexcept { return impl_.crbegin(); } + + reverse_iterator rend() noexcept { return impl_.rend(); } + const_reverse_iterator rend() const noexcept { return impl_.rend(); } + const_reverse_iterator crend() const noexcept { return impl_.crend(); } + reference operator[](const size_type i) noexcept { return impl_[i]; } const_reference operator[](const size_type i) const noexcept { return impl_[i]; } @@ -159,11 +188,15 @@ public: const size_type length, std::error_code& error); void map(const handle_type handle, const size_type offset, const size_type length, std::error_code& error); + void unmap() { impl_.unmap(); } /** Flushes the memory mapped page to disk. */ void sync(std::error_code& error); - void unmap() { impl_.unmap(); } + void swap(basic_mmap_sink& other) { impl_.swap(other.impl_); } + + friend bool operator==(const basic_mmap_sink& a, const basic_mmap_sink& b); + friend bool operator!=(const basic_mmap_sink& a, const basic_mmap_sink& b); }; using mmap_sink = basic_mmap_sink; diff --git a/test/test.cpp b/test/test.cpp index 1afce5a..0b9020b 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -39,4 +39,7 @@ int main(int argc, char** argv) assert(0); } } + + auto rit = file_view.rbegin(); + auto rend = file_view.rend(); }