From c52e35b2e839342e795c2028787546961e24e664 Mon Sep 17 00:00:00 2001 From: mandreyel Date: Fri, 6 Oct 2017 00:03:15 +0200 Subject: [PATCH] removed CharTraits --- README.md | 10 +-- include/mio/detail/basic_mmap.hpp | 44 +++++------- include/mio/detail/basic_mmap.ipp | 110 ++++++++++++++---------------- include/mio/mmap.hpp | 45 ++++++------ test/test.cpp | 25 +++++-- 5 files changed, 119 insertions(+), 115 deletions(-) diff --git a/README.md b/README.md index 826f444..a257f83 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,11 @@ int handle_error(const std::error_code& error) int main() { - // Read-only memory map the whole file by using `use_full_file_size` where the + // Read-only memory map the whole file by using `map_entire_file` where the // length of the mapping would otherwise be expected, with the factory method. std::error_code error; mio::mmap_source mmap1 = mio::make_mmap_source("log.txt", - offset_type(0), mio::use_full_file_size, error); + offset_type(0), length_type(mio::map_entire_file), error); if(error) { return handle_error(error); } // Read-write memory map the beginning of some file using the `map` member function. @@ -53,9 +53,11 @@ int main() return handle_error(error); } - // mio exposes an interface that abstracts away memory as a string, so it is - // possible to create mmap objects that have custom underlying character types: + // It's possible to change the character type of the mmap object, which is useful + // for wide strings or reading fixed width integers (although endianness is not + // accounted for by mio, so appropriate conversions need be done by the user). using wmmap_source = mio::basic_mmap_source; + using i32mmap_source = mio::basic_mmap_source; } ``` diff --git a/include/mio/detail/basic_mmap.hpp b/include/mio/detail/basic_mmap.hpp index 17acf08..cd60660 100644 --- a/include/mio/detail/basic_mmap.hpp +++ b/include/mio/detail/basic_mmap.hpp @@ -37,7 +37,7 @@ namespace mio { namespace detail { -enum { use_full_file_size = 0 }; +enum { map_entire_file = 0 }; enum class access_mode { @@ -45,10 +45,7 @@ enum class access_mode read_write }; -template< - typename CharT, - typename CharTraits = std::char_traits -> struct basic_mmap +template struct basic_mmap { using value_type = CharT; using size_type = int64_t; @@ -77,7 +74,7 @@ private: // 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 latter. handle_type file_handle_ = INVALID_HANDLE_VALUE; -#if defined(_WIN32) +#ifdef _WIN32 handle_type file_mapping_handle_ = INVALID_HANDLE_VALUE; #endif @@ -108,8 +105,9 @@ public: bool is_mapped() const noexcept; bool empty() const noexcept { return length() == 0; } - size_type length() const noexcept { return length_ >> sizeof(CharT); } - size_type mapped_length() const noexcept { return mapped_length_ >> sizeof(CharT); } + size_type length() const noexcept { return length_ >> (sizeof(CharT) - 1); } + size_type mapped_length() const noexcept + { return mapped_length_ >> (sizeof(CharT) - 1); } pointer data() noexcept { return data_; } const_pointer data() const noexcept { return data_; } @@ -153,29 +151,23 @@ private: const access_mode mode, std::error_code& error); }; -template -bool operator==(const basic_mmap& a, - const basic_mmap& b); +template +bool operator==(const basic_mmap& a, const basic_mmap& b); -template -bool operator!=(const basic_mmap& a, - const basic_mmap& b); +template +bool operator!=(const basic_mmap& a, const basic_mmap& b); -template -bool operator<(const basic_mmap& a, - const basic_mmap& b); +template +bool operator<(const basic_mmap& a, const basic_mmap& b); -template -bool operator<=(const basic_mmap& a, - const basic_mmap& b); +template +bool operator<=(const basic_mmap& a, const basic_mmap& b); -template -bool operator>(const basic_mmap& a, - const basic_mmap& b); +template +bool operator>(const basic_mmap& a, const basic_mmap& b); -template -bool operator>=(const basic_mmap& a, - const basic_mmap& b); +template +bool operator>=(const basic_mmap& a, const basic_mmap& b); } // namespace detail } // namespace mio diff --git a/include/mio/detail/basic_mmap.ipp b/include/mio/detail/basic_mmap.ipp index 5a0cca1..582ac28 100644 --- a/include/mio/detail/basic_mmap.ipp +++ b/include/mio/detail/basic_mmap.ipp @@ -41,7 +41,7 @@ namespace detail { // Generic handle type for use by free functions. using handle_type = basic_mmap::handle_type; -#if defined(_WIN32) +#ifdef _WIN32 inline DWORD int64_high(int64_t n) noexcept { return n >> 32; @@ -73,7 +73,7 @@ handle_type open_file(const Path& path, const access_mode mode, std::error_code& error = std::make_error_code(std::errc::invalid_argument); return INVALID_HANDLE_VALUE; } -#if defined(_WIN32) +#ifdef _WIN32 const auto handle = ::CreateFile(c_str(path), mode == access_mode::read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -116,14 +116,14 @@ inline int64_t query_file_size(handle_type handle, std::error_code& error) // -- basic_mmap -- -template -basic_mmap::~basic_mmap() +template +basic_mmap::~basic_mmap() { unmap(); } -template -basic_mmap::basic_mmap(basic_mmap&& other) +template +basic_mmap::basic_mmap(basic_mmap&& other) : data_(std::move(other.data_)) , length_(std::move(other.length_)) , mapped_length_(std::move(other.mapped_length_)) @@ -141,8 +141,8 @@ basic_mmap::basic_mmap(basic_mmap&& other) #endif } -template -basic_mmap& basic_mmap::operator=(basic_mmap&& other) +template +basic_mmap& basic_mmap::operator=(basic_mmap&& other) { if(this != &other) { @@ -170,9 +170,9 @@ basic_mmap& basic_mmap::operator=(basic_mm return *this; } -template -typename basic_mmap::handle_type -basic_mmap::mapping_handle() const noexcept +template +typename basic_mmap::handle_type +basic_mmap::mapping_handle() const noexcept { #ifdef _WIN32 return file_mapping_handle_; @@ -181,9 +181,9 @@ basic_mmap::mapping_handle() const noexcept #endif } -template +template template -void basic_mmap::map(String& path, size_type offset, +void basic_mmap::map(String& path, size_type offset, size_type length, access_mode mode, std::error_code& error) { error.clear(); @@ -202,8 +202,8 @@ void basic_mmap::map(String& path, size_type offset, } } -template -void basic_mmap::map(handle_type handle, size_type offset, +template +void basic_mmap::map(handle_type handle, size_type offset, size_type length, access_mode mode, std::error_code& error) { error.clear(); @@ -216,7 +216,7 @@ void basic_mmap::map(handle_type handle, size_type offset, const auto file_size = query_file_size(handle, error); if(error) { return; } - if(length <= use_full_file_size) + if(length <= map_entire_file) { length = file_size; } @@ -231,13 +231,13 @@ void basic_mmap::map(handle_type handle, size_type offset, map(offset, length, mode, error); } -template -void basic_mmap::map(const size_type offset, const size_type length, +template +void basic_mmap::map(const size_type offset, const size_type length, const access_mode mode, std::error_code& error) { const size_type aligned_offset = make_offset_page_aligned(offset); const size_type length_to_map = offset - aligned_offset + length; -#if defined(_WIN32) +#ifdef _WIN32 const size_type max_file_size = offset + length; file_mapping_handle_ = ::CreateFileMapping( file_handle_, @@ -282,8 +282,8 @@ void basic_mmap::map(const size_type offset, const size_type mapped_length_ = length_to_map; } -template -void basic_mmap::sync(std::error_code& error) +template +void basic_mmap::sync(std::error_code& error) { error.clear(); if(!is_open()) @@ -313,8 +313,8 @@ void basic_mmap::sync(std::error_code& error) #endif } -template -void basic_mmap::unmap() +template +void basic_mmap::unmap() { if(!is_open()) { return; } // TODO do we care about errors here? @@ -350,23 +350,23 @@ void basic_mmap::unmap() #endif } -template -typename basic_mmap::pointer -basic_mmap::get_mapping_start() noexcept +template +typename basic_mmap::pointer +basic_mmap::get_mapping_start() noexcept { if(!data_) { return nullptr; } const auto offset = mapped_length_ - length_; return data_ - offset; } -template -bool basic_mmap::is_open() const noexcept +template +bool basic_mmap::is_open() const noexcept { return file_handle_ != INVALID_HANDLE_VALUE; } -template -bool basic_mmap::is_mapped() const noexcept +template +bool basic_mmap::is_mapped() const noexcept { #ifdef _WIN32 return file_mapping_handle_ != INVALID_HANDLE_VALUE; @@ -375,8 +375,8 @@ bool basic_mmap::is_mapped() const noexcept #endif } -template -void basic_mmap::swap(basic_mmap& other) +template +void basic_mmap::swap(basic_mmap& other) { if(this != &other) { @@ -392,49 +392,43 @@ void basic_mmap::swap(basic_mmap& other) } } -template -bool operator==(const basic_mmap& a, - const basic_mmap& b) +template +bool operator==(const basic_mmap& a, const basic_mmap& b) { - return a.size() == b.size() - && CharTraits::compare(a.data(), b.data(), a.size()) == 0; + return a.data() == b.data() + && a.size() == b.size(); } -template -bool operator!=(const basic_mmap& a, - const basic_mmap& b) +template +bool operator!=(const basic_mmap& a, const basic_mmap& b) { return !(a == b); } -template -bool operator<(const basic_mmap& a, - const basic_mmap& b) +template +bool operator<(const basic_mmap& a, const basic_mmap& b) { - return CharTraits::compare(a.data(), b.data(), a.size()) < 0; + if(a.data() == b.data()) { return a.size() < b.size(); } + return a.data() < b.data(); } -// TODO optimize -template -bool operator<=(const basic_mmap& a, - const basic_mmap& b) +template +bool operator<=(const basic_mmap& a, const basic_mmap& b) { - return (a == b) || (a < b); + return !(a > b); } -template -bool operator>(const basic_mmap& a, - const basic_mmap& b) +template +bool operator>(const basic_mmap& a, const basic_mmap& b) { - return CharTraits::compare(a.data(), b.data(), a.size()) > 0; + if(a.data() == b.data()) { return a.size() > b.size(); } + return a.data() > b.data(); } -// TODO optimize -template -bool operator>=(const basic_mmap& a, - const basic_mmap& b) +template +bool operator>=(const basic_mmap& a, const basic_mmap& b) { - return (a == b) || (a > b); + return !(a < b); } } // namespace detail diff --git a/include/mio/mmap.hpp b/include/mio/mmap.hpp index 1bd6860..a34c1ef 100644 --- a/include/mio/mmap.hpp +++ b/include/mio/mmap.hpp @@ -34,20 +34,20 @@ using detail::access_mode; // This value may be provided as the `length` parameter to the constructor or // `map`, in which case a memory mapping of the entire file is created. -using detail::use_full_file_size; +using detail::map_entire_file; template< access_mode AccessMode, - typename CharT, - typename CharTraits = std::char_traits + typename CharT > class basic_mmap { static_assert(AccessMode == access_mode::read_only || AccessMode == access_mode::read_write, "AccessMode must be either read_only or read_write"); - using impl_type = detail::basic_mmap; + using impl_type = detail::basic_mmap; impl_type impl_; + public: using value_type = typename impl_type::value_type; @@ -211,8 +211,10 @@ public: * from the start of the file. * * `length` must be the number of bytes to map, regardless of the underlying - * value_type's size! If it is `use_full_file_size`, a mapping of the entire file - * is created. + * value_type's size. That is, if CharT is a wide char, the value returned by + * the `size` and `length` methods is not the same as this `length` value (TODO + * this can be confusing). + * If it is `map_entire_file`, a mapping of the entire file is created. */ template void map(const String& path, const size_type offset, @@ -237,8 +239,10 @@ public: * from the start of the file. * * `length` must be the number of bytes to map, regardless of the underlying - * value_type's size! If it is `use_full_file_size`, a mapping of the entire file - * is created. + * value_type's size. That is, if CharT is a wide char, the value returned by + * the `size` and `length` methods is not the same as this `length` value (TODO + * this can be confusing). + * If it is `map_entire_file`, a mapping of the entire file is created. */ void map(const handle_type handle, const size_type offset, const size_type length, std::error_code& error) @@ -259,14 +263,16 @@ public: void swap(basic_mmap& other) { impl_.swap(other.impl_); } - /** Flushes the memory mapped page to disk. */ - // TODO better name? + /** Flushes the memory mapped page to disk. Errors are reported via `error`. */ template< access_mode A = AccessMode, typename = typename std::enable_if::type > void sync(std::error_code& error) { impl_.sync(error); } - /** All operators compare two mapped areas according to CharTraits::compare. */ + /** + * All operators compare the address of the first byte and size of the two mapped + * regions. + */ friend bool operator==(const basic_mmap& a, const basic_mmap& b) { @@ -303,21 +309,20 @@ public: * This is the basis for all read-only mmap objects and should be preferred over * directly using basic_mmap. */ -template< - typename CharT, - typename CharTraits = std::char_traits -> using basic_mmap_source = basic_mmap; +template +using basic_mmap_source = basic_mmap; /** * This is the basis for all read-write mmap objects and should be preferred over * directly using basic_mmap. */ -template< - typename CharT, - typename CharTraits = std::char_traits -> using basic_mmap_sink = basic_mmap; +template +using basic_mmap_sink = basic_mmap; -/** These aliases should cover the most common use cases. */ +/** + * These aliases cover the most common use cases, both representing a raw byte stream + * (either with a char or an unsigned char/uint8_t). + */ using mmap_source = basic_mmap_source; using ummap_source = basic_mmap_source; diff --git a/test/test.cpp b/test/test.cpp index 56e2791..747008f 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -6,6 +6,13 @@ #include #include +int handle_error(const std::error_code& error) +{ + const auto& errmsg = error.message(); + std::printf("error mapping file: %s, exiting...\n", errmsg.c_str()); + return error.value(); +} + int main() { const char* path = "test-file"; @@ -19,13 +26,8 @@ int main() // Map the region of the file to which buffer was written. std::error_code error; mio::mmap_source file_view = mio::make_mmap_source( - path, 0, mio::use_full_file_size, error); - if(error) - { - const auto& errmsg = error.message(); - std::printf("error mapping file: %s, exiting...\n", errmsg.c_str()); - return error.value(); - } + path, 0, mio::map_entire_file, error); + if(error) { return handle_error(error); } assert(file_view.is_open()); assert(file_view.size() == buffer.size()); @@ -71,5 +73,14 @@ int main() // Just making sure custom types compile. mio::ummap_source ummap; + const auto page_size = mio::page_size(); + + // Now check if an mmap with a wider char type reports the correct size. + using u16mmap_source = mio::basic_mmap_source; + u16mmap_source wide_mmap = mio::make_mmap(path, 0, page_size, error); + if(error) { return handle_error(error); } + + assert(wide_mmap.size() == page_size / 2); + std::printf("all tests passed!\n"); }