odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

filesystem.h (18654B)


      1 // This file is part of Blend2D project <https://blend2d.com>
      2 //
      3 // See blend2d.h or LICENSE.md for license and copyright information
      4 // SPDX-License-Identifier: Zlib
      5 
      6 #ifndef BLEND2D_FILESYSTEM_H_INCLUDED
      7 #define BLEND2D_FILESYSTEM_H_INCLUDED
      8 
      9 #include "array.h"
     10 
     11 //! \addtogroup bl_filesystem
     12 //! \{
     13 
     14 //! \name BLFile API Constants
     15 //! \{
     16 
     17 //! File information flags, used by \ref BLFileInfo.
     18 BL_DEFINE_ENUM(BLFileInfoFlags) {
     19   //! File owner has read permission (compatible with 0400 octal notation).
     20   BL_FILE_INFO_OWNER_R = 0x00000100u,
     21   //! File owner has write permission (compatible with 0200 octal notation).
     22   BL_FILE_INFO_OWNER_W = 0x00000080u,
     23   //! File owner has execute permission (compatible with 0100 octal notation).
     24   BL_FILE_INFO_OWNER_X = 0x00000040u,
     25   //! A combination of \ref BL_FILE_INFO_OWNER_R, \ref BL_FILE_INFO_OWNER_W, and \ref BL_FILE_INFO_OWNER_X.
     26   BL_FILE_INFO_OWNER_MASK = 0x000001C0u,
     27 
     28   //! File group owner has read permission (compatible with 040 octal notation).
     29   BL_FILE_INFO_GROUP_R = 0x00000020u,
     30   //! File group owner has write permission (compatible with 020 octal notation).
     31   BL_FILE_INFO_GROUP_W = 0x00000010u,
     32   //! File group owner has execute permission (compatible with 010 octal notation).
     33   BL_FILE_INFO_GROUP_X = 0x00000008u,
     34   //! A combination of \ref BL_FILE_INFO_GROUP_R, \ref BL_FILE_INFO_GROUP_W, and \ref BL_FILE_INFO_GROUP_X.
     35   BL_FILE_INFO_GROUP_MASK = 0x00000038u,
     36 
     37   //! Other users have read permission (compatible with 04 octal notation).
     38   BL_FILE_INFO_OTHER_R = 0x00000004u,
     39   //! Other users have write permission (compatible with 02 octal notation).
     40   BL_FILE_INFO_OTHER_W = 0x00000002u,
     41   //! Other users have execute permission (compatible with 01 octal notation).
     42   BL_FILE_INFO_OTHER_X = 0x00000001u,
     43   //! A combination of \ref BL_FILE_INFO_OTHER_R, \ref BL_FILE_INFO_OTHER_W, and \ref BL_FILE_INFO_OTHER_X.
     44   BL_FILE_INFO_OTHER_MASK = 0x00000007u,
     45 
     46   //! Set user ID to file owner user ID on execution (compatible with 04000 octal notation).
     47   BL_FILE_INFO_SUID = 0x00000800u,
     48   //! Set group ID to file's user group ID on execution (compatible with 02000 octal notation).
     49   BL_FILE_INFO_SGID = 0x00000400u,
     50 
     51   //! A combination of all file permission bits.
     52   BL_FILE_INFO_PERMISSIONS_MASK = 0x00000FFFu,
     53 
     54   //! A flag specifying that this is a regular file.
     55   BL_FILE_INFO_REGULAR = 0x00010000u,
     56   //! A flag specifying that this is a directory.
     57   BL_FILE_INFO_DIRECTORY = 0x00020000u,
     58   //! A flag specifying that this is a symbolic link.
     59   BL_FILE_INFO_SYMLINK = 0x00040000u,
     60 
     61   //! A flag describing a character device.
     62   BL_FILE_INFO_CHAR_DEVICE = 0x00100000u,
     63   //! A flag describing a block device.
     64   BL_FILE_INFO_BLOCK_DEVICE = 0x00200000u,
     65   //! A flag describing a FIFO (named pipe).
     66   BL_FILE_INFO_FIFO = 0x00400000u,
     67   //! A flag describing a socket.
     68   BL_FILE_INFO_SOCKET = 0x00800000u,
     69 
     70   //! A flag describing a hidden file (Windows only).
     71   BL_FILE_INFO_HIDDEN = 0x01000000u,
     72   //! A flag describing a hidden file (Windows only).
     73   BL_FILE_INFO_EXECUTABLE = 0x02000000u,
     74   //! A flag describing an archive (Windows only).
     75   BL_FILE_INFO_ARCHIVE = 0x04000000u,
     76   //! A flag describing a system file (Windows only).
     77   BL_FILE_INFO_SYSTEM = 0x08000000u,
     78 
     79   //! File information is valid (the request succeeded).
     80   BL_FILE_INFO_VALID = 0x80000000u
     81 
     82   BL_FORCE_ENUM_UINT32(BL_FILE_INFO)
     83 };
     84 
     85 //! File open flags, see \ref BLFile::open().
     86 BL_DEFINE_ENUM(BLFileOpenFlags) {
     87   //! No flags.
     88   BL_FILE_OPEN_NO_FLAGS = 0u,
     89 
     90   //! Opens the file for reading.
     91   //!
     92   //! The following system flags are used when opening the file:
     93   //!   - `O_RDONLY` (Posix)
     94   //!   - `GENERIC_READ` (Windows)
     95   BL_FILE_OPEN_READ = 0x00000001u,
     96 
     97   //! Opens the file for writing:
     98   //!
     99   //! The following system flags are used when opening the file:
    100   //!   - `O_WRONLY` (Posix)
    101   //!   - `GENERIC_WRITE` (Windows)
    102   BL_FILE_OPEN_WRITE = 0x00000002u,
    103 
    104   //! Opens the file for reading & writing.
    105   //!
    106   //! The following system flags are used when opening the file:
    107   //!   - `O_RDWR` (Posix)
    108   //!   - `GENERIC_READ | GENERIC_WRITE` (Windows)
    109   BL_FILE_OPEN_RW = 0x00000003u,
    110 
    111   //! Creates the file if it doesn't exist or opens it if it does.
    112   //!
    113   //! The following system flags are used when opening the file:
    114   //!   - `O_CREAT` (Posix)
    115   //!   - `CREATE_ALWAYS` or `OPEN_ALWAYS` depending on other flags (Windows)
    116   BL_FILE_OPEN_CREATE = 0x00000004u,
    117 
    118   //! Opens the file for deleting or renaming (Windows).
    119   //!
    120   //! Adds `DELETE` flag when opening the file to `ACCESS_MASK`.
    121   BL_FILE_OPEN_DELETE = 0x00000008u,
    122 
    123   //! Truncates the file.
    124   //!
    125   //! The following system flags are used when opening the file:
    126   //!   - `O_TRUNC` (Posix)
    127   //!   - `TRUNCATE_EXISTING` (Windows)
    128   BL_FILE_OPEN_TRUNCATE = 0x00000010u,
    129 
    130   //! Opens the file for reading in exclusive mode (Windows).
    131   //!
    132   //! Exclusive mode means to not specify the `FILE_SHARE_READ` option.
    133   BL_FILE_OPEN_READ_EXCLUSIVE = 0x10000000u,
    134 
    135   //! Opens the file for writing in exclusive mode (Windows).
    136   //!
    137   //! Exclusive mode means to not specify the `FILE_SHARE_WRITE` option.
    138   BL_FILE_OPEN_WRITE_EXCLUSIVE = 0x20000000u,
    139 
    140   //! Opens the file for both reading and writing (Windows).
    141   //!
    142   //! This is a combination of both `BL_FILE_OPEN_READ_EXCLUSIVE` and `BL_FILE_OPEN_WRITE_EXCLUSIVE`.
    143   BL_FILE_OPEN_RW_EXCLUSIVE = 0x30000000u,
    144 
    145   //! Creates the file in exclusive mode - fails if the file already exists.
    146   //!
    147   //! The following system flags are used when opening the file:
    148   //!   - `O_EXCL` (Posix)
    149   //!   - `CREATE_NEW` (Windows)
    150   BL_FILE_OPEN_CREATE_EXCLUSIVE = 0x40000000u,
    151 
    152   //! Opens the file for deleting or renaming in exclusive mode (Windows).
    153   //!
    154   //! Exclusive mode means to not specify the `FILE_SHARE_DELETE` option.
    155   BL_FILE_OPEN_DELETE_EXCLUSIVE = 0x80000000u
    156 
    157   BL_FORCE_ENUM_UINT32(BL_FILE_OPEN)
    158 };
    159 
    160 //! File seek mode, see \ref BLFile::seek().
    161 //!
    162 //! \note Seek constants should be compatible with constants used by both POSIX
    163 //! and Windows API.
    164 BL_DEFINE_ENUM(BLFileSeekType) {
    165   //! Seek from the beginning of the file (SEEK_SET).
    166   BL_FILE_SEEK_SET = 0,
    167   //! Seek from the current position (SEEK_CUR).
    168   BL_FILE_SEEK_CUR = 1,
    169   //! Seek from the end of the file (SEEK_END).
    170   BL_FILE_SEEK_END = 2,
    171 
    172   //! Maximum value of `BLFileSeekType`.
    173   BL_FILE_SEEK_MAX_VALUE = 3
    174 
    175   BL_FORCE_ENUM_UINT32(BL_FILE_SEEK)
    176 };
    177 
    178 //! File read flags used by \ref BLFileSystem::read_file().
    179 BL_DEFINE_ENUM(BLFileReadFlags) {
    180   //! No flags.
    181   BL_FILE_READ_NO_FLAGS = 0u,
    182 
    183   //! Use memory mapping to read the content of the file.
    184   //!
    185   //! The destination buffer `BLArray<>` would be configured to use the memory mapped buffer instead of allocating its
    186   //! own.
    187   BL_FILE_READ_MMAP_ENABLED = 0x00000001u,
    188 
    189   //! Avoid memory mapping of small files.
    190   //!
    191   //! The size of small file is determined by Blend2D, however, you should expect it to be 16kB or 64kB depending on
    192   //! host operating system.
    193   BL_FILE_READ_MMAP_AVOID_SMALL = 0x00000002u,
    194 
    195   //! Do not fallback to regular read if memory mapping fails. It's worth noting that memory mapping would fail for
    196   //! files stored on filesystem that is not local (like a mounted network filesystem, etc...).
    197   BL_FILE_READ_MMAP_NO_FALLBACK = 0x00000008u
    198 
    199   BL_FORCE_ENUM_UINT32(BL_FILE_READ)
    200 };
    201 
    202 //! \}
    203 
    204 //! \name BLFile C API Structs
    205 //!
    206 //! \{
    207 
    208 //! A thin abstraction over a native OS file IO [C API].
    209 struct BLFileCore {
    210   //! A file handle - either a file descriptor used by POSIX or file handle used by Windows. On both platforms the
    211   //! handle is always `intptr_t` to make FFI easier (it's basically the size of a pointer / machine register).
    212   //!
    213   //! \note A handle of value `-1` is considered invalid and/or uninitialized. This value also matches Windows API
    214   //! `INVALID_HANDLE_VALUE`, which is also defined to be -1.
    215   intptr_t handle;
    216 };
    217 
    218 //! \}
    219 
    220 //! \name BLFileInfo Structs
    221 //!
    222 //! \{
    223 
    224 //! File information.
    225 struct BLFileInfo {
    226   //! \name Members
    227   //! \{
    228 
    229   uint64_t size;
    230   int64_t modified_time;
    231   BLFileInfoFlags flags;
    232   uint32_t uid;
    233   uint32_t gid;
    234   uint32_t reserved[5];
    235 
    236   //! \}
    237 
    238 #if defined(__cplusplus)
    239 
    240   //! \name Accessors
    241   //! \{
    242 
    243   //! Tests whether the file information has the given `flag` set in `flags`.
    244   BL_INLINE_NODEBUG bool has_flag(BLFileInfoFlags flag) const noexcept { return (flags & flag) != 0; }
    245 
    246   BL_INLINE_NODEBUG bool has_owner_r() const noexcept { return has_flag(BL_FILE_INFO_OWNER_R); }
    247   BL_INLINE_NODEBUG bool has_owner_w() const noexcept { return has_flag(BL_FILE_INFO_OWNER_W); }
    248   BL_INLINE_NODEBUG bool has_owner_x() const noexcept { return has_flag(BL_FILE_INFO_OWNER_X); }
    249 
    250   BL_INLINE_NODEBUG bool has_group_r() const noexcept { return has_flag(BL_FILE_INFO_GROUP_R); }
    251   BL_INLINE_NODEBUG bool has_group_w() const noexcept { return has_flag(BL_FILE_INFO_GROUP_W); }
    252   BL_INLINE_NODEBUG bool has_group_x() const noexcept { return has_flag(BL_FILE_INFO_GROUP_X); }
    253 
    254   BL_INLINE_NODEBUG bool has_other_r() const noexcept { return has_flag(BL_FILE_INFO_OTHER_R); }
    255   BL_INLINE_NODEBUG bool has_other_w() const noexcept { return has_flag(BL_FILE_INFO_OTHER_W); }
    256   BL_INLINE_NODEBUG bool has_other_x() const noexcept { return has_flag(BL_FILE_INFO_OTHER_X); }
    257 
    258   BL_INLINE_NODEBUG bool has_suid() const noexcept { return has_flag(BL_FILE_INFO_SUID); }
    259   BL_INLINE_NODEBUG bool has_sgid() const noexcept { return has_flag(BL_FILE_INFO_SGID); }
    260 
    261   BL_INLINE_NODEBUG bool is_regular() const noexcept { return has_flag(BL_FILE_INFO_REGULAR); }
    262   BL_INLINE_NODEBUG bool is_directory() const noexcept { return has_flag(BL_FILE_INFO_DIRECTORY); }
    263   BL_INLINE_NODEBUG bool is_symlink() const noexcept { return has_flag(BL_FILE_INFO_SYMLINK); }
    264 
    265   BL_INLINE_NODEBUG bool is_char_device() const noexcept { return has_flag(BL_FILE_INFO_CHAR_DEVICE); }
    266   BL_INLINE_NODEBUG bool is_block_device() const noexcept { return has_flag(BL_FILE_INFO_BLOCK_DEVICE); }
    267   BL_INLINE_NODEBUG bool is_fifo() const noexcept { return has_flag(BL_FILE_INFO_FIFO); }
    268   BL_INLINE_NODEBUG bool is_socket() const noexcept { return has_flag(BL_FILE_INFO_SOCKET); }
    269 
    270   BL_INLINE_NODEBUG bool is_hidden() const noexcept { return has_flag(BL_FILE_INFO_HIDDEN); }
    271   BL_INLINE_NODEBUG bool is_executable() const noexcept { return has_flag(BL_FILE_INFO_EXECUTABLE); }
    272   BL_INLINE_NODEBUG bool is_archive() const noexcept { return has_flag(BL_FILE_INFO_ARCHIVE); }
    273   BL_INLINE_NODEBUG bool is_system() const noexcept { return has_flag(BL_FILE_INFO_SYSTEM); }
    274 
    275   BL_INLINE_NODEBUG bool is_valid() const noexcept { return has_flag(BL_FILE_INFO_VALID); }
    276 
    277   //! \}
    278 
    279 #endif
    280 };
    281 
    282 //! \}
    283 
    284 //! \}
    285 
    286 //! \addtogroup bl_c_api
    287 //! \{
    288 
    289 BL_BEGIN_C_DECLS
    290 
    291 //! \name BLFile C API Functions
    292 //!
    293 //! File read/write functionality is provided by \ref BLFileCore in C API and wrapped by \ref BLFile in C++ API.
    294 //!
    295 //! \{
    296 
    297 BL_API BLResult BL_CDECL bl_file_init(BLFileCore* self) BL_NOEXCEPT_C;
    298 BL_API BLResult BL_CDECL bl_file_reset(BLFileCore* self) BL_NOEXCEPT_C;
    299 BL_API BLResult BL_CDECL bl_file_open(BLFileCore* self, const char* file_name, BLFileOpenFlags open_flags) BL_NOEXCEPT_C;
    300 BL_API BLResult BL_CDECL bl_file_close(BLFileCore* self) BL_NOEXCEPT_C;
    301 BL_API BLResult BL_CDECL bl_file_seek(BLFileCore* self, int64_t offset, BLFileSeekType seek_type, int64_t* position_out) BL_NOEXCEPT_C;
    302 BL_API BLResult BL_CDECL bl_file_read(BLFileCore* self, void* buffer, size_t n, size_t* bytes_read_out) BL_NOEXCEPT_C;
    303 BL_API BLResult BL_CDECL bl_file_write(BLFileCore* self, const void* buffer, size_t n, size_t* bytes_written_out) BL_NOEXCEPT_C;
    304 BL_API BLResult BL_CDECL bl_file_truncate(BLFileCore* self, int64_t max_size) BL_NOEXCEPT_C;
    305 BL_API BLResult BL_CDECL bl_file_get_info(BLFileCore* self, BLFileInfo* info_out) BL_NOEXCEPT_C;
    306 BL_API BLResult BL_CDECL bl_file_get_size(BLFileCore* self, uint64_t* file_size_out) BL_NOEXCEPT_C;
    307 
    308 //! \}
    309 
    310 //! \name BLFileSystem C API Functions
    311 //!
    312 //! \{
    313 
    314 BL_API BLResult BL_CDECL bl_file_system_get_info(const char* file_name, BLFileInfo* info_out) BL_NOEXCEPT_C;
    315 BL_API BLResult BL_CDECL bl_file_system_read_file(const char* file_name, BLArrayCore* dst, size_t max_size, BLFileReadFlags read_flags) BL_NOEXCEPT_C;
    316 BL_API BLResult BL_CDECL bl_file_system_write_file(const char* file_name, const void* data, size_t size, size_t* bytes_written_out) BL_NOEXCEPT_C;
    317 
    318 //! \}
    319 
    320 BL_END_C_DECLS
    321 
    322 //! \}
    323 
    324 //! \addtogroup bl_filesystem
    325 //! \{
    326 
    327 #ifdef __cplusplus
    328 //! \name BLFile C++ API
    329 //! \{
    330 
    331 //! A thin abstraction over a native OS file IO [C++ API].
    332 //!
    333 //! A thin wrapper around a native OS file support. The file handle is always `intptr_t` and it refers to either
    334 //! a file descriptor on POSIX targets and file handle on Windows targets.
    335 class BLFile final : public BLFileCore {
    336 public:
    337   // Prevent copy-constructor and copy-assignment.
    338   BL_INLINE_NODEBUG BLFile(const BLFile& other) noexcept = delete;
    339   BL_INLINE_NODEBUG BLFile& operator=(const BLFile& other) noexcept = delete;
    340 
    341   //! \name Construction & Destruction
    342   //! \{
    343 
    344   //! Creates an empty file instance, which doesn't represent any open file.
    345   //!
    346   //! \note The internal file handle of non-opened files is set to -1.
    347   BL_INLINE_NODEBUG BLFile() noexcept
    348     : BLFileCore { -1 } {}
    349 
    350   //! Move constructor - copies file descriptor from `other` to this instance and resets `other` to a default
    351   //! constructed state.
    352   BL_INLINE_NODEBUG BLFile(BLFile&& other) noexcept {
    353     intptr_t h = other.handle;
    354     other.handle = -1;
    355     handle = h;
    356   }
    357 
    358   //! Creates a file instance from an existing file `handle`, which either represents a file descriptor or Windows
    359   //! `HANDLE` (if compiled for Windows platform).
    360   BL_INLINE_NODEBUG explicit BLFile(intptr_t handle) noexcept
    361     : BLFileCore { handle } {}
    362 
    363   BL_INLINE_NODEBUG BLFile& operator=(BLFile&& other) noexcept {
    364     intptr_t h = other.handle;
    365     other.handle = -1;
    366 
    367     this->close();
    368     this->handle = h;
    369 
    370     return *this;
    371   }
    372 
    373   //! Destroys this file instance - closes the file descriptor or handle when it's referencing an open file.
    374   BL_INLINE_NODEBUG ~BLFile() noexcept { bl_file_reset(this); }
    375 
    376   //! \}
    377 
    378   //! \name Common Functionality
    379   //! \{
    380 
    381   BL_INLINE_NODEBUG void swap(BLFile& other) noexcept { BLInternal::swap(this->handle, other.handle); }
    382 
    383   //! \}
    384 
    385   //! \name Interface
    386   //! \{
    387 
    388   //! Tests whether the file is open.
    389   BL_INLINE_NODEBUG bool is_open() const noexcept { return handle != -1; }
    390 
    391   //! Attempts to open a file specified by `file_name` with the given `open_flags`.
    392   BL_INLINE_NODEBUG BLResult open(const char* file_name, BLFileOpenFlags open_flags) noexcept {
    393     return bl_file_open(this, file_name, open_flags);
    394   }
    395 
    396   //! Closes the file (if open) and sets the file handle to -1.
    397   BL_INLINE_NODEBUG BLResult close() noexcept {
    398     return bl_file_close(this);
    399   }
    400 
    401   //! Sets the file position of the file to the given `offset` by using the specified `seek_type`.
    402   BL_INLINE_NODEBUG BLResult seek(int64_t offset, BLFileSeekType seek_type) noexcept {
    403     int64_t position_out;
    404     return bl_file_seek(this, offset, seek_type, &position_out);
    405   }
    406 
    407   //! Sets the file position of the file to the given `offset` by using the specified `seek_type` and writes the new
    408   //! position into `position_out` output parameter.
    409   BL_INLINE_NODEBUG BLResult seek(int64_t offset, BLFileSeekType seek_type, int64_t* position_out) noexcept {
    410     return bl_file_seek(this, offset, seek_type, position_out);
    411   }
    412 
    413   //! Reads `n` bytes from the file into the given `buffer` and stores the number of bytes actually read into
    414   //! the `bytes_read_out` output parameter.
    415   BL_INLINE_NODEBUG BLResult read(void* buffer, size_t n, size_t* bytes_read_out) noexcept {
    416     return bl_file_read(this, buffer, n, bytes_read_out);
    417   }
    418 
    419   //! Writes `n` bytes to the file from the given `buffer` and stores the number of bytes actually written into
    420   //! the `bytes_read_out` output parameter.
    421   BL_INLINE_NODEBUG BLResult write(const void* buffer, size_t n, size_t* bytes_written_out) noexcept {
    422     return bl_file_write(this, buffer, n, bytes_written_out);
    423   }
    424 
    425   //! Truncates the file to the given maximum size `max_size`.
    426   BL_INLINE_NODEBUG BLResult truncate(int64_t max_size) noexcept {
    427     return bl_file_truncate(this, max_size);
    428   }
    429 
    430   //! Queries an information of the file and stores it to `info_out`.
    431   BL_INLINE_NODEBUG BLResult get_info(BLFileInfo* info_out) noexcept {
    432     return bl_file_get_info(this, info_out);
    433   }
    434 
    435   //! Queries a size of the file and stores it to `size_out`.
    436   BL_INLINE_NODEBUG BLResult get_size(uint64_t* size_out) noexcept {
    437     return bl_file_get_size(this, size_out);
    438   }
    439 
    440   //! \}
    441 };
    442 
    443 //! File-system utilities.
    444 namespace BLFileSystem {
    445 
    446 static BL_INLINE_NODEBUG BLResult file_info(const char* file_name, BLFileInfo* info_out) noexcept {
    447   return bl_file_system_get_info(file_name, info_out);
    448 }
    449 
    450 //! Reads a file into the `dst` buffer.
    451 //!
    452 //! Optionally you can set `max_size` to non-zero value that would restrict the maximum bytes to read to such value.
    453 //! In addition, `read_flags` can be used to enable file mapping. See \ref BLFileReadFlags for more details.
    454 static BL_INLINE_NODEBUG BLResult read_file(const char* file_name, BLArray<uint8_t>& dst, size_t max_size = 0, BLFileReadFlags read_flags = BL_FILE_READ_NO_FLAGS) noexcept {
    455   return bl_file_system_read_file(file_name, &dst, max_size, read_flags);
    456 }
    457 
    458 static BL_INLINE_NODEBUG BLResult write_file(const char* file_name, const void* data, size_t size) noexcept {
    459   size_t bytes_written_out;
    460   return bl_file_system_write_file(file_name, data, size, &bytes_written_out);
    461 }
    462 
    463 static BL_INLINE_NODEBUG BLResult write_file(const char* file_name, const void* data, size_t size, size_t* bytes_written_out) noexcept {
    464   return bl_file_system_write_file(file_name, data, size, bytes_written_out);
    465 }
    466 
    467 static BL_INLINE_NODEBUG BLResult write_file(const char* file_name, const BLArrayView<uint8_t>& view) noexcept {
    468   return write_file(file_name, view.data, view.size);
    469 }
    470 
    471 static BL_INLINE_NODEBUG BLResult write_file(const char* file_name, const BLArrayView<uint8_t>& view, size_t* bytes_written_out) noexcept {
    472   return write_file(file_name, view.data, view.size, bytes_written_out);
    473 }
    474 
    475 static BL_INLINE_NODEBUG BLResult write_file(const char* file_name, const BLArray<uint8_t>& array) noexcept {
    476   return write_file(file_name, array.view());
    477 }
    478 
    479 static BL_INLINE_NODEBUG BLResult write_file(const char* file_name, const BLArray<uint8_t>& array, size_t* bytes_written_out) noexcept {
    480   return write_file(file_name, array.view(), bytes_written_out);
    481 }
    482 
    483 } // {BLFileSystem}
    484 
    485 //! \}
    486 #endif
    487 
    488 //! \}
    489 
    490 #endif // BLEND2D_FILESYSTEM_H_INCLUDED