File size: 2,265 Bytes
90f0b29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**************************************************************************************************
 *
 * Copyright (c) 2019-2024 Axera Semiconductor Co., Ltd. All Rights Reserved.
 *
 * This source file is the property of Axera Semiconductor Co., Ltd. and
 * may not be copied or distributed in any isomorphic form without the prior
 * written consent of Axera Semiconductor Co., Ltd.
 *
 **************************************************************************************************/

#pragma once

#if defined(ENV_HAS_POSIX_FILE_STAT)
#include "utilities/scalar_guard.hpp"
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#endif // ENV_HAS_POSIX_FILE_STAT

#if defined(ENV_HAS_WIN_API)
#include <Windows.h>
#endif // ENV_HAS_WIN_API

#include <utilities/file.hpp>

namespace utilities {

struct file_mapper {
    file_mapper() = delete;

    explicit file_mapper(const std::string& path) {
#if defined(ENV_HAS_POSIX_FILE_STAT)

        auto fd_guard = scalar_guard<int>(
            ::open(path.c_str(), O_RDONLY),
            [](const int& fd) { if (fd != -1) ::close(fd); }
        );

        if (-1 == fd_guard.get()) {
            return;
        }

        auto size = file_size(path);
        auto map_guard = scalar_guard<void*>(
            ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd_guard.get(), 0),
            [&size](void*& addr) { if (MAP_FAILED != addr && nullptr != addr) ::munmap(addr, size); }
        );

        if (MAP_FAILED == map_guard.get()) {
            return;
        }

        this->size_ = size;
        std::swap(this->fd_, fd_guard.get());
        std::swap(this->buffer_, map_guard.get());
#endif // ENV_HAS_POSIX_FILE_STAT
    }

    ~file_mapper() {
#if defined(ENV_HAS_POSIX_FILE_STAT)
        if (nullptr != this->buffer_) {
            ::munmap(this->buffer_, this->size_);
            this->buffer_ = nullptr;
        }
        if (-1 != this->fd_) {
            ::close(this->fd_);
            this->fd_ = -1;
        }
#endif // ENV_HAS_POSIX_FILE_STAT
    }

    [[nodiscard]] void* get() const {
        return this->buffer_;
    }

    [[nodiscard]] uint64_t size() const {
        return this->size_;
    }

private:
    int fd_ = -1;
    void* buffer_ = nullptr;
    uint64_t size_ = 0;
};

}