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()`.
20BL_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.
94BL_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()`.
107BL_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].
131struct 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.
154class BLFile : public BLFileCore {
155public:
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.
254namespace 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.
261static 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
265static 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
270static 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
274static BL_INLINE BLResult writeFile(const char* fileName, const BLArrayView<uint8_t>& view) noexcept {
275 return writeFile(fileName, view.data, view.size);
276}
277
278static 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
282static BL_INLINE BLResult writeFile(const char* fileName, const BLArray<uint8_t>& array) noexcept {
283 return writeFile(fileName, array.view());
284}
285
286static 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