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 | |