1 | // [Blend2D] |
2 | // 2D Vector Graphics Powered by a JIT Compiler. |
3 | // |
4 | // [License] |
5 | // Zlib - See LICENSE.md file in the package. |
6 | |
7 | #ifndef BLEND2D_BLFILESYSTEM_H |
8 | #define BLEND2D_BLFILESYSTEM_H |
9 | |
10 | #include "./blarray.h" |
11 | |
12 | //! \addtogroup blend2d_api_filesystem |
13 | //! \{ |
14 | |
15 | // ============================================================================ |
16 | // [Constants] |
17 | // ============================================================================ |
18 | |
19 | //! File open flags, see `BLFile::open()`. |
20 | BL_DEFINE_ENUM(BLFileOpenFlags) { |
21 | //! Opens the file for reading. |
22 | //! |
23 | //! The following system flags are used when opening the file: |
24 | //! * `O_RDONLY` (Posix) |
25 | //! * `GENERIC_READ` (Windows) |
26 | BL_FILE_OPEN_READ = 0x00000001u, |
27 | |
28 | //! Opens the file for writing: |
29 | //! |
30 | //! The following system flags are used when opening the file: |
31 | //! * `O_WRONLY` (Posix) |
32 | //! * `GENERIC_WRITE` (Windows) |
33 | BL_FILE_OPEN_WRITE = 0x00000002u, |
34 | |
35 | //! Opens the file for reading & writing. |
36 | //! |
37 | //! The following system flags are used when opening the file: |
38 | //! * `O_RDWR` (Posix) |
39 | //! * `GENERIC_READ | GENERIC_WRITE` (Windows) |
40 | BL_FILE_OPEN_RW = 0x00000003u, |
41 | |
42 | //! Creates the file if it doesn't exist or opens it if it does. |
43 | //! |
44 | //! The following system flags are used when opening the file: |
45 | //! * `O_CREAT` (Posix) |
46 | //! * `CREATE_ALWAYS` or `OPEN_ALWAYS` depending on other flags (Windows) |
47 | BL_FILE_OPEN_CREATE = 0x00000004u, |
48 | |
49 | //! Opens the file for deleting or renaming (Windows). |
50 | //! |
51 | //! Adds `DELETE` flag when opening the file to `ACCESS_MASK`. |
52 | BL_FILE_OPEN_DELETE = 0x00000008u, |
53 | |
54 | //! Truncates the file. |
55 | //! |
56 | //! The following system flags are used when opening the file: |
57 | //! * `O_TRUNC` (Posix) |
58 | //! * `TRUNCATE_EXISTING` (Windows) |
59 | BL_FILE_OPEN_TRUNCATE = 0x00000010u, |
60 | |
61 | //! Opens the file for reading in exclusive mode (Windows). |
62 | //! |
63 | //! Exclusive mode means to not specify the `FILE_SHARE_READ` option. |
64 | BL_FILE_OPEN_READ_EXCLUSIVE = 0x10000000u, |
65 | |
66 | //! Opens the file for writing in exclusive mode (Windows). |
67 | //! |
68 | //! Exclusive mode means to not specify the `FILE_SHARE_WRITE` option. |
69 | BL_FILE_OPEN_WRITE_EXCLUSIVE = 0x20000000u, |
70 | |
71 | //! Opens the file for both reading and writing (Windows). |
72 | //! |
73 | //! This is a combination of both `BL_FILE_OPEN_READ_EXCLUSIVE` and |
74 | //! `BL_FILE_OPEN_WRITE_EXCLUSIVE`. |
75 | BL_FILE_OPEN_RW_EXCLUSIVE = 0x30000000u, |
76 | |
77 | //! Creates the file in exclusive mode - fails if the file already exists. |
78 | //! |
79 | //! The following system flags are used when opening the file: |
80 | //! * `O_EXCL` (Posix) |
81 | //! * `CREATE_NEW` (Windows) |
82 | BL_FILE_OPEN_CREATE_EXCLUSIVE = 0x40000000u, |
83 | |
84 | //! Opens the file for deleting or renaming in exclusive mode (Windows). |
85 | //! |
86 | //! Exclusive mode means to not specify the `FILE_SHARE_DELETE` option. |
87 | BL_FILE_OPEN_DELETE_EXCLUSIVE = 0x80000000u |
88 | }; |
89 | |
90 | //! File seek mode, see `BLFile::seek()`. |
91 | //! |
92 | //! \note Seek constants should be compatible with constants used by both POSIX |
93 | //! and Windows API. |
94 | BL_DEFINE_ENUM(BLFileSeek) { |
95 | //! Seek from the beginning of the file (SEEK_SET). |
96 | BL_FILE_SEEK_SET = 0, |
97 | //! Seek from the current position (SEEK_CUR). |
98 | BL_FILE_SEEK_CUR = 1, |
99 | //! Seek from the end of the file (SEEK_END). |
100 | BL_FILE_SEEK_END = 2, |
101 | |
102 | //! Count of seek modes. |
103 | BL_FILE_SEEK_COUNT = 3 |
104 | }; |
105 | |
106 | //! File read flags used by `BLFileSystem::readFile()`. |
107 | BL_DEFINE_ENUM(BLFileReadFlags) { |
108 | //! Use memory mapping to read the content of the file. |
109 | //! |
110 | //! The destination buffer `BLArray<>` would be configured to use the memory |
111 | //! mapped buffer instead of allocating its own. |
112 | BL_FILE_READ_MMAP_ENABLED = 0x00000001u, |
113 | |
114 | //! Avoid memory mapping of small files. |
115 | //! |
116 | //! The size of small file is determined by Blend2D, however, you should |
117 | //! expect it to be 16kB or 64kB depending on host operating system. |
118 | BL_FILE_READ_MMAP_AVOID_SMALL = 0x00000002u, |
119 | |
120 | //! Do not fallback to regular read if memory mapping fails. It's worth noting |
121 | //! that memory mapping would fail for files stored on filesystem that is not |
122 | //! local (like a mounted network filesystem, etc...). |
123 | BL_FILE_READ_MMAP_NO_FALLBACK = 0x00000008u |
124 | }; |
125 | |
126 | // ============================================================================ |
127 | // [BLFile - Core] |
128 | // ============================================================================ |
129 | |
130 | //! A thin abstraction over a native OS file IO [C Interface - Core]. |
131 | struct BLFileCore { |
132 | //! A file handle - either a file descriptor used by POSIX or file handle used |
133 | //! by Windows. On both platforms the handle is always `intptr_t` to make FFI |
134 | //! easier (it's basically the size of a pointer / machine register). |
135 | //! |
136 | //! \note In C++ mode you can use `BLFileCore::Handle` or `BLFile::Handle` to |
137 | //! get the handle type. In C mode you must use `intptr_t`. A handle of value |
138 | //! `-1` is considered invalid and/or uninitialized. This value also matches |
139 | //! `INVALID_HANDLE_VALUE`, which is used by Windows API and defined to -1 as |
140 | //! well. |
141 | intptr_t handle; |
142 | }; |
143 | |
144 | // ============================================================================ |
145 | // [BLFile - C++] |
146 | // ============================================================================ |
147 | |
148 | #ifdef __cplusplus |
149 | //! A thin abstraction over a native OS file IO [C++ API]. |
150 | //! |
151 | //! A thin wrapper around a native OS file support. The file handle is always |
152 | //! `intptr_t` and it refers to either a file descriptor on POSIX targets and |
153 | //! file handle on Windows targets. |
154 | class BLFile : public BLFileCore { |
155 | public: |
156 | // Prevent copy-constructor and copy-assignment. |
157 | BL_INLINE BLFile(const BLFile& other) noexcept = delete; |
158 | BL_INLINE BLFile& operator=(const BLFile& other) noexcept = delete; |
159 | |
160 | //! \name Construction & Destruction |
161 | //! \{ |
162 | |
163 | BL_INLINE BLFile() noexcept |
164 | : BLFileCore { -1 } {} |
165 | |
166 | BL_INLINE BLFile(BLFile&& other) noexcept { |
167 | intptr_t h = other.handle; |
168 | other.handle = -1; |
169 | handle = h; |
170 | } |
171 | |
172 | BL_INLINE explicit BLFile(intptr_t handle) noexcept |
173 | : BLFileCore { handle } {} |
174 | |
175 | BL_INLINE BLFile& operator=(BLFile&& other) noexcept { |
176 | intptr_t h = other.handle; |
177 | other.handle = -1; |
178 | |
179 | this->close(); |
180 | this->handle = h; |
181 | |
182 | return *this; |
183 | } |
184 | |
185 | BL_INLINE ~BLFile() noexcept { blFileReset(this); } |
186 | |
187 | //! \} |
188 | |
189 | //! \name Common Functionality |
190 | //! \{ |
191 | |
192 | BL_INLINE void swap(BLFile& other) noexcept { std::swap(this->handle, other.handle); } |
193 | |
194 | //! \} |
195 | |
196 | //! \name File API |
197 | //! \{ |
198 | |
199 | //! Tests whether the file is open. |
200 | BL_INLINE bool isOpen() const noexcept { return handle != -1; } |
201 | |
202 | //! Returns the file handle and sets to invalid. After this operation you |
203 | //! will be the sole owner of the handle and you will be responsible for |
204 | //! closing it. |
205 | BL_INLINE intptr_t takeHandle() noexcept { |
206 | intptr_t h = this->handle; |
207 | this->handle = -1; |
208 | return h; |
209 | } |
210 | |
211 | BL_INLINE BLResult open(const char* fileName, uint32_t openFlags) noexcept { |
212 | return blFileOpen(this, fileName, openFlags); |
213 | } |
214 | |
215 | BL_INLINE BLResult close() noexcept { |
216 | return blFileClose(this); |
217 | } |
218 | |
219 | BL_INLINE BLResult seek(int64_t offset, uint32_t seekType) noexcept { |
220 | int64_t positionOut; |
221 | return blFileSeek(this, offset, seekType, &positionOut); |
222 | } |
223 | |
224 | BL_INLINE BLResult seek(int64_t offset, uint32_t seekType, int64_t* positionOut) noexcept { |
225 | return blFileSeek(this, offset, seekType, positionOut); |
226 | } |
227 | |
228 | BL_INLINE BLResult read(void* buffer, size_t n, size_t* bytesReadOut) noexcept { |
229 | return blFileRead(this, buffer, n, bytesReadOut); |
230 | } |
231 | |
232 | BL_INLINE BLResult write(const void* buffer, size_t n, size_t* bytesWrittenOut) noexcept { |
233 | return blFileWrite(this, buffer, n, bytesWrittenOut); |
234 | } |
235 | |
236 | BL_INLINE BLResult truncate(int64_t maxSize) noexcept { |
237 | return blFileTruncate(this, maxSize); |
238 | } |
239 | |
240 | BL_INLINE BLResult getSize(uint64_t* sizeOut) noexcept { |
241 | return blFileGetSize(this, sizeOut); |
242 | } |
243 | |
244 | //! \} |
245 | }; |
246 | #endif |
247 | |
248 | // ============================================================================ |
249 | // [BLFileSystem] |
250 | // ============================================================================ |
251 | |
252 | #ifdef __cplusplus |
253 | //! File-system utilities. |
254 | namespace BLFileSystem { |
255 | |
256 | //! Reads a file into the `dst` buffer. |
257 | //! |
258 | //! Optionally you can set `maxSize` to non-zero value that would restrict the |
259 | //! maximum bytes to read to such value. In addition, `readFlags` can be used to |
260 | //! enable file mapping. See `BLFileReadFlags` for more details. |
261 | static BL_INLINE BLResult readFile(const char* fileName, BLArray<uint8_t>& dst, size_t maxSize = 0, uint32_t readFlags = 0) noexcept { |
262 | return blFileSystemReadFile(fileName, &dst, maxSize, readFlags); |
263 | } |
264 | |
265 | static BL_INLINE BLResult writeFile(const char* fileName, const void* data, size_t size) noexcept { |
266 | size_t bytesWrittenOut; |
267 | return blFileSystemWriteFile(fileName, data, size, &bytesWrittenOut); |
268 | } |
269 | |
270 | static BL_INLINE BLResult writeFile(const char* fileName, const void* data, size_t size, size_t* bytesWrittenOut) noexcept { |
271 | return blFileSystemWriteFile(fileName, data, size, bytesWrittenOut); |
272 | } |
273 | |
274 | static BL_INLINE BLResult writeFile(const char* fileName, const BLArrayView<uint8_t>& view) noexcept { |
275 | return writeFile(fileName, view.data, view.size); |
276 | } |
277 | |
278 | static BL_INLINE BLResult writeFile(const char* fileName, const BLArrayView<uint8_t>& view, size_t* bytesWrittenOut) noexcept { |
279 | return writeFile(fileName, view.data, view.size, bytesWrittenOut); |
280 | } |
281 | |
282 | static BL_INLINE BLResult writeFile(const char* fileName, const BLArray<uint8_t>& array) noexcept { |
283 | return writeFile(fileName, array.view()); |
284 | } |
285 | |
286 | static BL_INLINE BLResult writeFile(const char* fileName, const BLArray<uint8_t>& array, size_t* bytesWrittenOut) noexcept { |
287 | return writeFile(fileName, array.view(), bytesWrittenOut); |
288 | } |
289 | |
290 | } // {BLFileSystem} |
291 | #endif |
292 | |
293 | //! \} |
294 | |
295 | #endif // BLEND2D_BLFILESYSTEM_H |
296 | |