~satchmo/libvmm

ref: fca0f83e2ab85960552b584818dd45ab72778133 libvmm/vmm/memory/detail/address.hpp -rw-r--r-- 6.2 KiB
fca0f83eJason Phan memory: Add FileOffset back 8 months ago
                                                                                
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//
// address.hpp -
//

#pragma once

namespace vmm::memory::detail {

#include <optional>
#include <limits>

// An address within some address space.
//
// NOTE: The operators (+, -, &, |, etc.) are not supported, meaning clients
//       must explicitly invoke the corresponding methods. However, there are
//       exceptions: `Address` (BitAnd|BitOr) `AddressValue` are supported.
template<typename Concrete, typename Size>
class Address
{
    public:
        Address() = default;
        virtual ~Address() = default;

        Address(const Address&) = default;
        Address& operator=(const Address&) = default;
        Address(Address&&) = default;
        Address& operator=(Address&&) = default;

        // Returns the raw value of the address.
        virtual auto data() const noexcept -> Size = 0;

        // Returns the bitwise AND of the address and a mask.
        virtual auto operator&(const Size) const noexcept -> Size = 0;

        // Returns the bitwise OR of the address and a mask.
        virtual auto operator|(const Size) const noexcept -> Size = 0;

        // Adds a value to the address (sum is wrapped).
        virtual auto operator+(const Size) const noexcept -> Concrete = 0;

        // Adds two addresses together (sum is wrapped).
        virtual auto operator+(const Concrete&) const noexcept -> Concrete = 0;

        // Adds a value to the address (nullopt if wrapped).
        virtual auto add(const Size value) const -> std::optional<Concrete>
        {
            if (std::numeric_limits<Size>::max() - value < data())
                return std::nullopt;

            return *this + value;
        }

        // Adds two addresses together (nullopt if wrapped).
        virtual auto add(const Concrete& address) const -> std::optional<Concrete>
        {
            return add(address.data());
        }

        // Subtracts a value from the address (difference is wrapped).
        virtual auto operator-(const Size) const noexcept -> Concrete = 0;

        // Subtracts two addresses from each other (difference is wrapped).
        virtual auto operator-(const Concrete&) const noexcept -> Concrete = 0;

        // Subtracts a value from the address (nullopt if wrapped).
        virtual auto subtract(const Size value) const -> std::optional<Concrete>
        {
            if (data() < value)
                return std::nullopt;

            return *this - value;
        }

        // Subtracts two addresses from each other (nullopt if wrapped).
        virtual auto subtract(const Concrete& address) const -> std::optional<Concrete>
        {
            return subtract(address.data());
        }

        // Aligns the address to a power of 2.
        virtual auto align(const Size) noexcept -> Concrete& = 0;
};

//template<typename Derived>
//class EnableDownCast
//{
    //using Base = EnableDownCast;

    //protected:
        //// Disable deletion of Derived* through Base*.
        //// Enable deletion of Base* through Derived*.
        //~EnableDownCast() = default;
    //public:
        //[[nodiscard]] constexpr auto self() const noexcept -> const Derived*
        //{
            //return static_cast<const Derived*>(this);
        //}

        //constexpr auto self() noexcept -> Derived*
        //{
            //return static_cast<Derived*>(this);
        //}
//};

//template<typename Concrete, typename Size>
//class Address : EnableDownCast<Concrete>
//{
    //using EnableDownCast<Concrete>::self;

    //public:
        ////Address() = default;
        ////~Address() = default;

        ////Address(const Address&) = default;
        ////Address& operator=(const Address&) = default;
        ////Address(Address&&) = default;
        ////Address& operator=(Address&&) = default;

        //// Returns the raw value of the address.
        //auto data() const noexcept -> Size
        //{
            //return self()->data();
        //}

        //// Returns a bitwise AND of the address and a mask.
        //auto mask() const noexcept -> Size
        //{
            //return self()->mask();
        //}

        //// Adds `other` to the address' value.
        //auto operator+(const Size offset) const noexcept -> Concrete
        //{
            //return self()->operator+(offset);
        //}

        //// Subtracts `other` from the address' value.
        //auto operator-(const Size value) const noexcept -> Concrete
        //{
            //return self()->operator-(value);
        //}

        //auto operator-(const Concrete& addr) const noexcept -> Concrete
        //{
            //return self()->operator-(addr);
        //}

        //// Adds `other` to the address' value.
        ////
        //// Returns a pair consisting of the sum and a boolean indicating
        //// whether an overflow would have occurred. If an overflow would have
        //// occurred, the wrapped address is returned.
        //auto add(const Size offset) const -> Concrete
        //{
            //return self()->add(offset);
        //}

        //auto add(const Concrete& addr) const -> Concrete
        //{
            //return self()->add(addr);
        //}

            //// Subtracts `other` from the address' value.
            ////
            //// Returns a pair containing the difference and a boolean indicating
            //// whether an arithmetic underflow would have occurred. If an overflow
            //// would have occurred, then the wrapped address is returned.
        //auto subtract(const Size value) const -> Concrete
        //{
            //return self()->subtract(value);
        //}

        //auto subtract(const Concrete& addr) const -> Concrete
        //{
            //return self()->subtract(addr);
        //}

        //// Returns the offset from `m_addr` to `base`.
        ////virtual auto offset_from(const Concrete&) const noexcept -> Concrete;
        ////virtual auto checked_offset_from(const Concrete&) const -> Concrete;

        //// Aligns the address to a power of 2.
        //auto align_up(const Size alignment) noexcept -> void
        //{
            //return self()->align_up(alignment);
        //}

        ////auto checked_align_up(const Size alignment) -> void
        ////{
            ////return self()->checked_align_up(alignment);
        ////}
//};

}  // vmm::memory::detail