| 1 | /**************************************************************************/ |
| 2 | /* file_access.h */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 10 | /* */ |
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
| 12 | /* a copy of this software and associated documentation files (the */ |
| 13 | /* "Software"), to deal in the Software without restriction, including */ |
| 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
| 16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
| 17 | /* the following conditions: */ |
| 18 | /* */ |
| 19 | /* The above copyright notice and this permission notice shall be */ |
| 20 | /* included in all copies or substantial portions of the Software. */ |
| 21 | /* */ |
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 29 | /**************************************************************************/ |
| 30 | |
| 31 | #ifndef FILE_ACCESS_H |
| 32 | #define FILE_ACCESS_H |
| 33 | |
| 34 | #include "core/io/compression.h" |
| 35 | #include "core/math/math_defs.h" |
| 36 | #include "core/object/ref_counted.h" |
| 37 | #include "core/os/memory.h" |
| 38 | #include "core/string/ustring.h" |
| 39 | #include "core/typedefs.h" |
| 40 | |
| 41 | /** |
| 42 | * Multi-Platform abstraction for accessing to files. |
| 43 | */ |
| 44 | |
| 45 | class FileAccess : public RefCounted { |
| 46 | GDCLASS(FileAccess, RefCounted); |
| 47 | |
| 48 | public: |
| 49 | enum AccessType { |
| 50 | ACCESS_RESOURCES, |
| 51 | ACCESS_USERDATA, |
| 52 | ACCESS_FILESYSTEM, |
| 53 | ACCESS_MAX |
| 54 | }; |
| 55 | |
| 56 | enum ModeFlags { |
| 57 | READ = 1, |
| 58 | WRITE = 2, |
| 59 | READ_WRITE = 3, |
| 60 | WRITE_READ = 7, |
| 61 | }; |
| 62 | |
| 63 | enum UnixPermissionFlags { |
| 64 | UNIX_EXECUTE_OTHER = 0x001, |
| 65 | UNIX_WRITE_OTHER = 0x002, |
| 66 | UNIX_READ_OTHER = 0x004, |
| 67 | UNIX_EXECUTE_GROUP = 0x008, |
| 68 | UNIX_WRITE_GROUP = 0x010, |
| 69 | UNIX_READ_GROUP = 0x020, |
| 70 | UNIX_EXECUTE_OWNER = 0x040, |
| 71 | UNIX_WRITE_OWNER = 0x080, |
| 72 | UNIX_READ_OWNER = 0x100, |
| 73 | UNIX_RESTRICTED_DELETE = 0x200, |
| 74 | UNIX_SET_GROUP_ID = 0x400, |
| 75 | UNIX_SET_USER_ID = 0x800, |
| 76 | }; |
| 77 | |
| 78 | enum CompressionMode { |
| 79 | COMPRESSION_FASTLZ = Compression::MODE_FASTLZ, |
| 80 | COMPRESSION_DEFLATE = Compression::MODE_DEFLATE, |
| 81 | COMPRESSION_ZSTD = Compression::MODE_ZSTD, |
| 82 | COMPRESSION_GZIP = Compression::MODE_GZIP, |
| 83 | COMPRESSION_BROTLI = Compression::MODE_BROTLI, |
| 84 | }; |
| 85 | |
| 86 | typedef void (*FileCloseFailNotify)(const String &); |
| 87 | |
| 88 | typedef Ref<FileAccess> (*CreateFunc)(); |
| 89 | bool big_endian = false; |
| 90 | bool real_is_double = false; |
| 91 | |
| 92 | virtual BitField<UnixPermissionFlags> _get_unix_permissions(const String &p_file) = 0; |
| 93 | virtual Error _set_unix_permissions(const String &p_file, BitField<UnixPermissionFlags> p_permissions) = 0; |
| 94 | |
| 95 | virtual bool _get_hidden_attribute(const String &p_file) = 0; |
| 96 | virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) = 0; |
| 97 | virtual bool _get_read_only_attribute(const String &p_file) = 0; |
| 98 | virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) = 0; |
| 99 | |
| 100 | protected: |
| 101 | static void _bind_methods(); |
| 102 | |
| 103 | AccessType get_access_type() const; |
| 104 | virtual String fix_path(const String &p_path) const; |
| 105 | virtual Error open_internal(const String &p_path, int p_mode_flags) = 0; ///< open a file |
| 106 | virtual uint64_t _get_modified_time(const String &p_file) = 0; |
| 107 | virtual void _set_access_type(AccessType p_access); |
| 108 | |
| 109 | static FileCloseFailNotify close_fail_notify; |
| 110 | |
| 111 | private: |
| 112 | static bool backup_save; |
| 113 | thread_local static Error last_file_open_error; |
| 114 | |
| 115 | AccessType _access_type = ACCESS_FILESYSTEM; |
| 116 | static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */ |
| 117 | template <class T> |
| 118 | static Ref<FileAccess> _create_builtin() { |
| 119 | return memnew(T); |
| 120 | } |
| 121 | |
| 122 | static Ref<FileAccess> _open(const String &p_path, ModeFlags p_mode_flags); |
| 123 | |
| 124 | public: |
| 125 | static void set_file_close_fail_notify_callback(FileCloseFailNotify p_cbk) { close_fail_notify = p_cbk; } |
| 126 | |
| 127 | virtual bool is_open() const = 0; ///< true when file is open |
| 128 | |
| 129 | virtual String get_path() const { return "" ; } /// returns the path for the current open file |
| 130 | virtual String get_path_absolute() const { return "" ; } /// returns the absolute path for the current open file |
| 131 | |
| 132 | virtual void seek(uint64_t p_position) = 0; ///< seek to a given position |
| 133 | virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file with negative offset |
| 134 | virtual uint64_t get_position() const = 0; ///< get position in the file |
| 135 | virtual uint64_t get_length() const = 0; ///< get size of the file |
| 136 | |
| 137 | virtual bool eof_reached() const = 0; ///< reading passed EOF |
| 138 | |
| 139 | virtual uint8_t get_8() const = 0; ///< get a byte |
| 140 | virtual uint16_t get_16() const; ///< get 16 bits uint |
| 141 | virtual uint32_t get_32() const; ///< get 32 bits uint |
| 142 | virtual uint64_t get_64() const; ///< get 64 bits uint |
| 143 | |
| 144 | virtual float get_float() const; |
| 145 | virtual double get_double() const; |
| 146 | virtual real_t get_real() const; |
| 147 | |
| 148 | Variant get_var(bool p_allow_objects = false) const; |
| 149 | |
| 150 | virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes |
| 151 | Vector<uint8_t> get_buffer(int64_t p_length) const; |
| 152 | virtual String get_line() const; |
| 153 | virtual String get_token() const; |
| 154 | virtual Vector<String> get_csv_line(const String &p_delim = "," ) const; |
| 155 | String get_as_text(bool p_skip_cr = false) const; |
| 156 | virtual String get_as_utf8_string(bool p_skip_cr = false) const; |
| 157 | |
| 158 | /** |
| 159 | * Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) |
| 160 | * It's not about the current CPU type but file formats. |
| 161 | * This flag gets reset to `false` (little endian) on each open. |
| 162 | */ |
| 163 | virtual void set_big_endian(bool p_big_endian) { big_endian = p_big_endian; } |
| 164 | inline bool is_big_endian() const { return big_endian; } |
| 165 | |
| 166 | virtual Error get_error() const = 0; ///< get last error |
| 167 | |
| 168 | virtual void flush() = 0; |
| 169 | virtual void store_8(uint8_t p_dest) = 0; ///< store a byte |
| 170 | virtual void store_16(uint16_t p_dest); ///< store 16 bits uint |
| 171 | virtual void store_32(uint32_t p_dest); ///< store 32 bits uint |
| 172 | virtual void store_64(uint64_t p_dest); ///< store 64 bits uint |
| 173 | |
| 174 | virtual void store_float(float p_dest); |
| 175 | virtual void store_double(double p_dest); |
| 176 | virtual void store_real(real_t p_real); |
| 177 | |
| 178 | virtual void store_string(const String &p_string); |
| 179 | virtual void store_line(const String &p_line); |
| 180 | virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = "," ); |
| 181 | |
| 182 | virtual void store_pascal_string(const String &p_string); |
| 183 | virtual String get_pascal_string(); |
| 184 | |
| 185 | virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes |
| 186 | void store_buffer(const Vector<uint8_t> &p_buffer); |
| 187 | |
| 188 | void store_var(const Variant &p_var, bool p_full_objects = false); |
| 189 | |
| 190 | virtual void close() = 0; |
| 191 | |
| 192 | virtual bool file_exists(const String &p_name) = 0; ///< return true if a file exists |
| 193 | |
| 194 | virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType |
| 195 | |
| 196 | static Ref<FileAccess> create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files. |
| 197 | static Ref<FileAccess> create_for_path(const String &p_path); |
| 198 | static Ref<FileAccess> open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files. |
| 199 | |
| 200 | static Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key); |
| 201 | static Ref<FileAccess> open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass); |
| 202 | static Ref<FileAccess> open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode = COMPRESSION_FASTLZ); |
| 203 | static Error get_open_error(); |
| 204 | |
| 205 | static CreateFunc get_create_func(AccessType p_access); |
| 206 | static bool exists(const String &p_name); ///< return true if a file exists |
| 207 | static uint64_t get_modified_time(const String &p_file); |
| 208 | static BitField<FileAccess::UnixPermissionFlags> get_unix_permissions(const String &p_file); |
| 209 | static Error set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions); |
| 210 | |
| 211 | static bool get_hidden_attribute(const String &p_file); |
| 212 | static Error set_hidden_attribute(const String &p_file, bool p_hidden); |
| 213 | static bool get_read_only_attribute(const String &p_file); |
| 214 | static Error set_read_only_attribute(const String &p_file, bool p_ro); |
| 215 | |
| 216 | static void set_backup_save(bool p_enable) { backup_save = p_enable; }; |
| 217 | static bool is_backup_save_enabled() { return backup_save; }; |
| 218 | |
| 219 | static String get_md5(const String &p_file); |
| 220 | static String get_sha256(const String &p_file); |
| 221 | static String get_multiple_md5(const Vector<String> &p_file); |
| 222 | |
| 223 | static Vector<uint8_t> get_file_as_bytes(const String &p_path, Error *r_error = nullptr); |
| 224 | static String get_file_as_string(const String &p_path, Error *r_error = nullptr); |
| 225 | |
| 226 | static PackedByteArray _get_file_as_bytes(const String &p_path) { return get_file_as_bytes(p_path); } |
| 227 | static String _get_file_as_string(const String &p_path) { return get_file_as_string(p_path); }; |
| 228 | |
| 229 | template <class T> |
| 230 | static void make_default(AccessType p_access) { |
| 231 | create_func[p_access] = _create_builtin<T>; |
| 232 | } |
| 233 | |
| 234 | FileAccess() {} |
| 235 | virtual ~FileAccess() {} |
| 236 | }; |
| 237 | |
| 238 | VARIANT_ENUM_CAST(FileAccess::CompressionMode); |
| 239 | VARIANT_ENUM_CAST(FileAccess::ModeFlags); |
| 240 | VARIANT_BITFIELD_CAST(FileAccess::UnixPermissionFlags); |
| 241 | |
| 242 | #endif // FILE_ACCESS_H |
| 243 | |