• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // memory_buffer.hpp
3 //
4 // Copyright © 2024 Apple Inc. All rights reserved.
5 //
6 // Please refer to the license found in the LICENSE file in the root directory of the source tree.
7 
8 #pragma once
9 
10 #include <memory>
11 #include <stdio.h>
12 #include <string>
13 #include <system_error>
14 #include <vector>
15 
16 #include "range.hpp"
17 
18 namespace inmemoryfs {
19 /// A class representing a memory buffer.
20 class MemoryBuffer: public std::enable_shared_from_this<MemoryBuffer> {
21 public:
22     /// The kind of buffer.
23     enum class Kind: uint8_t {
24         MMap = 0,  // If the buffer is memory mapped.
25         Malloc ,   // If the buffer is heap allocated.
26     };
27 
28     enum class ReadOption: uint8_t {
29         Malloc = 0,
30         MMap,
31         LazyMMap
32     };
33 
MemoryBuffer(void * data,size_t size,Kind kind=Kind::Malloc,std::shared_ptr<MemoryBuffer> parent=nullptr)34     inline MemoryBuffer(void *data,
35                         size_t size,
36                         Kind kind = Kind::Malloc,
37                         std::shared_ptr<MemoryBuffer> parent = nullptr) noexcept:
38     data_(data),
39     size_(size),
40     kind_(kind),
41     parent_(parent)
42     {}
43 
44     MemoryBuffer(const MemoryBuffer &) = delete;
45     MemoryBuffer &operator=(const MemoryBuffer &) = delete;
46 
~MemoryBuffer()47     virtual ~MemoryBuffer() noexcept {}
48 
49     /// Returns the underlying data.
data()50     virtual inline void *data() noexcept {
51         return data_;
52     }
53 
54     /// Returns the size of the buffer.
size() const55     inline const size_t size() const noexcept {
56         return size_;
57     }
58 
59     /// Loads the contents of the buffer.
60     ///
61     /// - For a malloced buffer, the method is a no op, content is loaded at the initialization time.
62     /// - For a memory mapped buffer, the method can result in memory mapping the contents of the backed file.
63     ///
64     /// @param error  On failure, error is populated with the failure reason.
65     /// @retval `true` if the copy succeeded otherwise `false`.
load(std::error_code & error)66     inline virtual bool load(std::error_code& error) noexcept {
67         return true;
68     }
69 
70     /// Returns the kind of the buffer.
kind() const71     inline const Kind kind() const noexcept {
72         return kind_;
73     }
74 
75     /// Returns the offset range that would be used when writing the buffer content.
76     ///
77     /// @param proposed_offset The proposed offset.
78     /// @retval The  offset range that would be used when writing the buffer content.
get_offset_range(size_t proposed_offset) const79     inline virtual std::pair<size_t, size_t> get_offset_range(size_t proposed_offset) const noexcept {
80         return {proposed_offset, proposed_offset};
81     }
82 
83     /// Returns the revised range that must be used for writing.
84     ///
85     /// @param dst  The destination pointer.
86     /// @param proposed_range The proposed offset and size for writing the buffer content.
87     /// @retval The revised offset and size that must be used to write the buffer content.
get_revised_range_for_writing(void * dst,Range proposed_range) const88     inline virtual Range get_revised_range_for_writing(void *dst, Range proposed_range) const noexcept {
89         return proposed_range;
90     }
91 
92     /// Writes the contents of the buffer to the destination buffer at the given offset.
93     ///
94     /// @param dst The destination pointer.
95     /// @param offset The offset.
96     /// @param error  On failure, error is populated with the failure reason.
97     /// @retval `true` if the write succeeded otherwise `false`.
98     virtual bool write(void *dst,
99                        size_t offset,
100                        std::error_code& error) noexcept;
101 
102     /// Slices a buffer.
103     ///
104     /// @param range The memory range.
105     /// @retval The sliced buffer if the region is inside the buffer otherwise `nullptr`.
106     virtual std::shared_ptr<MemoryBuffer> slice(Range range) noexcept;
107 
108     /// Reads the file content at the specified path.
109     ///
110     /// @param file_path The file path.
111     /// @param ranges The ranges to be read.
112     /// @param option The read option.
113     /// @param error  On failure, error is populated with the failure reason.
114     /// @retval The read buffers or an empty vector if the read failed.
115     static std::vector<std::shared_ptr<MemoryBuffer>>
116     read_file_content(const std::string& file_path,
117                       const std::vector<Range>& ranges,
118                       ReadOption option,
119                       std::error_code& error);
120 
121     /// Reads the whole file content at the specified path.
122     ///
123     /// @param file_path The file path.
124     /// @param option The read option.
125     /// @param error   On failure, error is populated with the failure reason.
126     /// @retval The read buffer or `nullptr` if the read failed.
127     static std::shared_ptr<MemoryBuffer>
128     read_file_content(const std::string& file_path,
129                       ReadOption option,
130                       std::error_code& error);
131 
132     /// Constructs a `MemoryBuffer`.
133     ///
134     /// @param size The size of the buffer.
135     /// @param alignment The address alignment.
136     static std::unique_ptr<MemoryBuffer>
137     make_using_malloc(size_t size, size_t alignment = 1);
138 
139 
140     /// Constructs a `MemoryBuffer` from memory allocated using `mmap`.
141     ///
142     /// @param size The size of the buffer.
143     static std::unique_ptr<MemoryBuffer>
144     make_using_mmap(size_t size);
145 
146     /// Constructs a `MemoryBuffer` without copying data.
147     ///
148     /// @param data The buffer content.
149     /// @param size The size of the buffer.
150     static std::unique_ptr<MemoryBuffer>
151     make_unowned(void *data, size_t size);
152 
153     /// Constructs a `MemoryBuffer` with copying data.
154     ///
155     /// @param data The buffer content.
156     /// @param size The size of the buffer.
157     static std::unique_ptr<MemoryBuffer>
158     make_copy(void *data, size_t size);
159 private:
160     void *data_;
161     const size_t size_;
162     Kind kind_;
163     const std::shared_ptr<MemoryBuffer> parent_;
164 };
165 }
166