removed CharTraits

This commit is contained in:
mandreyel 2017-10-06 00:03:15 +02:00
parent 54694df5f7
commit c52e35b2e8
5 changed files with 119 additions and 115 deletions

View File

@ -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<wchar_t>;
using i32mmap_source = mio::basic_mmap_source<int32_t>;
}
```

View File

@ -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<CharT>
> struct basic_mmap
template<typename CharT> 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<typename CharT, typename CharTraits>
bool operator==(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b);
template<typename CharT>
bool operator==(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b);
template<typename CharT, typename CharTraits>
bool operator!=(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b);
template<typename CharT>
bool operator!=(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b);
template<typename CharT, typename CharTraits>
bool operator<(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b);
template<typename CharT>
bool operator<(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b);
template<typename CharT, typename CharTraits>
bool operator<=(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b);
template<typename CharT>
bool operator<=(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b);
template<typename CharT, typename CharTraits>
bool operator>(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b);
template<typename CharT>
bool operator>(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b);
template<typename CharT, typename CharTraits>
bool operator>=(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b);
template<typename CharT>
bool operator>=(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b);
} // namespace detail
} // namespace mio

View File

@ -41,7 +41,7 @@ namespace detail {
// Generic handle type for use by free functions.
using handle_type = basic_mmap<char>::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<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>::~basic_mmap()
template<typename CharT>
basic_mmap<CharT>::~basic_mmap()
{
unmap();
}
template<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>::basic_mmap(basic_mmap<CharT, CharTraits>&& other)
template<typename CharT>
basic_mmap<CharT>::basic_mmap(basic_mmap<CharT>&& other)
: data_(std::move(other.data_))
, length_(std::move(other.length_))
, mapped_length_(std::move(other.mapped_length_))
@ -141,8 +141,8 @@ basic_mmap<CharT, CharTraits>::basic_mmap(basic_mmap<CharT, CharTraits>&& other)
#endif
}
template<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>& basic_mmap<CharT, CharTraits>::operator=(basic_mmap<CharT, CharTraits>&& other)
template<typename CharT>
basic_mmap<CharT>& basic_mmap<CharT>::operator=(basic_mmap<CharT>&& other)
{
if(this != &other)
{
@ -170,9 +170,9 @@ basic_mmap<CharT, CharTraits>& basic_mmap<CharT, CharTraits>::operator=(basic_mm
return *this;
}
template<typename CharT, typename CharTraits>
typename basic_mmap<CharT, CharTraits>::handle_type
basic_mmap<CharT, CharTraits>::mapping_handle() const noexcept
template<typename CharT>
typename basic_mmap<CharT>::handle_type
basic_mmap<CharT>::mapping_handle() const noexcept
{
#ifdef _WIN32
return file_mapping_handle_;
@ -181,9 +181,9 @@ basic_mmap<CharT, CharTraits>::mapping_handle() const noexcept
#endif
}
template<typename CharT, typename CharTraits>
template<typename CharT>
template<typename String>
void basic_mmap<CharT, CharTraits>::map(String& path, size_type offset,
void basic_mmap<CharT>::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<CharT, CharTraits>::map(String& path, size_type offset,
}
}
template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::map(handle_type handle, size_type offset,
template<typename CharT>
void basic_mmap<CharT>::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<CharT, CharTraits>::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<CharT, CharTraits>::map(handle_type handle, size_type offset,
map(offset, length, mode, error);
}
template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::map(const size_type offset, const size_type length,
template<typename CharT>
void basic_mmap<CharT>::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<CharT, CharTraits>::map(const size_type offset, const size_type
mapped_length_ = length_to_map;
}
template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::sync(std::error_code& error)
template<typename CharT>
void basic_mmap<CharT>::sync(std::error_code& error)
{
error.clear();
if(!is_open())
@ -313,8 +313,8 @@ void basic_mmap<CharT, CharTraits>::sync(std::error_code& error)
#endif
}
template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::unmap()
template<typename CharT>
void basic_mmap<CharT>::unmap()
{
if(!is_open()) { return; }
// TODO do we care about errors here?
@ -350,23 +350,23 @@ void basic_mmap<CharT, CharTraits>::unmap()
#endif
}
template<typename CharT, typename CharTraits>
typename basic_mmap<CharT, CharTraits>::pointer
basic_mmap<CharT, CharTraits>::get_mapping_start() noexcept
template<typename CharT>
typename basic_mmap<CharT>::pointer
basic_mmap<CharT>::get_mapping_start() noexcept
{
if(!data_) { return nullptr; }
const auto offset = mapped_length_ - length_;
return data_ - offset;
}
template<typename CharT, typename CharTraits>
bool basic_mmap<CharT, CharTraits>::is_open() const noexcept
template<typename CharT>
bool basic_mmap<CharT>::is_open() const noexcept
{
return file_handle_ != INVALID_HANDLE_VALUE;
}
template<typename CharT, typename CharTraits>
bool basic_mmap<CharT, CharTraits>::is_mapped() const noexcept
template<typename CharT>
bool basic_mmap<CharT>::is_mapped() const noexcept
{
#ifdef _WIN32
return file_mapping_handle_ != INVALID_HANDLE_VALUE;
@ -375,8 +375,8 @@ bool basic_mmap<CharT, CharTraits>::is_mapped() const noexcept
#endif
}
template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::swap(basic_mmap<CharT, CharTraits>& other)
template<typename CharT>
void basic_mmap<CharT>::swap(basic_mmap<CharT>& other)
{
if(this != &other)
{
@ -392,49 +392,43 @@ void basic_mmap<CharT, CharTraits>::swap(basic_mmap<CharT, CharTraits>& other)
}
}
template<typename CharT, typename CharTraits>
bool operator==(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b)
template<typename CharT>
bool operator==(const basic_mmap<CharT>& a, const basic_mmap<CharT>& 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<typename CharT, typename CharTraits>
bool operator!=(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b)
template<typename CharT>
bool operator!=(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b)
{
return !(a == b);
}
template<typename CharT, typename CharTraits>
bool operator<(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b)
template<typename CharT>
bool operator<(const basic_mmap<CharT>& a, const basic_mmap<CharT>& 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<typename CharT, typename CharTraits>
bool operator<=(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b)
template<typename CharT>
bool operator<=(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b)
{
return (a == b) || (a < b);
return !(a > b);
}
template<typename CharT, typename CharTraits>
bool operator>(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b)
template<typename CharT>
bool operator>(const basic_mmap<CharT>& a, const basic_mmap<CharT>& 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<typename CharT, typename CharTraits>
bool operator>=(const basic_mmap<CharT, CharTraits>& a,
const basic_mmap<CharT, CharTraits>& b)
template<typename CharT>
bool operator>=(const basic_mmap<CharT>& a, const basic_mmap<CharT>& b)
{
return (a == b) || (a > b);
return !(a < b);
}
} // namespace detail

View File

@ -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<CharT>
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<CharT, CharTraits>;
using impl_type = detail::basic_mmap<CharT>;
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<typename String>
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<A == access_mode::read_write>::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<CharT>
> using basic_mmap_source = basic_mmap<access_mode::read_only, CharT, CharTraits>;
template<typename CharT>
using basic_mmap_source = basic_mmap<access_mode::read_only, CharT>;
/**
* 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<CharT>
> using basic_mmap_sink = basic_mmap<access_mode::read_write, CharT, CharTraits>;
template<typename CharT>
using basic_mmap_sink = basic_mmap<access_mode::read_write, CharT>;
/** 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<char>;
using ummap_source = basic_mmap_source<unsigned char>;

View File

@ -6,6 +6,13 @@
#include <cassert>
#include <system_error>
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<char16_t>;
u16mmap_source wide_mmap = mio::make_mmap<u16mmap_source>(path, 0, page_size, error);
if(error) { return handle_error(error); }
assert(wide_mmap.size() == page_size / 2);
std::printf("all tests passed!\n");
}