diff --git a/Makefile.am b/Makefile.am index 140524f3..497f0e7b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -162,11 +162,15 @@ UTIL_FILES = \ if PLATFORM_LINUX -UTIL_FILES += backtrace_execinfo.cpp +UTIL_FILES += \ + backtrace_execinfo.cpp \ + io_posix.cpp endif if PLATFORM_WIN32 -UTIL_FILES += backtrace_null.cpp +UTIL_FILES += \ + backtrace_null.cpp \ + io_win32.cpp endif ############################################################################### diff --git a/io.cpp b/io.cpp index f53ce132..a025ce94 100644 --- a/io.cpp +++ b/io.cpp @@ -198,99 +198,3 @@ util::set_cwd (const boost::filesystem::path &path) { if (chdir (path.string ().c_str ()) != 0) throw errno_error (); } - -//---------------------------------------------------------------------------- -#if defined(HAVE_MMAP) -#include - - -mapped_file::mapped_file (const boost::filesystem::path &_path, access_t _access): - m_fd (_path, _access) -{ load_fd (_access); } - - -mapped_file::~mapped_file () { - CHECK (m_data != NULL); - munmap (m_data, m_size); -} - - -int -mapped_file::access_to_flags (access_t a) { - int flags = 0; - - if (a & ACCESS_READ) - flags |= PROT_READ; - - if (a & ACCESS_WRITE) - flags |= PROT_WRITE; - - return flags; -} - - -void -mapped_file::load_fd (access_t access) { - struct stat meta; - if (fstat (m_fd, &meta) < 0) - throw errno_error (); - - m_size = (size_t)meta.st_size; - m_data = (uint8_t *)mmap (NULL, m_size, access_to_flags (access), MAP_SHARED, m_fd, 0); - if (m_data == MAP_FAILED) - throw errno_error (); -} - - -size_t -mapped_file::size (void) const { - CHECK (m_size > 0); - CHECK (m_data != NULL); - - return m_size; -} - - -uint8_t* -mapped_file::data (void) { - CHECK (m_size > 0); - CHECK (m_data != NULL); - - return m_data; -} - - -const uint8_t* -mapped_file::data (void) const { - CHECK (m_size > 0); - CHECK (m_data != NULL); - - return m_data; -} - - -uint8_t* -mapped_file::begin (void) { - return data (); -} - - -uint8_t* -mapped_file::end (void) { - return data () + size (); -} - - -const uint8_t* -mapped_file::cbegin (void) const { - return data (); -} - - -const uint8_t* -mapped_file::cend (void) const { - return data () + size (); -} - -#endif - diff --git a/io.hpp b/io.hpp index ebdc208b..4e8822b4 100644 --- a/io.hpp +++ b/io.hpp @@ -22,12 +22,17 @@ #include "types.hpp" #include "memory.hpp" +#include "platform.hpp" +#include "nocopy.hpp" #include #include #include #include +#ifdef PLATFORM_WIN32 +#include +#endif namespace util { /// Specifies bitwise combinations of IO access rights. @@ -60,6 +65,22 @@ namespace util { }; +#ifdef PLATFORM_WIN32 + struct handle_ref : util::nocopy { + public: + explicit handle_ref (HANDLE); + explicit handle_ref (); + ~handle_ref (); + + void reset (HANDLE); + + operator HANDLE (void) const; + + HANDLE handle; + }; +#endif + + //------------------------------------------------------------------------- class indenter : public std::streambuf { protected: @@ -111,39 +132,8 @@ namespace util { void set_cwd (const boost::filesystem::path &); - - /// Wraps a mechanism to map a file into memory. Read only. - class mapped_file { - private: - fd_ref m_fd; - uint8_t *m_data; - size_t m_size; - - void load_fd (access_t); - - protected: - int access_to_flags (access_t); - - public: - mapped_file (const boost::filesystem::path &path, access_t access = ACCESS_READ); - - mapped_file (const mapped_file&) = delete; - mapped_file& operator= (const mapped_file&) = delete; - - ~mapped_file (); - - const uint8_t* data (void) const; - uint8_t* data (void); - size_t size (void) const; - - uint8_t* begin (void); - uint8_t* end (void); - - const uint8_t* cbegin (void) const; - const uint8_t* cend (void) const; - }; - + //------------------------------------------------------------------------- class path_error : public std::runtime_error { public: path_error (const boost::filesystem::path &path): @@ -152,6 +142,12 @@ namespace util { }; } +#ifdef PLATFORM_WIN32 +#include "io_win32.hpp" +#else +#include "io_posix.hpp" +#endif + #include "io.ipp" #endif diff --git a/io_posix.cpp b/io_posix.cpp new file mode 100644 index 00000000..b8a6e0f8 --- /dev/null +++ b/io_posix.cpp @@ -0,0 +1,120 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2010-2014 Danny Robson + */ + +#include "io.hpp" + +#include "debug.hpp" +#include "except.hpp" + +#include +#include +#include +#include + +using util::detail::posix::mapped_file; + +//---------------------------------------------------------------------------- +mapped_file::mapped_file (const boost::filesystem::path &_path, access_t _access): + m_fd (_path, _access) +{ load_fd (_access); } + + +mapped_file::~mapped_file () { + CHECK (m_data != NULL); + munmap (m_data, m_size); +} + + +int +mapped_file::access_to_flags (access_t a) { + int flags = 0; + + if (a & ACCESS_READ) + flags |= PROT_READ; + + if (a & ACCESS_WRITE) + flags |= PROT_WRITE; + + return flags; +} + + +void +mapped_file::load_fd (access_t access) { + struct stat meta; + if (fstat (m_fd, &meta) < 0) + throw errno_error (); + + m_size = (size_t)meta.st_size; + m_data = (uint8_t *)mmap (NULL, m_size, access_to_flags (access), MAP_SHARED, m_fd, 0); + if (m_data == MAP_FAILED) + throw errno_error (); +} + + +size_t +mapped_file::size (void) const { + CHECK (m_size > 0); + CHECK (m_data != NULL); + + return m_size; +} + + +uint8_t* +mapped_file::data (void) { + CHECK (m_size > 0); + CHECK (m_data != NULL); + + return m_data; +} + + +const uint8_t* +mapped_file::data (void) const { + CHECK (m_size > 0); + CHECK (m_data != NULL); + + return m_data; +} + + +uint8_t* +mapped_file::begin (void) { + return data (); +} + + +uint8_t* +mapped_file::end (void) { + return data () + size (); +} + + +const uint8_t* +mapped_file::cbegin (void) const { + return data (); +} + + +const uint8_t* +mapped_file::cend (void) const { + return data () + size (); +} + diff --git a/io_posix.hpp b/io_posix.hpp new file mode 100644 index 00000000..4ed21479 --- /dev/null +++ b/io_posix.hpp @@ -0,0 +1,62 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2010-2014 Danny Robson + */ + +#ifndef __UTIL_IO_POSIX_HPP +#define __UTIL_IO_POSIX_HPP + +#include "io.hpp" + +namespace util { + namespace detail { namespace posix { + class mapped_file { + private: + fd_ref m_fd; + uint8_t *m_data; + size_t m_size; + + void load_fd (access_t); + + protected: + int access_to_flags (access_t); + + public: + mapped_file (const boost::filesystem::path &path, access_t access = ACCESS_READ); + + mapped_file (const mapped_file&) = delete; + mapped_file& operator= (const mapped_file&) = delete; + + ~mapped_file (); + + const uint8_t* data (void) const; + uint8_t* data (void); + size_t size (void) const; + + uint8_t* begin (void); + uint8_t* end (void); + + const uint8_t* cbegin (void) const; + const uint8_t* cend (void) const; + }; + + } } + + typedef detail::posix::mapped_file mapped_file; +} + +#endif diff --git a/io_win32.cpp b/io_win32.cpp new file mode 100644 index 00000000..1919f545 --- /dev/null +++ b/io_win32.cpp @@ -0,0 +1,165 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2014 Danny Robson + */ + +#include "io_win32.hpp" + +#include "debug.hpp" +#include "except.hpp" + +#include + +using util::detail::win32::mapped_file; + + +//----------------------------------------------------------------------------- +static DWORD +access_to_flags (util::access_t a) { + switch (a) { + case util::ACCESS_READ: + return GENERIC_READ; + + case util::ACCESS_WRITE: + return GENERIC_WRITE; + + default: + unreachable (); + } +} + +//----------------------------------------------------------------------------- +mapped_file::mapped_file (const boost::filesystem::path &path, + access_t access): + m_data (nullptr, UnmapViewOfFile) +{ + std::cerr << "mapped_file\n"; + + m_file.reset (CreateFile (path.string ().c_str (), + access_to_flags (access), + access == ACCESS_READ ? FILE_SHARE_READ : 0, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, + 0)); + + if (m_file == INVALID_HANDLE_VALUE) + win32_error::throw_code (); + std::cerr << "mapped_file: file\n"; + + m_mapping.reset (CreateFileMapping (m_file, + nullptr, + access == ACCESS_READ ? PAGE_READONLY : PAGE_READWRITE, + 0, 0, + nullptr)); + + if (m_mapping == INVALID_HANDLE_VALUE) + win32_error::throw_code (); + std::cerr << "mapped_file: mapping\n"; + + auto view = MapViewOfFile (m_mapping, + access == ACCESS_READ ? FILE_MAP_READ : FILE_MAP_WRITE, + 0, 0, + 0); + if (view == nullptr) + win32_error::throw_code (); + std::cerr << "mapped_file: view\n"; + + m_data.reset ( + static_cast (view) + ); + + m_size = GetFileSize (m_file, nullptr); + std::cout << "size: " << m_size << '\n'; +} + + +//----------------------------------------------------------------------------- +const uint8_t* +mapped_file::data (void) const +{ + return m_data.get (); +} + + +uint8_t* +mapped_file::data (void) +{ + return m_data.get (); +} + + +size_t +mapped_file::size (void) const +{ + return m_size; +} + + +uint8_t* +mapped_file::begin (void) +{ + return data (); +} + +uint8_t* +mapped_file::end (void) +{ + return data () + size (); +} + + +const uint8_t* +mapped_file::cbegin (void) const +{ + return data (); +} + +const uint8_t* +mapped_file::cend (void) const +{ + return data () + size (); +} + + +//----------------------------------------------------------------------------- +util::handle_ref::handle_ref (): + handle (INVALID_HANDLE_VALUE) +{ ; } + + +util::handle_ref::~handle_ref () +{ + reset (INVALID_HANDLE_VALUE); +} + + +void +util::handle_ref::reset (HANDLE _handle) +{ + if (handle != INVALID_HANDLE_VALUE) + if (!CloseHandle (handle)) + win32_error::throw_code (); + + handle = _handle; +} + + +util::handle_ref::operator HANDLE (void) const +{ + return handle; +} diff --git a/io_win32.hpp b/io_win32.hpp new file mode 100644 index 00000000..45e971e5 --- /dev/null +++ b/io_win32.hpp @@ -0,0 +1,61 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2014 Danny Robson + */ + +#ifndef __UTIL_IO_WIN32_HPP +#define __UTIL_IO_WIN32_HPP + +#include "io.hpp" + +#include +#include +#include + +namespace util { + namespace detail { namespace win32 { + class mapped_file { + public: + mapped_file (const boost::filesystem::path &path, + access_t access = ACCESS_READ); + + mapped_file (const mapped_file&) = delete; + mapped_file& operator= (const mapped_file&) = delete; + + const uint8_t* data (void) const; + uint8_t* data (void); + size_t size (void) const; + + uint8_t* begin (void); + uint8_t* end (void); + + const uint8_t* cbegin (void) const; + const uint8_t* cend (void) const; + + private: + handle_ref m_file; + handle_ref m_mapping; + + std::unique_ptr m_data; + size_t m_size; + }; + } } + + typedef detail::win32::mapped_file mapped_file; +} + +#endif