article thumbnail image
Published 2020. 11. 15. 03:34
#include "Precompiled.h"

namespace DevMil
{
    template <typename Traits>
    class unique_handle
    {
        typedef typename Traits::pointer pointer;

        pointer m_value;

        auto close() throw() -> void
        {
            if (*this)
            {
                Traits::close(m_value);
            }
        }

        unique_handle(unique_handle const &);
        auto operator=(unique_handle const &) -> unique_handle &;

    public:

        explicit unique_handle(pointer value = Traits::invalid()) throw() :
            m_value { value }
        {
        }

        unique_handle(unique_handle && other) throw() :
            m_value { other.release() }
        {
        }

        auto operator=(unique_handle && other) throw() -> unique_handle &
        {
            if (this != &other)
            {
                reset(other.release());
            }

            return *this;
        }

        ~unique_handle() throw()
        {
            close();
        }

        explicit operator bool() const throw()
        {
            return m_value != Traits::invalid();
        }

        auto get() const throw() -> pointer
        {
            return m_value;
        }

        auto release() throw() -> pointer
        {
            auto value = m_value;
            m_value = Traits::invalid();
            return value;
        }

        auto reset(pointer value = Traits::invalid()) throw() -> bool
        {
            if (m_value != value)
            {
                close();
                m_value = value;
            }

            return static_cast<bool>(*this);
        }
    };

    struct null_handle_traits
    {
        typedef HANDLE pointer;

        static auto invalid() throw() -> pointer
        {
            return nullptr;
        }

        static auto close(pointer value) throw() -> void
        {
            VERIFY(CloseHandle(value));
        }
    };

    struct invalid_handle_traits
    {
        typedef HANDLE pointer;

        static auto invalid() throw() -> pointer
        {
            return INVALID_HANDLE_VALUE;
        }

        static auto close(pointer value) throw() -> void
        {
            VERIFY(CloseHandle(value));
        }
    };

    typedef unique_handle<null_handle_traits> null_handle;
    typedef unique_handle<invalid_handle_traits> invalid_handle;
}

using namespace std;
using namespace DevMil;

struct map_view_deleter
{
    typedef char const * pointer;

    auto operator()(pointer value) const throw() -> void
    {
        VERIFY(UnmapViewOfFile(value));
    }
};

auto main() -> int
{
    auto filename = LR"(C:\Sample\Sample.cpp)";

    auto file = invalid_handle
    {
        CreateFile(filename,
                   GENERIC_READ,
                   FILE_SHARE_READ,
                   nullptr,
                   OPEN_EXISTING,
                   FILE_ATTRIBUTE_NORMAL,
                   nullptr)
    };

    if (!file)
    {
        printf("CreateFile failed %d\n", GetLastError());
        return 0;
    }

    auto size = LARGE_INTEGER {};

    if (!GetFileSizeEx(file.get(), &size))
    {
        printf("GetFileSizeEx failed %d\n", GetLastError());
        return 0;
    }

    if (size.QuadPart == 0)
    {
        printf("File is empty\n");
        return 0;
    }

    auto map = null_handle
    {
        CreateFileMapping(file.get(),
                          nullptr,
                          PAGE_READONLY,
                          0,0,
                          nullptr)
    };

    if (!map)
    {
        printf("CreateFileMapping failed %d\n", GetLastError());
        return 0;
    }

    file.reset();

    auto view = unique_ptr<char, map_view_deleter>
    {
        static_cast<char *>(MapViewOfFile(map.get(),
                                          FILE_MAP_READ,
                                          0,0,
                                          0))
    };

    if (!view)
    {
        printf("MapViewOfFile failed %d\n", GetLastError());
        return 0;
    }

    printf("%.*s\n", static_cast<unsigned>(size.QuadPart), view.get());
}
복사했습니다!